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_SetValuesBatch; 40 PetscLogEvent MAT_ViennaCLCopyToGPU; 41 PetscLogEvent MAT_CUDACopyToGPU; 42 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU; 43 PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom; 44 PetscLogEvent MAT_FactorFactS, MAT_FactorInvS; 45 PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights; 46 PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR; 47 48 const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL}; 49 50 /*@ 51 MatSetRandom - Sets all components of a matrix to random numbers. 52 53 Logically Collective 54 55 Input Parameters: 56 + x - the matrix 57 - rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or `NULL` and 58 it will create one internally. 59 60 Example: 61 .vb 62 PetscRandomCreate(PETSC_COMM_WORLD,&rctx); 63 MatSetRandom(x,rctx); 64 PetscRandomDestroy(rctx); 65 .ve 66 67 Level: intermediate 68 69 Notes: 70 For sparse matrices that have been preallocated but not been assembled it randomly selects appropriate locations, 71 72 for sparse matrices that already have locations it fills the locations with random numbers. 73 74 It generates an error if used on sparse matrices that have not been preallocated. 75 76 .seealso: [](ch_matrices), `Mat`, `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomDestroy()` 77 @*/ 78 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx) 79 { 80 PetscRandom randObj = NULL; 81 82 PetscFunctionBegin; 83 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 84 if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2); 85 PetscValidType(x, 1); 86 MatCheckPreallocated(x, 1); 87 88 if (!rctx) { 89 MPI_Comm comm; 90 PetscCall(PetscObjectGetComm((PetscObject)x, &comm)); 91 PetscCall(PetscRandomCreate(comm, &randObj)); 92 PetscCall(PetscRandomSetType(randObj, x->defaultrandtype)); 93 PetscCall(PetscRandomSetFromOptions(randObj)); 94 rctx = randObj; 95 } 96 PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0)); 97 PetscUseTypeMethod(x, setrandom, rctx); 98 PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0)); 99 100 PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY)); 101 PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY)); 102 PetscCall(PetscRandomDestroy(&randObj)); 103 PetscFunctionReturn(PETSC_SUCCESS); 104 } 105 106 /*@ 107 MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in 108 109 Logically Collective 110 111 Input Parameter: 112 . mat - the factored matrix 113 114 Output Parameters: 115 + pivot - the pivot value computed 116 - row - the row that the zero pivot occurred. This row value must be interpreted carefully due to row reorderings and which processes 117 the share the matrix 118 119 Level: advanced 120 121 Notes: 122 This routine does not work for factorizations done with external packages. 123 124 This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT` 125 126 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 127 128 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, 129 `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, 130 `MAT_FACTOR_NUMERIC_ZEROPIVOT` 131 @*/ 132 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row) 133 { 134 PetscFunctionBegin; 135 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 136 PetscAssertPointer(pivot, 2); 137 PetscAssertPointer(row, 3); 138 *pivot = mat->factorerror_zeropivot_value; 139 *row = mat->factorerror_zeropivot_row; 140 PetscFunctionReturn(PETSC_SUCCESS); 141 } 142 143 /*@ 144 MatFactorGetError - gets the error code from a factorization 145 146 Logically Collective 147 148 Input Parameter: 149 . mat - the factored matrix 150 151 Output Parameter: 152 . err - the error code 153 154 Level: advanced 155 156 Note: 157 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 158 159 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, 160 `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, `MatFactorError` 161 @*/ 162 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err) 163 { 164 PetscFunctionBegin; 165 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 166 PetscAssertPointer(err, 2); 167 *err = mat->factorerrortype; 168 PetscFunctionReturn(PETSC_SUCCESS); 169 } 170 171 /*@ 172 MatFactorClearError - clears the error code in a factorization 173 174 Logically Collective 175 176 Input Parameter: 177 . mat - the factored matrix 178 179 Level: developer 180 181 Note: 182 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 183 184 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`, 185 `MatGetErrorCode()`, `MatFactorError` 186 @*/ 187 PetscErrorCode MatFactorClearError(Mat mat) 188 { 189 PetscFunctionBegin; 190 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 191 mat->factorerrortype = MAT_FACTOR_NOERROR; 192 mat->factorerror_zeropivot_value = 0.0; 193 mat->factorerror_zeropivot_row = 0; 194 PetscFunctionReturn(PETSC_SUCCESS); 195 } 196 197 PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero) 198 { 199 Vec r, l; 200 const PetscScalar *al; 201 PetscInt i, nz, gnz, N, n; 202 203 PetscFunctionBegin; 204 PetscCall(MatCreateVecs(mat, &r, &l)); 205 if (!cols) { /* nonzero rows */ 206 PetscCall(MatGetSize(mat, &N, NULL)); 207 PetscCall(MatGetLocalSize(mat, &n, NULL)); 208 PetscCall(VecSet(l, 0.0)); 209 PetscCall(VecSetRandom(r, NULL)); 210 PetscCall(MatMult(mat, r, l)); 211 PetscCall(VecGetArrayRead(l, &al)); 212 } else { /* nonzero columns */ 213 PetscCall(MatGetSize(mat, NULL, &N)); 214 PetscCall(MatGetLocalSize(mat, NULL, &n)); 215 PetscCall(VecSet(r, 0.0)); 216 PetscCall(VecSetRandom(l, NULL)); 217 PetscCall(MatMultTranspose(mat, l, r)); 218 PetscCall(VecGetArrayRead(r, &al)); 219 } 220 if (tol <= 0.0) { 221 for (i = 0, nz = 0; i < n; i++) 222 if (al[i] != 0.0) nz++; 223 } else { 224 for (i = 0, nz = 0; i < n; i++) 225 if (PetscAbsScalar(al[i]) > tol) nz++; 226 } 227 PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 228 if (gnz != N) { 229 PetscInt *nzr; 230 PetscCall(PetscMalloc1(nz, &nzr)); 231 if (nz) { 232 if (tol < 0) { 233 for (i = 0, nz = 0; i < n; i++) 234 if (al[i] != 0.0) nzr[nz++] = i; 235 } else { 236 for (i = 0, nz = 0; i < n; i++) 237 if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i; 238 } 239 } 240 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero)); 241 } else *nonzero = NULL; 242 if (!cols) { /* nonzero rows */ 243 PetscCall(VecRestoreArrayRead(l, &al)); 244 } else { 245 PetscCall(VecRestoreArrayRead(r, &al)); 246 } 247 PetscCall(VecDestroy(&l)); 248 PetscCall(VecDestroy(&r)); 249 PetscFunctionReturn(PETSC_SUCCESS); 250 } 251 252 /*@ 253 MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix 254 255 Input Parameter: 256 . mat - the matrix 257 258 Output Parameter: 259 . keptrows - the rows that are not completely zero 260 261 Level: intermediate 262 263 Note: 264 `keptrows` is set to `NULL` if all rows are nonzero. 265 266 .seealso: [](ch_matrices), `Mat`, `MatFindZeroRows()` 267 @*/ 268 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows) 269 { 270 PetscFunctionBegin; 271 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 272 PetscValidType(mat, 1); 273 PetscAssertPointer(keptrows, 2); 274 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 275 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 276 if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows); 277 else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows)); 278 PetscFunctionReturn(PETSC_SUCCESS); 279 } 280 281 /*@ 282 MatFindZeroRows - Locate all rows that are completely zero in the matrix 283 284 Input Parameter: 285 . mat - the matrix 286 287 Output Parameter: 288 . zerorows - the rows that are completely zero 289 290 Level: intermediate 291 292 Note: 293 `zerorows` is set to `NULL` if no rows are zero. 294 295 .seealso: [](ch_matrices), `Mat`, `MatFindNonzeroRows()` 296 @*/ 297 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows) 298 { 299 IS keptrows; 300 PetscInt m, n; 301 302 PetscFunctionBegin; 303 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 304 PetscValidType(mat, 1); 305 PetscAssertPointer(zerorows, 2); 306 PetscCall(MatFindNonzeroRows(mat, &keptrows)); 307 /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows. 308 In keeping with this convention, we set zerorows to NULL if there are no zero 309 rows. */ 310 if (keptrows == NULL) { 311 *zerorows = NULL; 312 } else { 313 PetscCall(MatGetOwnershipRange(mat, &m, &n)); 314 PetscCall(ISComplement(keptrows, m, n, zerorows)); 315 PetscCall(ISDestroy(&keptrows)); 316 } 317 PetscFunctionReturn(PETSC_SUCCESS); 318 } 319 320 /*@ 321 MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling 322 323 Not Collective 324 325 Input Parameter: 326 . A - the matrix 327 328 Output Parameter: 329 . a - the diagonal part (which is a SEQUENTIAL matrix) 330 331 Level: advanced 332 333 Notes: 334 See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix. 335 336 Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation. 337 338 .seealso: [](ch_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ` 339 @*/ 340 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a) 341 { 342 PetscFunctionBegin; 343 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 344 PetscValidType(A, 1); 345 PetscAssertPointer(a, 2); 346 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 347 if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a); 348 else { 349 PetscMPIInt size; 350 351 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 352 PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name); 353 *a = A; 354 } 355 PetscFunctionReturn(PETSC_SUCCESS); 356 } 357 358 /*@ 359 MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries. 360 361 Collective 362 363 Input Parameter: 364 . mat - the matrix 365 366 Output Parameter: 367 . trace - the sum of the diagonal entries 368 369 Level: advanced 370 371 .seealso: [](ch_matrices), `Mat` 372 @*/ 373 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace) 374 { 375 Vec diag; 376 377 PetscFunctionBegin; 378 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 379 PetscAssertPointer(trace, 2); 380 PetscCall(MatCreateVecs(mat, &diag, NULL)); 381 PetscCall(MatGetDiagonal(mat, diag)); 382 PetscCall(VecSum(diag, trace)); 383 PetscCall(VecDestroy(&diag)); 384 PetscFunctionReturn(PETSC_SUCCESS); 385 } 386 387 /*@ 388 MatRealPart - Zeros out the imaginary part of the matrix 389 390 Logically Collective 391 392 Input Parameter: 393 . mat - the matrix 394 395 Level: advanced 396 397 .seealso: [](ch_matrices), `Mat`, `MatImaginaryPart()` 398 @*/ 399 PetscErrorCode MatRealPart(Mat mat) 400 { 401 PetscFunctionBegin; 402 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 403 PetscValidType(mat, 1); 404 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 405 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 406 MatCheckPreallocated(mat, 1); 407 PetscUseTypeMethod(mat, realpart); 408 PetscFunctionReturn(PETSC_SUCCESS); 409 } 410 411 /*@C 412 MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix 413 414 Collective 415 416 Input Parameter: 417 . mat - the matrix 418 419 Output Parameters: 420 + nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each block) 421 - ghosts - the global indices of the ghost points 422 423 Level: advanced 424 425 Note: 426 `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()` 427 428 .seealso: [](ch_matrices), `Mat`, `VecCreateGhost()` 429 @*/ 430 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[]) 431 { 432 PetscFunctionBegin; 433 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 434 PetscValidType(mat, 1); 435 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 436 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 437 if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts); 438 else { 439 if (nghosts) *nghosts = 0; 440 if (ghosts) *ghosts = NULL; 441 } 442 PetscFunctionReturn(PETSC_SUCCESS); 443 } 444 445 /*@ 446 MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part 447 448 Logically Collective 449 450 Input Parameter: 451 . mat - the matrix 452 453 Level: advanced 454 455 .seealso: [](ch_matrices), `Mat`, `MatRealPart()` 456 @*/ 457 PetscErrorCode MatImaginaryPart(Mat mat) 458 { 459 PetscFunctionBegin; 460 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 461 PetscValidType(mat, 1); 462 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 463 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 464 MatCheckPreallocated(mat, 1); 465 PetscUseTypeMethod(mat, imaginarypart); 466 PetscFunctionReturn(PETSC_SUCCESS); 467 } 468 469 /*@ 470 MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices) 471 472 Not Collective 473 474 Input Parameter: 475 . mat - the matrix 476 477 Output Parameters: 478 + missing - is any diagonal missing 479 - dd - first diagonal entry that is missing (optional) on this process 480 481 Level: advanced 482 483 .seealso: [](ch_matrices), `Mat` 484 @*/ 485 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd) 486 { 487 PetscFunctionBegin; 488 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 489 PetscValidType(mat, 1); 490 PetscAssertPointer(missing, 2); 491 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name); 492 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 493 PetscUseTypeMethod(mat, missingdiagonal, missing, dd); 494 PetscFunctionReturn(PETSC_SUCCESS); 495 } 496 497 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 498 /*@C 499 MatGetRow - Gets a row of a matrix. You MUST call `MatRestoreRow()` 500 for each row that you get to ensure that your application does 501 not bleed memory. 502 503 Not Collective 504 505 Input Parameters: 506 + mat - the matrix 507 - row - the row to get 508 509 Output Parameters: 510 + ncols - if not `NULL`, the number of nonzeros in the row 511 . cols - if not `NULL`, the column numbers 512 - vals - if not `NULL`, the values 513 514 Level: advanced 515 516 Notes: 517 This routine is provided for people who need to have direct access 518 to the structure of a matrix. We hope that we provide enough 519 high-level matrix routines that few users will need it. 520 521 `MatGetRow()` always returns 0-based column indices, regardless of 522 whether the internal representation is 0-based (default) or 1-based. 523 524 For better efficiency, set cols and/or vals to `NULL` if you do 525 not wish to extract these quantities. 526 527 The user can only examine the values extracted with `MatGetRow()`; 528 the values cannot be altered. To change the matrix entries, one 529 must use `MatSetValues()`. 530 531 You can only have one call to `MatGetRow()` outstanding for a particular 532 matrix at a time, per processor. `MatGetRow()` can only obtain rows 533 associated with the given processor, it cannot get rows from the 534 other processors; for that we suggest using `MatCreateSubMatrices()`, then 535 MatGetRow() on the submatrix. The row index passed to `MatGetRow()` 536 is in the global number of rows. 537 538 Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix. 539 540 Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly. 541 542 Fortran Notes: 543 The calling sequence is 544 .vb 545 MatGetRow(matrix,row,ncols,cols,values,ierr) 546 Mat matrix (input) 547 integer row (input) 548 integer ncols (output) 549 integer cols(maxcols) (output) 550 double precision (or double complex) values(maxcols) output 551 .ve 552 where maxcols >= maximum nonzeros in any row of the matrix. 553 554 Caution: 555 Do not try to change the contents of the output arrays (`cols` and `vals`). 556 In some cases, this may corrupt the matrix. 557 558 .seealso: [](ch_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()` 559 @*/ 560 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 561 { 562 PetscInt incols; 563 564 PetscFunctionBegin; 565 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 566 PetscValidType(mat, 1); 567 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 568 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 569 MatCheckPreallocated(mat, 1); 570 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); 571 PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0)); 572 PetscUseTypeMethod(mat, getrow, row, &incols, (PetscInt **)cols, (PetscScalar **)vals); 573 if (ncols) *ncols = incols; 574 PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0)); 575 PetscFunctionReturn(PETSC_SUCCESS); 576 } 577 578 /*@ 579 MatConjugate - replaces the matrix values with their complex conjugates 580 581 Logically Collective 582 583 Input Parameter: 584 . mat - the matrix 585 586 Level: advanced 587 588 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()` 589 @*/ 590 PetscErrorCode MatConjugate(Mat mat) 591 { 592 PetscFunctionBegin; 593 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 594 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 595 if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) { 596 PetscUseTypeMethod(mat, conjugate); 597 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 598 } 599 PetscFunctionReturn(PETSC_SUCCESS); 600 } 601 602 /*@C 603 MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`. 604 605 Not Collective 606 607 Input Parameters: 608 + mat - the matrix 609 . row - the row to get 610 . ncols - the number of nonzeros 611 . cols - the columns of the nonzeros 612 - vals - if nonzero the column values 613 614 Level: advanced 615 616 Notes: 617 This routine should be called after you have finished examining the entries. 618 619 This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental 620 us of the array after it has been restored. If you pass `NULL`, it will 621 not zero the pointers. Use of `cols` or `vals` after `MatRestoreRow()` is invalid. 622 623 Fortran Notes: 624 The calling sequence is 625 .vb 626 MatRestoreRow(matrix,row,ncols,cols,values,ierr) 627 Mat matrix (input) 628 integer row (input) 629 integer ncols (output) 630 integer cols(maxcols) (output) 631 double precision (or double complex) values(maxcols) output 632 .ve 633 Where maxcols >= maximum nonzeros in any row of the matrix. 634 635 In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()` 636 before another call to `MatGetRow()` can be made. 637 638 .seealso: [](ch_matrices), `Mat`, `MatGetRow()` 639 @*/ 640 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 641 { 642 PetscFunctionBegin; 643 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 644 if (ncols) PetscAssertPointer(ncols, 3); 645 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 646 if (!mat->ops->restorerow) PetscFunctionReturn(PETSC_SUCCESS); 647 PetscUseTypeMethod(mat, restorerow, row, ncols, (PetscInt **)cols, (PetscScalar **)vals); 648 if (ncols) *ncols = 0; 649 if (cols) *cols = NULL; 650 if (vals) *vals = NULL; 651 PetscFunctionReturn(PETSC_SUCCESS); 652 } 653 654 /*@ 655 MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 656 You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag. 657 658 Not Collective 659 660 Input Parameter: 661 . mat - the matrix 662 663 Level: advanced 664 665 Note: 666 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. 667 668 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()` 669 @*/ 670 PetscErrorCode MatGetRowUpperTriangular(Mat mat) 671 { 672 PetscFunctionBegin; 673 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 674 PetscValidType(mat, 1); 675 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 676 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 677 MatCheckPreallocated(mat, 1); 678 if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS); 679 PetscUseTypeMethod(mat, getrowuppertriangular); 680 PetscFunctionReturn(PETSC_SUCCESS); 681 } 682 683 /*@ 684 MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 685 686 Not Collective 687 688 Input Parameter: 689 . mat - the matrix 690 691 Level: advanced 692 693 Note: 694 This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`. 695 696 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()` 697 @*/ 698 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat) 699 { 700 PetscFunctionBegin; 701 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 702 PetscValidType(mat, 1); 703 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 704 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 705 MatCheckPreallocated(mat, 1); 706 if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS); 707 PetscUseTypeMethod(mat, restorerowuppertriangular); 708 PetscFunctionReturn(PETSC_SUCCESS); 709 } 710 711 /*@C 712 MatSetOptionsPrefix - Sets the prefix used for searching for all 713 `Mat` options in the database. 714 715 Logically Collective 716 717 Input Parameters: 718 + A - the matrix 719 - prefix - the prefix to prepend to all option names 720 721 Level: advanced 722 723 Notes: 724 A hyphen (-) must NOT be given at the beginning of the prefix name. 725 The first character of all runtime options is AUTOMATICALLY the hyphen. 726 727 This is NOT used for options for the factorization of the matrix. Normally the 728 prefix is automatically passed in from the PC calling the factorization. To set 729 it directly use `MatSetOptionsPrefixFactor()` 730 731 .seealso: [](ch_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()` 732 @*/ 733 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[]) 734 { 735 PetscFunctionBegin; 736 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 737 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix)); 738 PetscFunctionReturn(PETSC_SUCCESS); 739 } 740 741 /*@C 742 MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for 743 for matrices created with `MatGetFactor()` 744 745 Logically Collective 746 747 Input Parameters: 748 + A - the matrix 749 - prefix - the prefix to prepend to all option names for the factored matrix 750 751 Level: developer 752 753 Notes: 754 A hyphen (-) must NOT be given at the beginning of the prefix name. 755 The first character of all runtime options is AUTOMATICALLY the hyphen. 756 757 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 758 it directly when not using `KSP`/`PC` use `MatSetOptionsPrefixFactor()` 759 760 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()` 761 @*/ 762 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[]) 763 { 764 PetscFunctionBegin; 765 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 766 if (prefix) { 767 PetscAssertPointer(prefix, 2); 768 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 769 if (prefix != A->factorprefix) { 770 PetscCall(PetscFree(A->factorprefix)); 771 PetscCall(PetscStrallocpy(prefix, &A->factorprefix)); 772 } 773 } else PetscCall(PetscFree(A->factorprefix)); 774 PetscFunctionReturn(PETSC_SUCCESS); 775 } 776 777 /*@C 778 MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for 779 for matrices created with `MatGetFactor()` 780 781 Logically Collective 782 783 Input Parameters: 784 + A - the matrix 785 - prefix - the prefix to prepend to all option names for the factored matrix 786 787 Level: developer 788 789 Notes: 790 A hyphen (-) must NOT be given at the beginning of the prefix name. 791 The first character of all runtime options is AUTOMATICALLY the hyphen. 792 793 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 794 it directly when not using `KSP`/`PC` use `MatAppendOptionsPrefixFactor()` 795 796 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`, 797 `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`, 798 `MatSetOptionsPrefix()` 799 @*/ 800 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[]) 801 { 802 size_t len1, len2, new_len; 803 804 PetscFunctionBegin; 805 PetscValidHeader(A, 1); 806 if (!prefix) PetscFunctionReturn(PETSC_SUCCESS); 807 if (!A->factorprefix) { 808 PetscCall(MatSetOptionsPrefixFactor(A, prefix)); 809 PetscFunctionReturn(PETSC_SUCCESS); 810 } 811 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 812 813 PetscCall(PetscStrlen(A->factorprefix, &len1)); 814 PetscCall(PetscStrlen(prefix, &len2)); 815 new_len = len1 + len2 + 1; 816 PetscCall(PetscRealloc(new_len * sizeof(*(A->factorprefix)), &A->factorprefix)); 817 PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1)); 818 PetscFunctionReturn(PETSC_SUCCESS); 819 } 820 821 /*@C 822 MatAppendOptionsPrefix - Appends to the prefix used for searching for all 823 matrix options in the database. 824 825 Logically Collective 826 827 Input Parameters: 828 + A - the matrix 829 - prefix - the prefix to prepend to all option names 830 831 Level: advanced 832 833 Note: 834 A hyphen (-) must NOT be given at the beginning of the prefix name. 835 The first character of all runtime options is AUTOMATICALLY the hyphen. 836 837 .seealso: [](ch_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()` 838 @*/ 839 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[]) 840 { 841 PetscFunctionBegin; 842 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 843 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix)); 844 PetscFunctionReturn(PETSC_SUCCESS); 845 } 846 847 /*@C 848 MatGetOptionsPrefix - Gets the prefix used for searching for all 849 matrix options in the database. 850 851 Not Collective 852 853 Input Parameter: 854 . A - the matrix 855 856 Output Parameter: 857 . prefix - pointer to the prefix string used 858 859 Level: advanced 860 861 Fortran Notes: 862 The user should pass in a string `prefix` of 863 sufficient length to hold the prefix. 864 865 .seealso: [](ch_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()` 866 @*/ 867 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[]) 868 { 869 PetscFunctionBegin; 870 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 871 PetscAssertPointer(prefix, 2); 872 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix)); 873 PetscFunctionReturn(PETSC_SUCCESS); 874 } 875 876 /*@ 877 MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by users. 878 879 Collective 880 881 Input Parameter: 882 . A - the matrix 883 884 Level: beginner 885 886 Notes: 887 The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`. 888 889 Users can reset the preallocation to access the original memory. 890 891 Currently only supported for `MATAIJ` matrices. 892 893 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()` 894 @*/ 895 PetscErrorCode MatResetPreallocation(Mat A) 896 { 897 PetscFunctionBegin; 898 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 899 PetscValidType(A, 1); 900 PetscCheck(A->insertmode == NOT_SET_VALUES, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot reset preallocation after setting some values but not yet calling MatAssemblyBegin()/MatAsssemblyEnd()"); 901 if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS); 902 PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A)); 903 PetscFunctionReturn(PETSC_SUCCESS); 904 } 905 906 /*@ 907 MatSetUp - Sets up the internal matrix data structures for later use. 908 909 Collective 910 911 Input Parameter: 912 . A - the matrix 913 914 Level: intermediate 915 916 Notes: 917 If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of 918 setting values in the matrix. 919 920 If a suitable preallocation routine is used, this function does not need to be called. 921 922 This routine is called internally by other matrix functions when needed so rarely needs to be called by users 923 924 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()` 925 @*/ 926 PetscErrorCode MatSetUp(Mat A) 927 { 928 PetscFunctionBegin; 929 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 930 if (!((PetscObject)A)->type_name) { 931 PetscMPIInt size; 932 933 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 934 PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ)); 935 } 936 if (!A->preallocated) PetscTryTypeMethod(A, setup); 937 PetscCall(PetscLayoutSetUp(A->rmap)); 938 PetscCall(PetscLayoutSetUp(A->cmap)); 939 A->preallocated = PETSC_TRUE; 940 PetscFunctionReturn(PETSC_SUCCESS); 941 } 942 943 #if defined(PETSC_HAVE_SAWS) 944 #include <petscviewersaws.h> 945 #endif 946 947 /* 948 If threadsafety is on extraneous matrices may be printed 949 950 This flag cannot be stored in the matrix because the original matrix in MatView() may assemble a new matrix which is passed into MatViewFromOptions() 951 */ 952 #if !defined(PETSC_HAVE_THREADSAFETY) 953 static PetscInt insidematview = 0; 954 #endif 955 956 /*@C 957 MatViewFromOptions - View properties of the matrix based on options set in the options database 958 959 Collective 960 961 Input Parameters: 962 + A - the matrix 963 . obj - optional additional object that provides the options prefix to use 964 - name - command line option 965 966 Options Database Key: 967 . -mat_view [viewertype]:... - the viewer and its options 968 969 Level: intermediate 970 971 Notes: 972 .vb 973 If no value is provided ascii:stdout is used 974 ascii[:[filename][:[format][:append]]] defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab, 975 for example ascii::ascii_info prints just the information about the object not all details 976 unless :append is given filename opens in write mode, overwriting what was already there 977 binary[:[filename][:[format][:append]]] defaults to the file binaryoutput 978 draw[:drawtype[:filename]] for example, draw:tikz, draw:tikz:figure.tex or draw:x 979 socket[:port] defaults to the standard output port 980 saws[:communicatorname] publishes object to the Scientific Application Webserver (SAWs) 981 .ve 982 983 .seealso: [](ch_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()` 984 @*/ 985 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[]) 986 { 987 PetscFunctionBegin; 988 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 989 #if !defined(PETSC_HAVE_THREADSAFETY) 990 if (insidematview) PetscFunctionReturn(PETSC_SUCCESS); 991 #endif 992 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 993 PetscFunctionReturn(PETSC_SUCCESS); 994 } 995 996 /*@C 997 MatView - display information about a matrix in a variety ways 998 999 Collective 1000 1001 Input Parameters: 1002 + mat - the matrix 1003 - viewer - visualization context 1004 1005 Options Database Keys: 1006 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 1007 . -mat_view ::ascii_info_detail - Prints more detailed info 1008 . -mat_view - Prints matrix in ASCII format 1009 . -mat_view ::ascii_matlab - Prints matrix in MATLAB format 1010 . -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 1011 . -display <name> - Sets display name (default is host) 1012 . -draw_pause <sec> - Sets number of seconds to pause after display 1013 . -mat_view socket - Sends matrix to socket, can be accessed from MATLAB (see Users-Manual: ch_matlab for details) 1014 . -viewer_socket_machine <machine> - - 1015 . -viewer_socket_port <port> - - 1016 . -mat_view binary - save matrix to file in binary format 1017 - -viewer_binary_filename <name> - - 1018 1019 Level: beginner 1020 1021 Notes: 1022 The available visualization contexts include 1023 + `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices 1024 . `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD` 1025 . `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm 1026 - `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure 1027 1028 The user can open alternative visualization contexts with 1029 + `PetscViewerASCIIOpen()` - Outputs matrix to a specified file 1030 . `PetscViewerBinaryOpen()` - Outputs matrix in binary to a 1031 specified file; corresponding input uses `MatLoad()` 1032 . `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to 1033 an X window display 1034 - `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer. 1035 Currently only the `MATSEQDENSE` and `MATAIJ` 1036 matrix types support the Socket viewer. 1037 1038 The user can call `PetscViewerPushFormat()` to specify the output 1039 format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`, 1040 `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`). Available formats include 1041 + `PETSC_VIEWER_DEFAULT` - default, prints matrix contents 1042 . `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in MATLAB format 1043 . `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros 1044 . `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse 1045 format common among all matrix types 1046 . `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific 1047 format (which is in many cases the same as the default) 1048 . `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix 1049 size and structure (not the matrix entries) 1050 - `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about 1051 the matrix structure 1052 1053 The ASCII viewers are only recommended for small matrices on at most a moderate number of processes, 1054 the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format. 1055 1056 In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer). 1057 1058 See the manual page for `MatLoad()` for the exact format of the binary file when the binary 1059 viewer is used. 1060 1061 See share/petsc/matlab/PetscBinaryRead.m for a MATLAB code that can read in the binary file when the binary 1062 viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python. 1063 1064 One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure, 1065 and then use the following mouse functions. 1066 .vb 1067 left mouse: zoom in 1068 middle mouse: zoom out 1069 right mouse: continue with the simulation 1070 .ve 1071 1072 .seealso: [](ch_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`, 1073 `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()` 1074 @*/ 1075 PetscErrorCode MatView(Mat mat, PetscViewer viewer) 1076 { 1077 PetscInt rows, cols, rbs, cbs; 1078 PetscBool isascii, isstring, issaws; 1079 PetscViewerFormat format; 1080 PetscMPIInt size; 1081 1082 PetscFunctionBegin; 1083 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1084 PetscValidType(mat, 1); 1085 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer)); 1086 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1087 PetscCheckSameComm(mat, 1, viewer, 2); 1088 1089 PetscCall(PetscViewerGetFormat(viewer, &format)); 1090 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 1091 if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS); 1092 1093 #if !defined(PETSC_HAVE_THREADSAFETY) 1094 insidematview++; 1095 #endif 1096 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 1097 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 1098 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws)); 1099 PetscCheck((isascii && (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL)) || !mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "No viewers for factored matrix except ASCII, info, or info_detail"); 1100 1101 PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0)); 1102 if (isascii) { 1103 if (!mat->preallocated) { 1104 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n")); 1105 #if !defined(PETSC_HAVE_THREADSAFETY) 1106 insidematview--; 1107 #endif 1108 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1109 PetscFunctionReturn(PETSC_SUCCESS); 1110 } 1111 if (!mat->assembled) { 1112 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n")); 1113 #if !defined(PETSC_HAVE_THREADSAFETY) 1114 insidematview--; 1115 #endif 1116 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1117 PetscFunctionReturn(PETSC_SUCCESS); 1118 } 1119 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer)); 1120 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1121 MatNullSpace nullsp, transnullsp; 1122 1123 PetscCall(PetscViewerASCIIPushTab(viewer)); 1124 PetscCall(MatGetSize(mat, &rows, &cols)); 1125 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1126 if (rbs != 1 || cbs != 1) { 1127 if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs)); 1128 else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs)); 1129 } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols)); 1130 if (mat->factortype) { 1131 MatSolverType solver; 1132 PetscCall(MatFactorGetSolverType(mat, &solver)); 1133 PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver)); 1134 } 1135 if (mat->ops->getinfo) { 1136 MatInfo info; 1137 PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info)); 1138 PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated)); 1139 if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs)); 1140 } 1141 PetscCall(MatGetNullSpace(mat, &nullsp)); 1142 PetscCall(MatGetTransposeNullSpace(mat, &transnullsp)); 1143 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached null space\n")); 1144 if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached transposed null space\n")); 1145 PetscCall(MatGetNearNullSpace(mat, &nullsp)); 1146 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached near null space\n")); 1147 PetscCall(PetscViewerASCIIPushTab(viewer)); 1148 PetscCall(MatProductView(mat, viewer)); 1149 PetscCall(PetscViewerASCIIPopTab(viewer)); 1150 } 1151 } else if (issaws) { 1152 #if defined(PETSC_HAVE_SAWS) 1153 PetscMPIInt rank; 1154 1155 PetscCall(PetscObjectName((PetscObject)mat)); 1156 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 1157 if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer)); 1158 #endif 1159 } else if (isstring) { 1160 const char *type; 1161 PetscCall(MatGetType(mat, &type)); 1162 PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type)); 1163 PetscTryTypeMethod(mat, view, viewer); 1164 } 1165 if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) { 1166 PetscCall(PetscViewerASCIIPushTab(viewer)); 1167 PetscUseTypeMethod(mat, viewnative, viewer); 1168 PetscCall(PetscViewerASCIIPopTab(viewer)); 1169 } else if (mat->ops->view) { 1170 PetscCall(PetscViewerASCIIPushTab(viewer)); 1171 PetscUseTypeMethod(mat, view, viewer); 1172 PetscCall(PetscViewerASCIIPopTab(viewer)); 1173 } 1174 if (isascii) { 1175 PetscCall(PetscViewerGetFormat(viewer, &format)); 1176 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer)); 1177 } 1178 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1179 #if !defined(PETSC_HAVE_THREADSAFETY) 1180 insidematview--; 1181 #endif 1182 PetscFunctionReturn(PETSC_SUCCESS); 1183 } 1184 1185 #if defined(PETSC_USE_DEBUG) 1186 #include <../src/sys/totalview/tv_data_display.h> 1187 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat) 1188 { 1189 TV_add_row("Local rows", "int", &mat->rmap->n); 1190 TV_add_row("Local columns", "int", &mat->cmap->n); 1191 TV_add_row("Global rows", "int", &mat->rmap->N); 1192 TV_add_row("Global columns", "int", &mat->cmap->N); 1193 TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name); 1194 return TV_format_OK; 1195 } 1196 #endif 1197 1198 /*@C 1199 MatLoad - Loads a matrix that has been stored in binary/HDF5 format 1200 with `MatView()`. The matrix format is determined from the options database. 1201 Generates a parallel MPI matrix if the communicator has more than one 1202 processor. The default matrix type is `MATAIJ`. 1203 1204 Collective 1205 1206 Input Parameters: 1207 + mat - the newly loaded matrix, this needs to have been created with `MatCreate()` 1208 or some related function before a call to `MatLoad()` 1209 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer 1210 1211 Options Database Keys: 1212 Used with block matrix formats (`MATSEQBAIJ`, ...) to specify 1213 block size 1214 . -matload_block_size <bs> - set block size 1215 1216 Level: beginner 1217 1218 Notes: 1219 If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the 1220 `Mat` before calling this routine if you wish to set it from the options database. 1221 1222 `MatLoad()` automatically loads into the options database any options 1223 given in the file filename.info where filename is the name of the file 1224 that was passed to the `PetscViewerBinaryOpen()`. The options in the info 1225 file will be ignored if you use the -viewer_binary_skip_info option. 1226 1227 If the type or size of mat is not set before a call to `MatLoad()`, PETSc 1228 sets the default matrix type AIJ and sets the local and global sizes. 1229 If type and/or size is already set, then the same are used. 1230 1231 In parallel, each processor can load a subset of rows (or the 1232 entire matrix). This routine is especially useful when a large 1233 matrix is stored on disk and only part of it is desired on each 1234 processor. For example, a parallel solver may access only some of 1235 the rows from each processor. The algorithm used here reads 1236 relatively small blocks of data rather than reading the entire 1237 matrix and then subsetting it. 1238 1239 Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`. 1240 Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`, 1241 or the sequence like 1242 .vb 1243 `PetscViewer` v; 1244 `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v); 1245 `PetscViewerSetType`(v,`PETSCVIEWERBINARY`); 1246 `PetscViewerSetFromOptions`(v); 1247 `PetscViewerFileSetMode`(v,`FILE_MODE_READ`); 1248 `PetscViewerFileSetName`(v,"datafile"); 1249 .ve 1250 The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option 1251 $ -viewer_type {binary, hdf5} 1252 1253 See the example src/ksp/ksp/tutorials/ex27.c with the first approach, 1254 and src/mat/tutorials/ex10.c with the second approach. 1255 1256 In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks 1257 is read onto MPI rank 0 and then shipped to its destination MPI rank, one after another. 1258 Multiple objects, both matrices and vectors, can be stored within the same file. 1259 Their `PetscObject` name is ignored; they are loaded in the order of their storage. 1260 1261 Most users should not need to know the details of the binary storage 1262 format, since `MatLoad()` and `MatView()` completely hide these details. 1263 But for anyone who is interested, the standard binary matrix storage 1264 format is 1265 1266 .vb 1267 PetscInt MAT_FILE_CLASSID 1268 PetscInt number of rows 1269 PetscInt number of columns 1270 PetscInt total number of nonzeros 1271 PetscInt *number nonzeros in each row 1272 PetscInt *column indices of all nonzeros (starting index is zero) 1273 PetscScalar *values of all nonzeros 1274 .ve 1275 If PETSc was not configured with `--with-64-bit-indices` then only `MATMPIAIJ` matrices with more than `PETSC_INT_MAX` non-zeros can be 1276 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 1277 case will not fit in a (32-bit) `PetscInt` the value `PETSC_INT_MAX` is used for the header entry `total number of nonzeros`. 1278 1279 PETSc automatically does the byte swapping for 1280 machines that store the bytes reversed. Thus if you write your own binary 1281 read/write routines you have to swap the bytes; see `PetscBinaryRead()` 1282 and `PetscBinaryWrite()` to see how this may be done. 1283 1284 In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used. 1285 Each processor's chunk is loaded independently by its owning MPI process. 1286 Multiple objects, both matrices and vectors, can be stored within the same file. 1287 They are looked up by their PetscObject name. 1288 1289 As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use 1290 by default the same structure and naming of the AIJ arrays and column count 1291 within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g. 1292 $ save example.mat A b -v7.3 1293 can be directly read by this routine (see Reference 1 for details). 1294 1295 Depending on your MATLAB version, this format might be a default, 1296 otherwise you can set it as default in Preferences. 1297 1298 Unless -nocompression flag is used to save the file in MATLAB, 1299 PETSc must be configured with ZLIB package. 1300 1301 See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c 1302 1303 This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5` 1304 1305 Corresponding `MatView()` is not yet implemented. 1306 1307 The loaded matrix is actually a transpose of the original one in MATLAB, 1308 unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above). 1309 With this format, matrix is automatically transposed by PETSc, 1310 unless the matrix is marked as SPD or symmetric 1311 (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`). 1312 1313 References: 1314 . * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version 1315 1316 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()` 1317 @*/ 1318 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer) 1319 { 1320 PetscBool flg; 1321 1322 PetscFunctionBegin; 1323 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1324 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1325 1326 if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ)); 1327 1328 flg = PETSC_FALSE; 1329 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL)); 1330 if (flg) { 1331 PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE)); 1332 PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE)); 1333 } 1334 flg = PETSC_FALSE; 1335 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL)); 1336 if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE)); 1337 1338 PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0)); 1339 PetscUseTypeMethod(mat, load, viewer); 1340 PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0)); 1341 PetscFunctionReturn(PETSC_SUCCESS); 1342 } 1343 1344 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant) 1345 { 1346 Mat_Redundant *redund = *redundant; 1347 1348 PetscFunctionBegin; 1349 if (redund) { 1350 if (redund->matseq) { /* via MatCreateSubMatrices() */ 1351 PetscCall(ISDestroy(&redund->isrow)); 1352 PetscCall(ISDestroy(&redund->iscol)); 1353 PetscCall(MatDestroySubMatrices(1, &redund->matseq)); 1354 } else { 1355 PetscCall(PetscFree2(redund->send_rank, redund->recv_rank)); 1356 PetscCall(PetscFree(redund->sbuf_j)); 1357 PetscCall(PetscFree(redund->sbuf_a)); 1358 for (PetscInt i = 0; i < redund->nrecvs; i++) { 1359 PetscCall(PetscFree(redund->rbuf_j[i])); 1360 PetscCall(PetscFree(redund->rbuf_a[i])); 1361 } 1362 PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a)); 1363 } 1364 1365 if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm)); 1366 PetscCall(PetscFree(redund)); 1367 } 1368 PetscFunctionReturn(PETSC_SUCCESS); 1369 } 1370 1371 /*@C 1372 MatDestroy - Frees space taken by a matrix. 1373 1374 Collective 1375 1376 Input Parameter: 1377 . A - the matrix 1378 1379 Level: beginner 1380 1381 Developer Notes: 1382 Some special arrays of matrices are not destroyed in this routine but instead by the routines called by 1383 `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines. 1384 `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes 1385 if changes are needed here. 1386 1387 .seealso: [](ch_matrices), `Mat`, `MatCreate()` 1388 @*/ 1389 PetscErrorCode MatDestroy(Mat *A) 1390 { 1391 PetscFunctionBegin; 1392 if (!*A) PetscFunctionReturn(PETSC_SUCCESS); 1393 PetscValidHeaderSpecific(*A, MAT_CLASSID, 1); 1394 if (--((PetscObject)(*A))->refct > 0) { 1395 *A = NULL; 1396 PetscFunctionReturn(PETSC_SUCCESS); 1397 } 1398 1399 /* if memory was published with SAWs then destroy it */ 1400 PetscCall(PetscObjectSAWsViewOff((PetscObject)*A)); 1401 PetscTryTypeMethod((*A), destroy); 1402 1403 PetscCall(PetscFree((*A)->factorprefix)); 1404 PetscCall(PetscFree((*A)->defaultvectype)); 1405 PetscCall(PetscFree((*A)->defaultrandtype)); 1406 PetscCall(PetscFree((*A)->bsizes)); 1407 PetscCall(PetscFree((*A)->solvertype)); 1408 for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i])); 1409 if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL; 1410 PetscCall(MatDestroy_Redundant(&(*A)->redundant)); 1411 PetscCall(MatProductClear(*A)); 1412 PetscCall(MatNullSpaceDestroy(&(*A)->nullsp)); 1413 PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp)); 1414 PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp)); 1415 PetscCall(MatDestroy(&(*A)->schur)); 1416 PetscCall(PetscLayoutDestroy(&(*A)->rmap)); 1417 PetscCall(PetscLayoutDestroy(&(*A)->cmap)); 1418 PetscCall(PetscHeaderDestroy(A)); 1419 PetscFunctionReturn(PETSC_SUCCESS); 1420 } 1421 1422 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1423 /*@C 1424 MatSetValues - Inserts or adds a block of values into a matrix. 1425 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1426 MUST be called after all calls to `MatSetValues()` have been completed. 1427 1428 Not Collective 1429 1430 Input Parameters: 1431 + mat - the matrix 1432 . v - a logically two-dimensional array of values 1433 . m - the number of rows 1434 . idxm - the global indices of the rows 1435 . n - the number of columns 1436 . idxn - the global indices of the columns 1437 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1438 1439 Level: beginner 1440 1441 Notes: 1442 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1443 1444 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1445 options cannot be mixed without intervening calls to the assembly 1446 routines. 1447 1448 `MatSetValues()` uses 0-based row and column numbers in Fortran 1449 as well as in C. 1450 1451 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1452 simply ignored. This allows easily inserting element stiffness matrices 1453 with homogeneous Dirichlet boundary conditions that you don't want represented 1454 in the matrix. 1455 1456 Efficiency Alert: 1457 The routine `MatSetValuesBlocked()` may offer much better efficiency 1458 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1459 1460 Developer Notes: 1461 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1462 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1463 1464 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1465 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1466 @*/ 1467 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1468 { 1469 PetscFunctionBeginHot; 1470 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1471 PetscValidType(mat, 1); 1472 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1473 PetscAssertPointer(idxm, 3); 1474 PetscAssertPointer(idxn, 5); 1475 MatCheckPreallocated(mat, 1); 1476 1477 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1478 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1479 1480 if (PetscDefined(USE_DEBUG)) { 1481 PetscInt i, j; 1482 1483 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1484 for (i = 0; i < m; i++) { 1485 for (j = 0; j < n; j++) { 1486 if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j])) 1487 #if defined(PETSC_USE_COMPLEX) 1488 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]); 1489 #else 1490 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]); 1491 #endif 1492 } 1493 } 1494 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); 1495 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); 1496 } 1497 1498 if (mat->assembled) { 1499 mat->was_assembled = PETSC_TRUE; 1500 mat->assembled = PETSC_FALSE; 1501 } 1502 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1503 PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv); 1504 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1505 PetscFunctionReturn(PETSC_SUCCESS); 1506 } 1507 1508 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1509 /*@C 1510 MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns 1511 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1512 MUST be called after all calls to `MatSetValues()` have been completed. 1513 1514 Not Collective 1515 1516 Input Parameters: 1517 + mat - the matrix 1518 . v - a logically two-dimensional array of values 1519 . ism - the rows to provide 1520 . isn - the columns to provide 1521 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1522 1523 Level: beginner 1524 1525 Notes: 1526 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1527 1528 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1529 options cannot be mixed without intervening calls to the assembly 1530 routines. 1531 1532 `MatSetValues()` uses 0-based row and column numbers in Fortran 1533 as well as in C. 1534 1535 Negative indices may be passed in `ism` and `isn`, these rows and columns are 1536 simply ignored. This allows easily inserting element stiffness matrices 1537 with homogeneous Dirichlet boundary conditions that you don't want represented 1538 in the matrix. 1539 1540 Efficiency Alert: 1541 The routine `MatSetValuesBlocked()` may offer much better efficiency 1542 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1543 1544 This is currently not optimized for any particular `ISType` 1545 1546 Developer Notes: 1547 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1548 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1549 1550 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1551 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1552 @*/ 1553 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv) 1554 { 1555 PetscInt m, n; 1556 const PetscInt *rows, *cols; 1557 1558 PetscFunctionBeginHot; 1559 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1560 PetscCall(ISGetIndices(ism, &rows)); 1561 PetscCall(ISGetIndices(isn, &cols)); 1562 PetscCall(ISGetLocalSize(ism, &m)); 1563 PetscCall(ISGetLocalSize(isn, &n)); 1564 PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv)); 1565 PetscCall(ISRestoreIndices(ism, &rows)); 1566 PetscCall(ISRestoreIndices(isn, &cols)); 1567 PetscFunctionReturn(PETSC_SUCCESS); 1568 } 1569 1570 /*@ 1571 MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1572 values into a matrix 1573 1574 Not Collective 1575 1576 Input Parameters: 1577 + mat - the matrix 1578 . row - the (block) row to set 1579 - v - a logically two-dimensional array of values 1580 1581 Level: intermediate 1582 1583 Notes: 1584 The values, `v`, are column-oriented (for the block version) and sorted 1585 1586 All the nonzeros in the row must be provided 1587 1588 The matrix must have previously had its column indices set, likely by having been assembled. 1589 1590 The row must belong to this process 1591 1592 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1593 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()` 1594 @*/ 1595 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[]) 1596 { 1597 PetscInt globalrow; 1598 1599 PetscFunctionBegin; 1600 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1601 PetscValidType(mat, 1); 1602 PetscAssertPointer(v, 3); 1603 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow)); 1604 PetscCall(MatSetValuesRow(mat, globalrow, v)); 1605 PetscFunctionReturn(PETSC_SUCCESS); 1606 } 1607 1608 /*@ 1609 MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1610 values into a matrix 1611 1612 Not Collective 1613 1614 Input Parameters: 1615 + mat - the matrix 1616 . row - the (block) row to set 1617 - 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 1618 1619 Level: advanced 1620 1621 Notes: 1622 The values, `v`, are column-oriented for the block version. 1623 1624 All the nonzeros in the row must be provided 1625 1626 THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used. 1627 1628 The row must belong to this process 1629 1630 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1631 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1632 @*/ 1633 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[]) 1634 { 1635 PetscFunctionBeginHot; 1636 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1637 PetscValidType(mat, 1); 1638 MatCheckPreallocated(mat, 1); 1639 PetscAssertPointer(v, 3); 1640 PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values"); 1641 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1642 mat->insertmode = INSERT_VALUES; 1643 1644 if (mat->assembled) { 1645 mat->was_assembled = PETSC_TRUE; 1646 mat->assembled = PETSC_FALSE; 1647 } 1648 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1649 PetscUseTypeMethod(mat, setvaluesrow, row, v); 1650 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1651 PetscFunctionReturn(PETSC_SUCCESS); 1652 } 1653 1654 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1655 /*@ 1656 MatSetValuesStencil - Inserts or adds a block of values into a matrix. 1657 Using structured grid indexing 1658 1659 Not Collective 1660 1661 Input Parameters: 1662 + mat - the matrix 1663 . m - number of rows being entered 1664 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered 1665 . n - number of columns being entered 1666 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered 1667 . v - a logically two-dimensional array of values 1668 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values 1669 1670 Level: beginner 1671 1672 Notes: 1673 By default the values, `v`, are row-oriented. See `MatSetOption()` for other options. 1674 1675 Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1676 options cannot be mixed without intervening calls to the assembly 1677 routines. 1678 1679 The grid coordinates are across the entire grid, not just the local portion 1680 1681 `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran 1682 as well as in C. 1683 1684 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1685 1686 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1687 or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1688 1689 The columns and rows in the stencil passed in MUST be contained within the 1690 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1691 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1692 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1693 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1694 1695 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 1696 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 1697 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 1698 `DM_BOUNDARY_PERIODIC` boundary type. 1699 1700 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 1701 a single value per point) you can skip filling those indices. 1702 1703 Inspired by the structured grid interface to the HYPRE package 1704 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1705 1706 Efficiency Alert: 1707 The routine `MatSetValuesBlockedStencil()` may offer much better efficiency 1708 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1709 1710 Fortran Notes: 1711 `idxm` and `idxn` should be declared as 1712 $ MatStencil idxm(4,m),idxn(4,n) 1713 and the values inserted using 1714 .vb 1715 idxm(MatStencil_i,1) = i 1716 idxm(MatStencil_j,1) = j 1717 idxm(MatStencil_k,1) = k 1718 idxm(MatStencil_c,1) = c 1719 etc 1720 .ve 1721 1722 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1723 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil` 1724 @*/ 1725 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1726 { 1727 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1728 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1729 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1730 1731 PetscFunctionBegin; 1732 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1733 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1734 PetscValidType(mat, 1); 1735 PetscAssertPointer(idxm, 3); 1736 PetscAssertPointer(idxn, 5); 1737 1738 if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 1739 jdxm = buf; 1740 jdxn = buf + m; 1741 } else { 1742 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1743 jdxm = bufm; 1744 jdxn = bufn; 1745 } 1746 for (i = 0; i < m; i++) { 1747 for (j = 0; j < 3 - sdim; j++) dxm++; 1748 tmp = *dxm++ - starts[0]; 1749 for (j = 0; j < dim - 1; j++) { 1750 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1751 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1752 } 1753 if (mat->stencil.noc) dxm++; 1754 jdxm[i] = tmp; 1755 } 1756 for (i = 0; i < n; i++) { 1757 for (j = 0; j < 3 - sdim; j++) dxn++; 1758 tmp = *dxn++ - starts[0]; 1759 for (j = 0; j < dim - 1; j++) { 1760 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1761 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1762 } 1763 if (mat->stencil.noc) dxn++; 1764 jdxn[i] = tmp; 1765 } 1766 PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv)); 1767 PetscCall(PetscFree2(bufm, bufn)); 1768 PetscFunctionReturn(PETSC_SUCCESS); 1769 } 1770 1771 /*@ 1772 MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix. 1773 Using structured grid indexing 1774 1775 Not Collective 1776 1777 Input Parameters: 1778 + mat - the matrix 1779 . m - number of rows being entered 1780 . idxm - grid coordinates for matrix rows being entered 1781 . n - number of columns being entered 1782 . idxn - grid coordinates for matrix columns being entered 1783 . v - a logically two-dimensional array of values 1784 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values 1785 1786 Level: beginner 1787 1788 Notes: 1789 By default the values, `v`, are row-oriented and unsorted. 1790 See `MatSetOption()` for other options. 1791 1792 Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1793 options cannot be mixed without intervening calls to the assembly 1794 routines. 1795 1796 The grid coordinates are across the entire grid, not just the local portion 1797 1798 `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran 1799 as well as in C. 1800 1801 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1802 1803 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1804 or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1805 1806 The columns and rows in the stencil passed in MUST be contained within the 1807 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1808 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1809 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1810 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1811 1812 Negative indices may be passed in idxm and idxn, these rows and columns are 1813 simply ignored. This allows easily inserting element stiffness matrices 1814 with homogeneous Dirichlet boundary conditions that you don't want represented 1815 in the matrix. 1816 1817 Inspired by the structured grid interface to the HYPRE package 1818 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1819 1820 Fortran Notes: 1821 `idxm` and `idxn` should be declared as 1822 $ MatStencil idxm(4,m),idxn(4,n) 1823 and the values inserted using 1824 .vb 1825 idxm(MatStencil_i,1) = i 1826 idxm(MatStencil_j,1) = j 1827 idxm(MatStencil_k,1) = k 1828 etc 1829 .ve 1830 1831 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1832 `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`, 1833 `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` 1834 @*/ 1835 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1836 { 1837 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1838 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1839 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1840 1841 PetscFunctionBegin; 1842 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1843 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1844 PetscValidType(mat, 1); 1845 PetscAssertPointer(idxm, 3); 1846 PetscAssertPointer(idxn, 5); 1847 PetscAssertPointer(v, 6); 1848 1849 if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 1850 jdxm = buf; 1851 jdxn = buf + m; 1852 } else { 1853 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1854 jdxm = bufm; 1855 jdxn = bufn; 1856 } 1857 for (i = 0; i < m; i++) { 1858 for (j = 0; j < 3 - sdim; j++) dxm++; 1859 tmp = *dxm++ - starts[0]; 1860 for (j = 0; j < sdim - 1; j++) { 1861 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1862 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1863 } 1864 dxm++; 1865 jdxm[i] = tmp; 1866 } 1867 for (i = 0; i < n; i++) { 1868 for (j = 0; j < 3 - sdim; j++) dxn++; 1869 tmp = *dxn++ - starts[0]; 1870 for (j = 0; j < sdim - 1; j++) { 1871 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1872 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1873 } 1874 dxn++; 1875 jdxn[i] = tmp; 1876 } 1877 PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv)); 1878 PetscCall(PetscFree2(bufm, bufn)); 1879 PetscFunctionReturn(PETSC_SUCCESS); 1880 } 1881 1882 /*@ 1883 MatSetStencil - Sets the grid information for setting values into a matrix via 1884 `MatSetValuesStencil()` 1885 1886 Not Collective 1887 1888 Input Parameters: 1889 + mat - the matrix 1890 . dim - dimension of the grid 1, 2, or 3 1891 . dims - number of grid points in x, y, and z direction, including ghost points on your processor 1892 . starts - starting point of ghost nodes on your processor in x, y, and z direction 1893 - dof - number of degrees of freedom per node 1894 1895 Level: beginner 1896 1897 Notes: 1898 Inspired by the structured grid interface to the HYPRE package 1899 (www.llnl.gov/CASC/hyper) 1900 1901 For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the 1902 user. 1903 1904 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1905 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()` 1906 @*/ 1907 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof) 1908 { 1909 PetscFunctionBegin; 1910 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1911 PetscAssertPointer(dims, 3); 1912 PetscAssertPointer(starts, 4); 1913 1914 mat->stencil.dim = dim + (dof > 1); 1915 for (PetscInt i = 0; i < dim; i++) { 1916 mat->stencil.dims[i] = dims[dim - i - 1]; /* copy the values in backwards */ 1917 mat->stencil.starts[i] = starts[dim - i - 1]; 1918 } 1919 mat->stencil.dims[dim] = dof; 1920 mat->stencil.starts[dim] = 0; 1921 mat->stencil.noc = (PetscBool)(dof == 1); 1922 PetscFunctionReturn(PETSC_SUCCESS); 1923 } 1924 1925 /*@C 1926 MatSetValuesBlocked - Inserts or adds a block of values into a matrix. 1927 1928 Not Collective 1929 1930 Input Parameters: 1931 + mat - the matrix 1932 . v - a logically two-dimensional array of values 1933 . m - the number of block rows 1934 . idxm - the global block indices 1935 . n - the number of block columns 1936 . idxn - the global block indices 1937 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values 1938 1939 Level: intermediate 1940 1941 Notes: 1942 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call 1943 MatXXXXSetPreallocation() or `MatSetUp()` before using this routine. 1944 1945 The `m` and `n` count the NUMBER of blocks in the row direction and column direction, 1946 NOT the total number of rows/columns; for example, if the block size is 2 and 1947 you are passing in values for rows 2,3,4,5 then m would be 2 (not 4). 1948 The values in idxm would be 1 2; that is the first index for each block divided by 1949 the block size. 1950 1951 You must call `MatSetBlockSize()` when constructing this matrix (before 1952 preallocating it). 1953 1954 By default the values, `v`, are row-oriented, so the layout of 1955 `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options. 1956 1957 Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES` 1958 options cannot be mixed without intervening calls to the assembly 1959 routines. 1960 1961 `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran 1962 as well as in C. 1963 1964 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1965 simply ignored. This allows easily inserting element stiffness matrices 1966 with homogeneous Dirichlet boundary conditions that you don't want represented 1967 in the matrix. 1968 1969 Each time an entry is set within a sparse matrix via `MatSetValues()`, 1970 internal searching must be done to determine where to place the 1971 data in the matrix storage space. By instead inserting blocks of 1972 entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is 1973 reduced. 1974 1975 Example: 1976 .vb 1977 Suppose m=n=2 and block size(bs) = 2 The array is 1978 1979 1 2 | 3 4 1980 5 6 | 7 8 1981 - - - | - - - 1982 9 10 | 11 12 1983 13 14 | 15 16 1984 1985 v[] should be passed in like 1986 v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] 1987 1988 If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then 1989 v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16] 1990 .ve 1991 1992 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()` 1993 @*/ 1994 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1995 { 1996 PetscFunctionBeginHot; 1997 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1998 PetscValidType(mat, 1); 1999 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2000 PetscAssertPointer(idxm, 3); 2001 PetscAssertPointer(idxn, 5); 2002 MatCheckPreallocated(mat, 1); 2003 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2004 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2005 if (PetscDefined(USE_DEBUG)) { 2006 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2007 PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2008 } 2009 if (PetscDefined(USE_DEBUG)) { 2010 PetscInt rbs, cbs, M, N, i; 2011 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 2012 PetscCall(MatGetSize(mat, &M, &N)); 2013 for (i = 0; i < m; i++) PetscCheck(idxm[i] * rbs < M, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row block index %" PetscInt_FMT " (index %" PetscInt_FMT ") greater than row length %" PetscInt_FMT, i, idxm[i], M); 2014 for (i = 0; i < n; i++) PetscCheck(idxn[i] * cbs < N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column block index %" PetscInt_FMT " (index %" PetscInt_FMT ") great than column length %" PetscInt_FMT, i, idxn[i], N); 2015 } 2016 if (mat->assembled) { 2017 mat->was_assembled = PETSC_TRUE; 2018 mat->assembled = PETSC_FALSE; 2019 } 2020 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2021 if (mat->ops->setvaluesblocked) { 2022 PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv); 2023 } else { 2024 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn; 2025 PetscInt i, j, bs, cbs; 2026 2027 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 2028 if ((m * bs + n * cbs) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2029 iidxm = buf; 2030 iidxn = buf + m * bs; 2031 } else { 2032 PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc)); 2033 iidxm = bufr; 2034 iidxn = bufc; 2035 } 2036 for (i = 0; i < m; i++) { 2037 for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j; 2038 } 2039 if (m != n || bs != cbs || idxm != idxn) { 2040 for (i = 0; i < n; i++) { 2041 for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j; 2042 } 2043 } else iidxn = iidxm; 2044 PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv)); 2045 PetscCall(PetscFree2(bufr, bufc)); 2046 } 2047 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2048 PetscFunctionReturn(PETSC_SUCCESS); 2049 } 2050 2051 /*@C 2052 MatGetValues - Gets a block of local values from a matrix. 2053 2054 Not Collective; can only return values that are owned by the give process 2055 2056 Input Parameters: 2057 + mat - the matrix 2058 . v - a logically two-dimensional array for storing the values 2059 . m - the number of rows 2060 . idxm - the global indices of the rows 2061 . n - the number of columns 2062 - idxn - the global indices of the columns 2063 2064 Level: advanced 2065 2066 Notes: 2067 The user must allocate space (m*n `PetscScalar`s) for the values, `v`. 2068 The values, `v`, are then returned in a row-oriented format, 2069 analogous to that used by default in `MatSetValues()`. 2070 2071 `MatGetValues()` uses 0-based row and column numbers in 2072 Fortran as well as in C. 2073 2074 `MatGetValues()` requires that the matrix has been assembled 2075 with `MatAssemblyBegin()`/`MatAssemblyEnd()`. Thus, calls to 2076 `MatSetValues()` and `MatGetValues()` CANNOT be made in succession 2077 without intermediate matrix assembly. 2078 2079 Negative row or column indices will be ignored and those locations in `v` will be 2080 left unchanged. 2081 2082 For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI process. 2083 That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable 2084 from `MatGetOwnershipRange`(mat,&rstart,&rend). 2085 2086 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()` 2087 @*/ 2088 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) 2089 { 2090 PetscFunctionBegin; 2091 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2092 PetscValidType(mat, 1); 2093 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); 2094 PetscAssertPointer(idxm, 3); 2095 PetscAssertPointer(idxn, 5); 2096 PetscAssertPointer(v, 6); 2097 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2098 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2099 MatCheckPreallocated(mat, 1); 2100 2101 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2102 PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v); 2103 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2104 PetscFunctionReturn(PETSC_SUCCESS); 2105 } 2106 2107 /*@C 2108 MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices 2109 defined previously by `MatSetLocalToGlobalMapping()` 2110 2111 Not Collective 2112 2113 Input Parameters: 2114 + mat - the matrix 2115 . nrow - number of rows 2116 . irow - the row local indices 2117 . ncol - number of columns 2118 - icol - the column local indices 2119 2120 Output Parameter: 2121 . y - a logically two-dimensional array of values 2122 2123 Level: advanced 2124 2125 Notes: 2126 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine. 2127 2128 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, 2129 are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can 2130 determine if the resulting global row associated with the local row r is owned by the requesting MPI process by applying the `ISLocalToGlobalMapping` set 2131 with `MatSetLocalToGlobalMapping()`. 2132 2133 Developer Notes: 2134 This is labelled with C so does not automatically generate Fortran stubs and interfaces 2135 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2136 2137 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2138 `MatSetValuesLocal()`, `MatGetValues()` 2139 @*/ 2140 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[]) 2141 { 2142 PetscFunctionBeginHot; 2143 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2144 PetscValidType(mat, 1); 2145 MatCheckPreallocated(mat, 1); 2146 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */ 2147 PetscAssertPointer(irow, 3); 2148 PetscAssertPointer(icol, 5); 2149 if (PetscDefined(USE_DEBUG)) { 2150 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2151 PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2152 } 2153 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2154 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2155 if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y); 2156 else { 2157 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm; 2158 if ((nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2159 irowm = buf; 2160 icolm = buf + nrow; 2161 } else { 2162 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2163 irowm = bufr; 2164 icolm = bufc; 2165 } 2166 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping())."); 2167 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping())."); 2168 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm)); 2169 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm)); 2170 PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y)); 2171 PetscCall(PetscFree2(bufr, bufc)); 2172 } 2173 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2174 PetscFunctionReturn(PETSC_SUCCESS); 2175 } 2176 2177 /*@ 2178 MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and 2179 the same size. Currently, this can only be called once and creates the given matrix. 2180 2181 Not Collective 2182 2183 Input Parameters: 2184 + mat - the matrix 2185 . nb - the number of blocks 2186 . bs - the number of rows (and columns) in each block 2187 . rows - a concatenation of the rows for each block 2188 - v - a concatenation of logically two-dimensional arrays of values 2189 2190 Level: advanced 2191 2192 Note: 2193 `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values 2194 2195 In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix. 2196 2197 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 2198 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()` 2199 @*/ 2200 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[]) 2201 { 2202 PetscFunctionBegin; 2203 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2204 PetscValidType(mat, 1); 2205 PetscAssertPointer(rows, 4); 2206 PetscAssertPointer(v, 5); 2207 PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2208 2209 PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0)); 2210 if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v); 2211 else { 2212 for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES)); 2213 } 2214 PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0)); 2215 PetscFunctionReturn(PETSC_SUCCESS); 2216 } 2217 2218 /*@ 2219 MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by 2220 the routine `MatSetValuesLocal()` to allow users to insert matrix entries 2221 using a local (per-processor) numbering. 2222 2223 Not Collective 2224 2225 Input Parameters: 2226 + x - the matrix 2227 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()` 2228 - cmapping - column mapping 2229 2230 Level: intermediate 2231 2232 Note: 2233 If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix 2234 2235 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()` 2236 @*/ 2237 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping) 2238 { 2239 PetscFunctionBegin; 2240 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 2241 PetscValidType(x, 1); 2242 if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2); 2243 if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3); 2244 if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping); 2245 else { 2246 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping)); 2247 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping)); 2248 } 2249 PetscFunctionReturn(PETSC_SUCCESS); 2250 } 2251 2252 /*@ 2253 MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()` 2254 2255 Not Collective 2256 2257 Input Parameter: 2258 . A - the matrix 2259 2260 Output Parameters: 2261 + rmapping - row mapping 2262 - cmapping - column mapping 2263 2264 Level: advanced 2265 2266 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()` 2267 @*/ 2268 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping) 2269 { 2270 PetscFunctionBegin; 2271 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2272 PetscValidType(A, 1); 2273 if (rmapping) { 2274 PetscAssertPointer(rmapping, 2); 2275 *rmapping = A->rmap->mapping; 2276 } 2277 if (cmapping) { 2278 PetscAssertPointer(cmapping, 3); 2279 *cmapping = A->cmap->mapping; 2280 } 2281 PetscFunctionReturn(PETSC_SUCCESS); 2282 } 2283 2284 /*@ 2285 MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix 2286 2287 Logically Collective 2288 2289 Input Parameters: 2290 + A - the matrix 2291 . rmap - row layout 2292 - cmap - column layout 2293 2294 Level: advanced 2295 2296 Note: 2297 The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called. 2298 2299 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()` 2300 @*/ 2301 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap) 2302 { 2303 PetscFunctionBegin; 2304 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2305 PetscCall(PetscLayoutReference(rmap, &A->rmap)); 2306 PetscCall(PetscLayoutReference(cmap, &A->cmap)); 2307 PetscFunctionReturn(PETSC_SUCCESS); 2308 } 2309 2310 /*@ 2311 MatGetLayouts - Gets the `PetscLayout` objects for rows and columns 2312 2313 Not Collective 2314 2315 Input Parameter: 2316 . A - the matrix 2317 2318 Output Parameters: 2319 + rmap - row layout 2320 - cmap - column layout 2321 2322 Level: advanced 2323 2324 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()` 2325 @*/ 2326 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap) 2327 { 2328 PetscFunctionBegin; 2329 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2330 PetscValidType(A, 1); 2331 if (rmap) { 2332 PetscAssertPointer(rmap, 2); 2333 *rmap = A->rmap; 2334 } 2335 if (cmap) { 2336 PetscAssertPointer(cmap, 3); 2337 *cmap = A->cmap; 2338 } 2339 PetscFunctionReturn(PETSC_SUCCESS); 2340 } 2341 2342 /*@C 2343 MatSetValuesLocal - Inserts or adds values into certain locations of a matrix, 2344 using a local numbering of the nodes. 2345 2346 Not Collective 2347 2348 Input Parameters: 2349 + mat - the matrix 2350 . nrow - number of rows 2351 . irow - the row local indices 2352 . ncol - number of columns 2353 . icol - the column local indices 2354 . y - a logically two-dimensional array of values 2355 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2356 2357 Level: intermediate 2358 2359 Notes: 2360 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 2361 `MatSetUp()` before using this routine 2362 2363 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine 2364 2365 Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2366 options cannot be mixed without intervening calls to the assembly 2367 routines. 2368 2369 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2370 MUST be called after all calls to `MatSetValuesLocal()` have been completed. 2371 2372 Developer Notes: 2373 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2374 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2375 2376 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2377 `MatGetValuesLocal()` 2378 @*/ 2379 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2380 { 2381 PetscFunctionBeginHot; 2382 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2383 PetscValidType(mat, 1); 2384 MatCheckPreallocated(mat, 1); 2385 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2386 PetscAssertPointer(irow, 3); 2387 PetscAssertPointer(icol, 5); 2388 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2389 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2390 if (PetscDefined(USE_DEBUG)) { 2391 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2392 PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2393 } 2394 2395 if (mat->assembled) { 2396 mat->was_assembled = PETSC_TRUE; 2397 mat->assembled = PETSC_FALSE; 2398 } 2399 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2400 if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv); 2401 else { 2402 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2403 const PetscInt *irowm, *icolm; 2404 2405 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2406 bufr = buf; 2407 bufc = buf + nrow; 2408 irowm = bufr; 2409 icolm = bufc; 2410 } else { 2411 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2412 irowm = bufr; 2413 icolm = bufc; 2414 } 2415 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr)); 2416 else irowm = irow; 2417 if (mat->cmap->mapping) { 2418 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2419 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc)); 2420 } else icolm = irowm; 2421 } else icolm = icol; 2422 PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv)); 2423 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2424 } 2425 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2426 PetscFunctionReturn(PETSC_SUCCESS); 2427 } 2428 2429 /*@C 2430 MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix, 2431 using a local ordering of the nodes a block at a time. 2432 2433 Not Collective 2434 2435 Input Parameters: 2436 + mat - the matrix 2437 . nrow - number of rows 2438 . irow - the row local indices 2439 . ncol - number of columns 2440 . icol - the column local indices 2441 . y - a logically two-dimensional array of values 2442 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2443 2444 Level: intermediate 2445 2446 Notes: 2447 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 2448 `MatSetUp()` before using this routine 2449 2450 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()` 2451 before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the 2452 2453 Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2454 options cannot be mixed without intervening calls to the assembly 2455 routines. 2456 2457 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2458 MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed. 2459 2460 Developer Notes: 2461 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2462 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2463 2464 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, 2465 `MatSetValuesLocal()`, `MatSetValuesBlocked()` 2466 @*/ 2467 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2468 { 2469 PetscFunctionBeginHot; 2470 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2471 PetscValidType(mat, 1); 2472 MatCheckPreallocated(mat, 1); 2473 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2474 PetscAssertPointer(irow, 3); 2475 PetscAssertPointer(icol, 5); 2476 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2477 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2478 if (PetscDefined(USE_DEBUG)) { 2479 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2480 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); 2481 } 2482 2483 if (mat->assembled) { 2484 mat->was_assembled = PETSC_TRUE; 2485 mat->assembled = PETSC_FALSE; 2486 } 2487 if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */ 2488 PetscInt irbs, rbs; 2489 PetscCall(MatGetBlockSizes(mat, &rbs, NULL)); 2490 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs)); 2491 PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs); 2492 } 2493 if (PetscUnlikelyDebug(mat->cmap->mapping)) { 2494 PetscInt icbs, cbs; 2495 PetscCall(MatGetBlockSizes(mat, NULL, &cbs)); 2496 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs)); 2497 PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs); 2498 } 2499 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2500 if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv); 2501 else { 2502 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2503 const PetscInt *irowm, *icolm; 2504 2505 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= ((PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf))) { 2506 bufr = buf; 2507 bufc = buf + nrow; 2508 irowm = bufr; 2509 icolm = bufc; 2510 } else { 2511 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2512 irowm = bufr; 2513 icolm = bufc; 2514 } 2515 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr)); 2516 else irowm = irow; 2517 if (mat->cmap->mapping) { 2518 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2519 PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc)); 2520 } else icolm = irowm; 2521 } else icolm = icol; 2522 PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv)); 2523 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2524 } 2525 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2526 PetscFunctionReturn(PETSC_SUCCESS); 2527 } 2528 2529 /*@ 2530 MatMultDiagonalBlock - Computes the matrix-vector product, y = Dx. Where D is defined by the inode or block structure of the diagonal 2531 2532 Collective 2533 2534 Input Parameters: 2535 + mat - the matrix 2536 - x - the vector to be multiplied 2537 2538 Output Parameter: 2539 . y - the result 2540 2541 Level: developer 2542 2543 Note: 2544 The vectors `x` and `y` cannot be the same. I.e., one cannot 2545 call `MatMultDiagonalBlock`(A,y,y). 2546 2547 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2548 @*/ 2549 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y) 2550 { 2551 PetscFunctionBegin; 2552 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2553 PetscValidType(mat, 1); 2554 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2555 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2556 2557 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2558 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2559 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2560 MatCheckPreallocated(mat, 1); 2561 2562 PetscUseTypeMethod(mat, multdiagonalblock, x, y); 2563 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2564 PetscFunctionReturn(PETSC_SUCCESS); 2565 } 2566 2567 /*@ 2568 MatMult - Computes the matrix-vector product, y = Ax. 2569 2570 Neighbor-wise Collective 2571 2572 Input Parameters: 2573 + mat - the matrix 2574 - x - the vector to be multiplied 2575 2576 Output Parameter: 2577 . y - the result 2578 2579 Level: beginner 2580 2581 Note: 2582 The vectors `x` and `y` cannot be the same. I.e., one cannot 2583 call `MatMult`(A,y,y). 2584 2585 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2586 @*/ 2587 PetscErrorCode MatMult(Mat mat, Vec x, Vec y) 2588 { 2589 PetscFunctionBegin; 2590 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2591 PetscValidType(mat, 1); 2592 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2593 VecCheckAssembled(x); 2594 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2595 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2596 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2597 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2598 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); 2599 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); 2600 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); 2601 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); 2602 PetscCall(VecSetErrorIfLocked(y, 3)); 2603 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2604 MatCheckPreallocated(mat, 1); 2605 2606 PetscCall(VecLockReadPush(x)); 2607 PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0)); 2608 PetscUseTypeMethod(mat, mult, x, y); 2609 PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0)); 2610 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2611 PetscCall(VecLockReadPop(x)); 2612 PetscFunctionReturn(PETSC_SUCCESS); 2613 } 2614 2615 /*@ 2616 MatMultTranspose - Computes matrix transpose times a vector y = A^T * x. 2617 2618 Neighbor-wise Collective 2619 2620 Input Parameters: 2621 + mat - the matrix 2622 - x - the vector to be multiplied 2623 2624 Output Parameter: 2625 . y - the result 2626 2627 Level: beginner 2628 2629 Notes: 2630 The vectors `x` and `y` cannot be the same. I.e., one cannot 2631 call `MatMultTranspose`(A,y,y). 2632 2633 For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple, 2634 use `MatMultHermitianTranspose()` 2635 2636 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()` 2637 @*/ 2638 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y) 2639 { 2640 PetscErrorCode (*op)(Mat, Vec, Vec) = NULL; 2641 2642 PetscFunctionBegin; 2643 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2644 PetscValidType(mat, 1); 2645 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2646 VecCheckAssembled(x); 2647 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2648 2649 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2650 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2651 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2652 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); 2653 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); 2654 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); 2655 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); 2656 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2657 MatCheckPreallocated(mat, 1); 2658 2659 if (!mat->ops->multtranspose) { 2660 if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult; 2661 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); 2662 } else op = mat->ops->multtranspose; 2663 PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0)); 2664 PetscCall(VecLockReadPush(x)); 2665 PetscCall((*op)(mat, x, y)); 2666 PetscCall(VecLockReadPop(x)); 2667 PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0)); 2668 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2669 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2670 PetscFunctionReturn(PETSC_SUCCESS); 2671 } 2672 2673 /*@ 2674 MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector. 2675 2676 Neighbor-wise Collective 2677 2678 Input Parameters: 2679 + mat - the matrix 2680 - x - the vector to be multiplied 2681 2682 Output Parameter: 2683 . y - the result 2684 2685 Level: beginner 2686 2687 Notes: 2688 The vectors `x` and `y` cannot be the same. I.e., one cannot 2689 call `MatMultHermitianTranspose`(A,y,y). 2690 2691 Also called the conjugate transpose, complex conjugate transpose, or adjoint. 2692 2693 For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical. 2694 2695 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()` 2696 @*/ 2697 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y) 2698 { 2699 PetscFunctionBegin; 2700 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2701 PetscValidType(mat, 1); 2702 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2703 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2704 2705 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2706 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2707 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2708 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); 2709 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); 2710 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); 2711 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); 2712 MatCheckPreallocated(mat, 1); 2713 2714 PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0)); 2715 #if defined(PETSC_USE_COMPLEX) 2716 if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) { 2717 PetscCall(VecLockReadPush(x)); 2718 if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y); 2719 else PetscUseTypeMethod(mat, mult, x, y); 2720 PetscCall(VecLockReadPop(x)); 2721 } else { 2722 Vec w; 2723 PetscCall(VecDuplicate(x, &w)); 2724 PetscCall(VecCopy(x, w)); 2725 PetscCall(VecConjugate(w)); 2726 PetscCall(MatMultTranspose(mat, w, y)); 2727 PetscCall(VecDestroy(&w)); 2728 PetscCall(VecConjugate(y)); 2729 } 2730 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2731 #else 2732 PetscCall(MatMultTranspose(mat, x, y)); 2733 #endif 2734 PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0)); 2735 PetscFunctionReturn(PETSC_SUCCESS); 2736 } 2737 2738 /*@ 2739 MatMultAdd - Computes v3 = v2 + A * v1. 2740 2741 Neighbor-wise Collective 2742 2743 Input Parameters: 2744 + mat - the matrix 2745 . v1 - the vector to be multiplied by `mat` 2746 - v2 - the vector to be added to the result 2747 2748 Output Parameter: 2749 . v3 - the result 2750 2751 Level: beginner 2752 2753 Note: 2754 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2755 call `MatMultAdd`(A,v1,v2,v1). 2756 2757 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()` 2758 @*/ 2759 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2760 { 2761 PetscFunctionBegin; 2762 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2763 PetscValidType(mat, 1); 2764 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2765 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2766 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2767 2768 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2769 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2770 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); 2771 /* 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); 2772 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); */ 2773 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); 2774 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); 2775 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2776 MatCheckPreallocated(mat, 1); 2777 2778 PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3)); 2779 PetscCall(VecLockReadPush(v1)); 2780 PetscUseTypeMethod(mat, multadd, v1, v2, v3); 2781 PetscCall(VecLockReadPop(v1)); 2782 PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3)); 2783 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2784 PetscFunctionReturn(PETSC_SUCCESS); 2785 } 2786 2787 /*@ 2788 MatMultTransposeAdd - Computes v3 = v2 + A' * v1. 2789 2790 Neighbor-wise Collective 2791 2792 Input Parameters: 2793 + mat - the matrix 2794 . v1 - the vector to be multiplied by the transpose of the matrix 2795 - v2 - the vector to be added to the result 2796 2797 Output Parameter: 2798 . v3 - the result 2799 2800 Level: beginner 2801 2802 Note: 2803 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2804 call `MatMultTransposeAdd`(A,v1,v2,v1). 2805 2806 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2807 @*/ 2808 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2809 { 2810 PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd; 2811 2812 PetscFunctionBegin; 2813 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2814 PetscValidType(mat, 1); 2815 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2816 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2817 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2818 2819 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2820 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2821 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); 2822 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); 2823 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); 2824 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2825 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2826 MatCheckPreallocated(mat, 1); 2827 2828 PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2829 PetscCall(VecLockReadPush(v1)); 2830 PetscCall((*op)(mat, v1, v2, v3)); 2831 PetscCall(VecLockReadPop(v1)); 2832 PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2833 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2834 PetscFunctionReturn(PETSC_SUCCESS); 2835 } 2836 2837 /*@ 2838 MatMultHermitianTransposeAdd - Computes v3 = v2 + A^H * v1. 2839 2840 Neighbor-wise Collective 2841 2842 Input Parameters: 2843 + mat - the matrix 2844 . v1 - the vector to be multiplied by the Hermitian transpose 2845 - v2 - the vector to be added to the result 2846 2847 Output Parameter: 2848 . v3 - the result 2849 2850 Level: beginner 2851 2852 Note: 2853 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2854 call `MatMultHermitianTransposeAdd`(A,v1,v2,v1). 2855 2856 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2857 @*/ 2858 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2859 { 2860 PetscFunctionBegin; 2861 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2862 PetscValidType(mat, 1); 2863 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2864 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2865 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2866 2867 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2868 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2869 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2870 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); 2871 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); 2872 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); 2873 MatCheckPreallocated(mat, 1); 2874 2875 PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2876 PetscCall(VecLockReadPush(v1)); 2877 if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3); 2878 else { 2879 Vec w, z; 2880 PetscCall(VecDuplicate(v1, &w)); 2881 PetscCall(VecCopy(v1, w)); 2882 PetscCall(VecConjugate(w)); 2883 PetscCall(VecDuplicate(v3, &z)); 2884 PetscCall(MatMultTranspose(mat, w, z)); 2885 PetscCall(VecDestroy(&w)); 2886 PetscCall(VecConjugate(z)); 2887 if (v2 != v3) { 2888 PetscCall(VecWAXPY(v3, 1.0, v2, z)); 2889 } else { 2890 PetscCall(VecAXPY(v3, 1.0, z)); 2891 } 2892 PetscCall(VecDestroy(&z)); 2893 } 2894 PetscCall(VecLockReadPop(v1)); 2895 PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2896 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2897 PetscFunctionReturn(PETSC_SUCCESS); 2898 } 2899 2900 /*@C 2901 MatGetFactorType - gets the type of factorization it is 2902 2903 Not Collective 2904 2905 Input Parameter: 2906 . mat - the matrix 2907 2908 Output Parameter: 2909 . 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` 2910 2911 Level: intermediate 2912 2913 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2914 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2915 @*/ 2916 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t) 2917 { 2918 PetscFunctionBegin; 2919 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2920 PetscValidType(mat, 1); 2921 PetscAssertPointer(t, 2); 2922 *t = mat->factortype; 2923 PetscFunctionReturn(PETSC_SUCCESS); 2924 } 2925 2926 /*@C 2927 MatSetFactorType - sets the type of factorization it is 2928 2929 Logically Collective 2930 2931 Input Parameters: 2932 + mat - the matrix 2933 - 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` 2934 2935 Level: intermediate 2936 2937 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2938 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2939 @*/ 2940 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t) 2941 { 2942 PetscFunctionBegin; 2943 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2944 PetscValidType(mat, 1); 2945 mat->factortype = t; 2946 PetscFunctionReturn(PETSC_SUCCESS); 2947 } 2948 2949 /*@C 2950 MatGetInfo - Returns information about matrix storage (number of 2951 nonzeros, memory, etc.). 2952 2953 Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag 2954 2955 Input Parameters: 2956 + mat - the matrix 2957 - 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) 2958 2959 Output Parameter: 2960 . info - matrix information context 2961 2962 Options Database Key: 2963 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT` 2964 2965 Notes: 2966 The `MatInfo` context contains a variety of matrix data, including 2967 number of nonzeros allocated and used, number of mallocs during 2968 matrix assembly, etc. Additional information for factored matrices 2969 is provided (such as the fill ratio, number of mallocs during 2970 factorization, etc.). 2971 2972 Example: 2973 See the file ${PETSC_DIR}/include/petscmat.h for a complete list of 2974 data within the MatInfo context. For example, 2975 .vb 2976 MatInfo info; 2977 Mat A; 2978 double mal, nz_a, nz_u; 2979 2980 MatGetInfo(A, MAT_LOCAL, &info); 2981 mal = info.mallocs; 2982 nz_a = info.nz_allocated; 2983 .ve 2984 2985 Fortran users should declare info as a double precision 2986 array of dimension `MAT_INFO_SIZE`, and then extract the parameters 2987 of interest. See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h 2988 a complete list of parameter names. 2989 .vb 2990 double precision info(MAT_INFO_SIZE) 2991 double precision mal, nz_a 2992 Mat A 2993 integer ierr 2994 2995 call MatGetInfo(A, MAT_LOCAL, info, ierr) 2996 mal = info(MAT_INFO_MALLOCS) 2997 nz_a = info(MAT_INFO_NZ_ALLOCATED) 2998 .ve 2999 3000 Level: intermediate 3001 3002 Developer Notes: 3003 The Fortran interface is not autogenerated as the 3004 interface definition cannot be generated correctly [due to `MatInfo` argument] 3005 3006 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()` 3007 @*/ 3008 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info) 3009 { 3010 PetscFunctionBegin; 3011 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3012 PetscValidType(mat, 1); 3013 PetscAssertPointer(info, 3); 3014 MatCheckPreallocated(mat, 1); 3015 PetscUseTypeMethod(mat, getinfo, flag, info); 3016 PetscFunctionReturn(PETSC_SUCCESS); 3017 } 3018 3019 /* 3020 This is used by external packages where it is not easy to get the info from the actual 3021 matrix factorization. 3022 */ 3023 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info) 3024 { 3025 PetscFunctionBegin; 3026 PetscCall(PetscMemzero(info, sizeof(MatInfo))); 3027 PetscFunctionReturn(PETSC_SUCCESS); 3028 } 3029 3030 /*@C 3031 MatLUFactor - Performs in-place LU factorization of matrix. 3032 3033 Collective 3034 3035 Input Parameters: 3036 + mat - the matrix 3037 . row - row permutation 3038 . col - column permutation 3039 - info - options for factorization, includes 3040 .vb 3041 fill - expected fill as ratio of original fill. 3042 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3043 Run with the option -info to determine an optimal value to use 3044 .ve 3045 3046 Level: developer 3047 3048 Notes: 3049 Most users should employ the `KSP` interface for linear solvers 3050 instead of working directly with matrix algebra routines such as this. 3051 See, e.g., `KSPCreate()`. 3052 3053 This changes the state of the matrix to a factored matrix; it cannot be used 3054 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3055 3056 This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()` 3057 when not using `KSP`. 3058 3059 Developer Notes: 3060 The Fortran interface is not autogenerated as the 3061 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3062 3063 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, 3064 `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3065 @*/ 3066 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3067 { 3068 MatFactorInfo tinfo; 3069 3070 PetscFunctionBegin; 3071 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3072 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3073 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3074 if (info) PetscAssertPointer(info, 4); 3075 PetscValidType(mat, 1); 3076 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3077 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3078 MatCheckPreallocated(mat, 1); 3079 if (!info) { 3080 PetscCall(MatFactorInfoInitialize(&tinfo)); 3081 info = &tinfo; 3082 } 3083 3084 PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0)); 3085 PetscUseTypeMethod(mat, lufactor, row, col, info); 3086 PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0)); 3087 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3088 PetscFunctionReturn(PETSC_SUCCESS); 3089 } 3090 3091 /*@C 3092 MatILUFactor - Performs in-place ILU factorization of matrix. 3093 3094 Collective 3095 3096 Input Parameters: 3097 + mat - the matrix 3098 . row - row permutation 3099 . col - column permutation 3100 - info - structure containing 3101 .vb 3102 levels - number of levels of fill. 3103 expected fill - as ratio of original fill. 3104 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 3105 missing diagonal entries) 3106 .ve 3107 3108 Level: developer 3109 3110 Notes: 3111 Most users should employ the `KSP` interface for linear solvers 3112 instead of working directly with matrix algebra routines such as this. 3113 See, e.g., `KSPCreate()`. 3114 3115 Probably really in-place only when level of fill is zero, otherwise allocates 3116 new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()` 3117 when not using `KSP`. 3118 3119 Developer Notes: 3120 The Fortran interface is not autogenerated as the 3121 interface definition cannot be generated correctly [due to MatFactorInfo] 3122 3123 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 3124 @*/ 3125 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3126 { 3127 PetscFunctionBegin; 3128 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3129 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3130 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3131 PetscAssertPointer(info, 4); 3132 PetscValidType(mat, 1); 3133 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 3134 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3135 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3136 MatCheckPreallocated(mat, 1); 3137 3138 PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0)); 3139 PetscUseTypeMethod(mat, ilufactor, row, col, info); 3140 PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0)); 3141 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3142 PetscFunctionReturn(PETSC_SUCCESS); 3143 } 3144 3145 /*@C 3146 MatLUFactorSymbolic - Performs symbolic LU factorization of matrix. 3147 Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`. 3148 3149 Collective 3150 3151 Input Parameters: 3152 + fact - the factor matrix obtained with `MatGetFactor()` 3153 . mat - the matrix 3154 . row - the row permutation 3155 . col - the column permutation 3156 - info - options for factorization, includes 3157 .vb 3158 fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use 3159 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3160 .ve 3161 3162 Level: developer 3163 3164 Notes: 3165 See [Matrix Factorization](sec_matfactor) for additional information about factorizations 3166 3167 Most users should employ the simplified `KSP` interface for linear solvers 3168 instead of working directly with matrix algebra routines such as this. 3169 See, e.g., `KSPCreate()`. 3170 3171 Developer Notes: 3172 The Fortran interface is not autogenerated as the 3173 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3174 3175 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3176 @*/ 3177 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 3178 { 3179 MatFactorInfo tinfo; 3180 3181 PetscFunctionBegin; 3182 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3183 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3184 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 3185 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 3186 if (info) PetscAssertPointer(info, 5); 3187 PetscValidType(fact, 1); 3188 PetscValidType(mat, 2); 3189 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3190 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3191 MatCheckPreallocated(mat, 2); 3192 if (!info) { 3193 PetscCall(MatFactorInfoInitialize(&tinfo)); 3194 info = &tinfo; 3195 } 3196 3197 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0)); 3198 PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info); 3199 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0)); 3200 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3201 PetscFunctionReturn(PETSC_SUCCESS); 3202 } 3203 3204 /*@C 3205 MatLUFactorNumeric - Performs numeric LU factorization of a matrix. 3206 Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`. 3207 3208 Collective 3209 3210 Input Parameters: 3211 + fact - the factor matrix obtained with `MatGetFactor()` 3212 . mat - the matrix 3213 - info - options for factorization 3214 3215 Level: developer 3216 3217 Notes: 3218 See `MatLUFactor()` for in-place factorization. See 3219 `MatCholeskyFactorNumeric()` for the symmetric, positive definite case. 3220 3221 Most users should employ the `KSP` interface for linear solvers 3222 instead of working directly with matrix algebra routines such as this. 3223 See, e.g., `KSPCreate()`. 3224 3225 Developer Notes: 3226 The Fortran interface is not autogenerated as the 3227 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3228 3229 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()` 3230 @*/ 3231 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3232 { 3233 MatFactorInfo tinfo; 3234 3235 PetscFunctionBegin; 3236 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3237 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3238 PetscValidType(fact, 1); 3239 PetscValidType(mat, 2); 3240 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3241 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, 3242 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3243 3244 MatCheckPreallocated(mat, 2); 3245 if (!info) { 3246 PetscCall(MatFactorInfoInitialize(&tinfo)); 3247 info = &tinfo; 3248 } 3249 3250 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3251 else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0)); 3252 PetscUseTypeMethod(fact, lufactornumeric, mat, info); 3253 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3254 else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0)); 3255 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3256 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3257 PetscFunctionReturn(PETSC_SUCCESS); 3258 } 3259 3260 /*@C 3261 MatCholeskyFactor - Performs in-place Cholesky factorization of a 3262 symmetric matrix. 3263 3264 Collective 3265 3266 Input Parameters: 3267 + mat - the matrix 3268 . perm - row and column permutations 3269 - info - expected fill as ratio of original fill 3270 3271 Level: developer 3272 3273 Notes: 3274 See `MatLUFactor()` for the nonsymmetric case. See also `MatGetFactor()`, 3275 `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`. 3276 3277 Most users should employ the `KSP` interface for linear solvers 3278 instead of working directly with matrix algebra routines such as this. 3279 See, e.g., `KSPCreate()`. 3280 3281 Developer Notes: 3282 The Fortran interface is not autogenerated as the 3283 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3284 3285 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()` 3286 `MatGetOrdering()` 3287 @*/ 3288 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info) 3289 { 3290 MatFactorInfo tinfo; 3291 3292 PetscFunctionBegin; 3293 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3294 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2); 3295 if (info) PetscAssertPointer(info, 3); 3296 PetscValidType(mat, 1); 3297 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3298 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3299 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3300 MatCheckPreallocated(mat, 1); 3301 if (!info) { 3302 PetscCall(MatFactorInfoInitialize(&tinfo)); 3303 info = &tinfo; 3304 } 3305 3306 PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0)); 3307 PetscUseTypeMethod(mat, choleskyfactor, perm, info); 3308 PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0)); 3309 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3310 PetscFunctionReturn(PETSC_SUCCESS); 3311 } 3312 3313 /*@C 3314 MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization 3315 of a symmetric matrix. 3316 3317 Collective 3318 3319 Input Parameters: 3320 + fact - the factor matrix obtained with `MatGetFactor()` 3321 . mat - the matrix 3322 . perm - row and column permutations 3323 - info - options for factorization, includes 3324 .vb 3325 fill - expected fill as ratio of original fill. 3326 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3327 Run with the option -info to determine an optimal value to use 3328 .ve 3329 3330 Level: developer 3331 3332 Notes: 3333 See `MatLUFactorSymbolic()` for the nonsymmetric case. See also 3334 `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`. 3335 3336 Most users should employ the `KSP` interface for linear solvers 3337 instead of working directly with matrix algebra routines such as this. 3338 See, e.g., `KSPCreate()`. 3339 3340 Developer Notes: 3341 The Fortran interface is not autogenerated as the 3342 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3343 3344 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()` 3345 `MatGetOrdering()` 3346 @*/ 3347 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 3348 { 3349 MatFactorInfo tinfo; 3350 3351 PetscFunctionBegin; 3352 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3353 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3354 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 3355 if (info) PetscAssertPointer(info, 4); 3356 PetscValidType(fact, 1); 3357 PetscValidType(mat, 2); 3358 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3359 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3360 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3361 MatCheckPreallocated(mat, 2); 3362 if (!info) { 3363 PetscCall(MatFactorInfoInitialize(&tinfo)); 3364 info = &tinfo; 3365 } 3366 3367 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3368 PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info); 3369 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3370 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3371 PetscFunctionReturn(PETSC_SUCCESS); 3372 } 3373 3374 /*@C 3375 MatCholeskyFactorNumeric - Performs numeric Cholesky factorization 3376 of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and 3377 `MatCholeskyFactorSymbolic()`. 3378 3379 Collective 3380 3381 Input Parameters: 3382 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored 3383 . mat - the initial matrix that is to be factored 3384 - info - options for factorization 3385 3386 Level: developer 3387 3388 Note: 3389 Most users should employ the `KSP` interface for linear solvers 3390 instead of working directly with matrix algebra routines such as this. 3391 See, e.g., `KSPCreate()`. 3392 3393 Developer Notes: 3394 The Fortran interface is not autogenerated as the 3395 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3396 3397 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()` 3398 @*/ 3399 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3400 { 3401 MatFactorInfo tinfo; 3402 3403 PetscFunctionBegin; 3404 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3405 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3406 PetscValidType(fact, 1); 3407 PetscValidType(mat, 2); 3408 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3409 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, 3410 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3411 MatCheckPreallocated(mat, 2); 3412 if (!info) { 3413 PetscCall(MatFactorInfoInitialize(&tinfo)); 3414 info = &tinfo; 3415 } 3416 3417 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3418 else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0)); 3419 PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info); 3420 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3421 else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0)); 3422 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3423 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3424 PetscFunctionReturn(PETSC_SUCCESS); 3425 } 3426 3427 /*@ 3428 MatQRFactor - Performs in-place QR factorization of matrix. 3429 3430 Collective 3431 3432 Input Parameters: 3433 + mat - the matrix 3434 . col - column permutation 3435 - info - options for factorization, includes 3436 .vb 3437 fill - expected fill as ratio of original fill. 3438 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3439 Run with the option -info to determine an optimal value to use 3440 .ve 3441 3442 Level: developer 3443 3444 Notes: 3445 Most users should employ the `KSP` interface for linear solvers 3446 instead of working directly with matrix algebra routines such as this. 3447 See, e.g., `KSPCreate()`. 3448 3449 This changes the state of the matrix to a factored matrix; it cannot be used 3450 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3451 3452 Developer Notes: 3453 The Fortran interface is not autogenerated as the 3454 interface definition cannot be generated correctly [due to MatFactorInfo] 3455 3456 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`, 3457 `MatSetUnfactored()` 3458 @*/ 3459 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info) 3460 { 3461 PetscFunctionBegin; 3462 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3463 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2); 3464 if (info) PetscAssertPointer(info, 3); 3465 PetscValidType(mat, 1); 3466 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3467 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3468 MatCheckPreallocated(mat, 1); 3469 PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0)); 3470 PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info)); 3471 PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0)); 3472 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3473 PetscFunctionReturn(PETSC_SUCCESS); 3474 } 3475 3476 /*@ 3477 MatQRFactorSymbolic - Performs symbolic QR factorization of matrix. 3478 Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`. 3479 3480 Collective 3481 3482 Input Parameters: 3483 + fact - the factor matrix obtained with `MatGetFactor()` 3484 . mat - the matrix 3485 . col - column permutation 3486 - info - options for factorization, includes 3487 .vb 3488 fill - expected fill as ratio of original fill. 3489 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3490 Run with the option -info to determine an optimal value to use 3491 .ve 3492 3493 Level: developer 3494 3495 Note: 3496 Most users should employ the `KSP` interface for linear solvers 3497 instead of working directly with matrix algebra routines such as this. 3498 See, e.g., `KSPCreate()`. 3499 3500 Developer Notes: 3501 The Fortran interface is not autogenerated as the 3502 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3503 3504 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfoInitialize()` 3505 @*/ 3506 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info) 3507 { 3508 MatFactorInfo tinfo; 3509 3510 PetscFunctionBegin; 3511 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3512 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3513 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3514 if (info) PetscAssertPointer(info, 4); 3515 PetscValidType(fact, 1); 3516 PetscValidType(mat, 2); 3517 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3518 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3519 MatCheckPreallocated(mat, 2); 3520 if (!info) { 3521 PetscCall(MatFactorInfoInitialize(&tinfo)); 3522 info = &tinfo; 3523 } 3524 3525 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3526 PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info)); 3527 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3528 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3529 PetscFunctionReturn(PETSC_SUCCESS); 3530 } 3531 3532 /*@ 3533 MatQRFactorNumeric - Performs numeric QR factorization of a matrix. 3534 Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`. 3535 3536 Collective 3537 3538 Input Parameters: 3539 + fact - the factor matrix obtained with `MatGetFactor()` 3540 . mat - the matrix 3541 - info - options for factorization 3542 3543 Level: developer 3544 3545 Notes: 3546 See `MatQRFactor()` for in-place factorization. 3547 3548 Most users should employ the `KSP` interface for linear solvers 3549 instead of working directly with matrix algebra routines such as this. 3550 See, e.g., `KSPCreate()`. 3551 3552 Developer Notes: 3553 The Fortran interface is not autogenerated as the 3554 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3555 3556 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()` 3557 @*/ 3558 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3559 { 3560 MatFactorInfo tinfo; 3561 3562 PetscFunctionBegin; 3563 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3564 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3565 PetscValidType(fact, 1); 3566 PetscValidType(mat, 2); 3567 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3568 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, 3569 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3570 3571 MatCheckPreallocated(mat, 2); 3572 if (!info) { 3573 PetscCall(MatFactorInfoInitialize(&tinfo)); 3574 info = &tinfo; 3575 } 3576 3577 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3578 else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0)); 3579 PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info)); 3580 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3581 else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0)); 3582 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3583 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3584 PetscFunctionReturn(PETSC_SUCCESS); 3585 } 3586 3587 /*@ 3588 MatSolve - Solves A x = b, given a factored matrix. 3589 3590 Neighbor-wise Collective 3591 3592 Input Parameters: 3593 + mat - the factored matrix 3594 - b - the right-hand-side vector 3595 3596 Output Parameter: 3597 . x - the result vector 3598 3599 Level: developer 3600 3601 Notes: 3602 The vectors `b` and `x` cannot be the same. I.e., one cannot 3603 call `MatSolve`(A,x,x). 3604 3605 Most users should employ the `KSP` interface for linear solvers 3606 instead of working directly with matrix algebra routines such as this. 3607 See, e.g., `KSPCreate()`. 3608 3609 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3610 @*/ 3611 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x) 3612 { 3613 PetscFunctionBegin; 3614 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3615 PetscValidType(mat, 1); 3616 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3617 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3618 PetscCheckSameComm(mat, 1, b, 2); 3619 PetscCheckSameComm(mat, 1, x, 3); 3620 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3621 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); 3622 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); 3623 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); 3624 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3625 MatCheckPreallocated(mat, 1); 3626 3627 PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0)); 3628 if (mat->factorerrortype) { 3629 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3630 PetscCall(VecSetInf(x)); 3631 } else PetscUseTypeMethod(mat, solve, b, x); 3632 PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0)); 3633 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3634 PetscFunctionReturn(PETSC_SUCCESS); 3635 } 3636 3637 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans) 3638 { 3639 Vec b, x; 3640 PetscInt N, i; 3641 PetscErrorCode (*f)(Mat, Vec, Vec); 3642 PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE; 3643 3644 PetscFunctionBegin; 3645 if (A->factorerrortype) { 3646 PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype)); 3647 PetscCall(MatSetInf(X)); 3648 PetscFunctionReturn(PETSC_SUCCESS); 3649 } 3650 f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose; 3651 PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 3652 PetscCall(MatBoundToCPU(A, &Abound)); 3653 if (!Abound) { 3654 PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3655 PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3656 } 3657 #if PetscDefined(HAVE_CUDA) 3658 if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B)); 3659 if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X)); 3660 #elif PetscDefined(HAVE_HIP) 3661 if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B)); 3662 if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X)); 3663 #endif 3664 PetscCall(MatGetSize(B, NULL, &N)); 3665 for (i = 0; i < N; i++) { 3666 PetscCall(MatDenseGetColumnVecRead(B, i, &b)); 3667 PetscCall(MatDenseGetColumnVecWrite(X, i, &x)); 3668 PetscCall((*f)(A, b, x)); 3669 PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x)); 3670 PetscCall(MatDenseRestoreColumnVecRead(B, i, &b)); 3671 } 3672 if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B)); 3673 if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X)); 3674 PetscFunctionReturn(PETSC_SUCCESS); 3675 } 3676 3677 /*@ 3678 MatMatSolve - Solves A X = B, given a factored matrix. 3679 3680 Neighbor-wise Collective 3681 3682 Input Parameters: 3683 + A - the factored matrix 3684 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS) 3685 3686 Output Parameter: 3687 . X - the result matrix (dense matrix) 3688 3689 Level: developer 3690 3691 Note: 3692 If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`; 3693 otherwise, `B` and `X` cannot be the same. 3694 3695 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3696 @*/ 3697 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X) 3698 { 3699 PetscFunctionBegin; 3700 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3701 PetscValidType(A, 1); 3702 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3703 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3704 PetscCheckSameComm(A, 1, B, 2); 3705 PetscCheckSameComm(A, 1, X, 3); 3706 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); 3707 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); 3708 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"); 3709 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3710 MatCheckPreallocated(A, 1); 3711 3712 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3713 if (!A->ops->matsolve) { 3714 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name)); 3715 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE)); 3716 } else PetscUseTypeMethod(A, matsolve, B, X); 3717 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3718 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3719 PetscFunctionReturn(PETSC_SUCCESS); 3720 } 3721 3722 /*@ 3723 MatMatSolveTranspose - Solves A^T X = B, given a factored matrix. 3724 3725 Neighbor-wise Collective 3726 3727 Input Parameters: 3728 + A - the factored matrix 3729 - B - the right-hand-side matrix (`MATDENSE` matrix) 3730 3731 Output Parameter: 3732 . X - the result matrix (dense matrix) 3733 3734 Level: developer 3735 3736 Note: 3737 The matrices `B` and `X` cannot be the same. I.e., one cannot 3738 call `MatMatSolveTranspose`(A,X,X). 3739 3740 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()` 3741 @*/ 3742 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X) 3743 { 3744 PetscFunctionBegin; 3745 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3746 PetscValidType(A, 1); 3747 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3748 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3749 PetscCheckSameComm(A, 1, B, 2); 3750 PetscCheckSameComm(A, 1, X, 3); 3751 PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3752 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); 3753 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); 3754 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); 3755 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"); 3756 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3757 MatCheckPreallocated(A, 1); 3758 3759 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3760 if (!A->ops->matsolvetranspose) { 3761 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name)); 3762 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE)); 3763 } else PetscUseTypeMethod(A, matsolvetranspose, B, X); 3764 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3765 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3766 PetscFunctionReturn(PETSC_SUCCESS); 3767 } 3768 3769 /*@ 3770 MatMatTransposeSolve - Solves A X = B^T, given a factored matrix. 3771 3772 Neighbor-wise Collective 3773 3774 Input Parameters: 3775 + A - the factored matrix 3776 - Bt - the transpose of right-hand-side matrix as a `MATDENSE` 3777 3778 Output Parameter: 3779 . X - the result matrix (dense matrix) 3780 3781 Level: developer 3782 3783 Note: 3784 For MUMPS, it only supports centralized sparse compressed column format on the host processor for right hand side matrix. User must create B^T in sparse compressed row 3785 format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`. 3786 3787 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3788 @*/ 3789 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X) 3790 { 3791 PetscFunctionBegin; 3792 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3793 PetscValidType(A, 1); 3794 PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2); 3795 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3796 PetscCheckSameComm(A, 1, Bt, 2); 3797 PetscCheckSameComm(A, 1, X, 3); 3798 3799 PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3800 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); 3801 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); 3802 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"); 3803 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3804 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3805 MatCheckPreallocated(A, 1); 3806 3807 PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0)); 3808 PetscUseTypeMethod(A, mattransposesolve, Bt, X); 3809 PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0)); 3810 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3811 PetscFunctionReturn(PETSC_SUCCESS); 3812 } 3813 3814 /*@ 3815 MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or 3816 U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U, 3817 3818 Neighbor-wise Collective 3819 3820 Input Parameters: 3821 + mat - the factored matrix 3822 - b - the right-hand-side vector 3823 3824 Output Parameter: 3825 . x - the result vector 3826 3827 Level: developer 3828 3829 Notes: 3830 `MatSolve()` should be used for most applications, as it performs 3831 a forward solve followed by a backward solve. 3832 3833 The vectors `b` and `x` cannot be the same, i.e., one cannot 3834 call `MatForwardSolve`(A,x,x). 3835 3836 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3837 the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet. 3838 `MatForwardSolve()` solves U^T*D y = b, and 3839 `MatBackwardSolve()` solves U x = y. 3840 Thus they do not provide a symmetric preconditioner. 3841 3842 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()` 3843 @*/ 3844 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x) 3845 { 3846 PetscFunctionBegin; 3847 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3848 PetscValidType(mat, 1); 3849 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3850 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3851 PetscCheckSameComm(mat, 1, b, 2); 3852 PetscCheckSameComm(mat, 1, x, 3); 3853 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3854 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); 3855 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); 3856 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); 3857 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3858 MatCheckPreallocated(mat, 1); 3859 3860 PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0)); 3861 PetscUseTypeMethod(mat, forwardsolve, b, x); 3862 PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0)); 3863 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3864 PetscFunctionReturn(PETSC_SUCCESS); 3865 } 3866 3867 /*@ 3868 MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU. 3869 D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U, 3870 3871 Neighbor-wise Collective 3872 3873 Input Parameters: 3874 + mat - the factored matrix 3875 - b - the right-hand-side vector 3876 3877 Output Parameter: 3878 . x - the result vector 3879 3880 Level: developer 3881 3882 Notes: 3883 `MatSolve()` should be used for most applications, as it performs 3884 a forward solve followed by a backward solve. 3885 3886 The vectors `b` and `x` cannot be the same. I.e., one cannot 3887 call `MatBackwardSolve`(A,x,x). 3888 3889 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3890 the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet. 3891 `MatForwardSolve()` solves U^T*D y = b, and 3892 `MatBackwardSolve()` solves U x = y. 3893 Thus they do not provide a symmetric preconditioner. 3894 3895 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()` 3896 @*/ 3897 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x) 3898 { 3899 PetscFunctionBegin; 3900 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3901 PetscValidType(mat, 1); 3902 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3903 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3904 PetscCheckSameComm(mat, 1, b, 2); 3905 PetscCheckSameComm(mat, 1, x, 3); 3906 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3907 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); 3908 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); 3909 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); 3910 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3911 MatCheckPreallocated(mat, 1); 3912 3913 PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0)); 3914 PetscUseTypeMethod(mat, backwardsolve, b, x); 3915 PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0)); 3916 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3917 PetscFunctionReturn(PETSC_SUCCESS); 3918 } 3919 3920 /*@ 3921 MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix. 3922 3923 Neighbor-wise Collective 3924 3925 Input Parameters: 3926 + mat - the factored matrix 3927 . b - the right-hand-side vector 3928 - y - the vector to be added to 3929 3930 Output Parameter: 3931 . x - the result vector 3932 3933 Level: developer 3934 3935 Note: 3936 The vectors `b` and `x` cannot be the same. I.e., one cannot 3937 call `MatSolveAdd`(A,x,y,x). 3938 3939 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3940 @*/ 3941 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x) 3942 { 3943 PetscScalar one = 1.0; 3944 Vec tmp; 3945 3946 PetscFunctionBegin; 3947 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3948 PetscValidType(mat, 1); 3949 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 3950 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3951 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 3952 PetscCheckSameComm(mat, 1, b, 2); 3953 PetscCheckSameComm(mat, 1, y, 3); 3954 PetscCheckSameComm(mat, 1, x, 4); 3955 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3956 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); 3957 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); 3958 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); 3959 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); 3960 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); 3961 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3962 MatCheckPreallocated(mat, 1); 3963 3964 PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y)); 3965 if (mat->factorerrortype) { 3966 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3967 PetscCall(VecSetInf(x)); 3968 } else if (mat->ops->solveadd) { 3969 PetscUseTypeMethod(mat, solveadd, b, y, x); 3970 } else { 3971 /* do the solve then the add manually */ 3972 if (x != y) { 3973 PetscCall(MatSolve(mat, b, x)); 3974 PetscCall(VecAXPY(x, one, y)); 3975 } else { 3976 PetscCall(VecDuplicate(x, &tmp)); 3977 PetscCall(VecCopy(x, tmp)); 3978 PetscCall(MatSolve(mat, b, x)); 3979 PetscCall(VecAXPY(x, one, tmp)); 3980 PetscCall(VecDestroy(&tmp)); 3981 } 3982 } 3983 PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y)); 3984 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3985 PetscFunctionReturn(PETSC_SUCCESS); 3986 } 3987 3988 /*@ 3989 MatSolveTranspose - Solves A' x = 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 3997 Output Parameter: 3998 . x - the result vector 3999 4000 Level: developer 4001 4002 Notes: 4003 The vectors `b` and `x` cannot be the same. I.e., one cannot 4004 call `MatSolveTranspose`(A,x,x). 4005 4006 Most users should employ the `KSP` interface for linear solvers 4007 instead of working directly with matrix algebra routines such as this. 4008 See, e.g., `KSPCreate()`. 4009 4010 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()` 4011 @*/ 4012 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x) 4013 { 4014 PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose; 4015 4016 PetscFunctionBegin; 4017 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4018 PetscValidType(mat, 1); 4019 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4020 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 4021 PetscCheckSameComm(mat, 1, b, 2); 4022 PetscCheckSameComm(mat, 1, x, 3); 4023 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4024 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); 4025 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); 4026 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4027 MatCheckPreallocated(mat, 1); 4028 PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0)); 4029 if (mat->factorerrortype) { 4030 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4031 PetscCall(VecSetInf(x)); 4032 } else { 4033 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name); 4034 PetscCall((*f)(mat, b, x)); 4035 } 4036 PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0)); 4037 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4038 PetscFunctionReturn(PETSC_SUCCESS); 4039 } 4040 4041 /*@ 4042 MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a 4043 factored matrix. 4044 4045 Neighbor-wise Collective 4046 4047 Input Parameters: 4048 + mat - the factored matrix 4049 . b - the right-hand-side vector 4050 - y - the vector to be added to 4051 4052 Output Parameter: 4053 . x - the result vector 4054 4055 Level: developer 4056 4057 Note: 4058 The vectors `b` and `x` cannot be the same. I.e., one cannot 4059 call `MatSolveTransposeAdd`(A,x,y,x). 4060 4061 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()` 4062 @*/ 4063 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x) 4064 { 4065 PetscScalar one = 1.0; 4066 Vec tmp; 4067 PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd; 4068 4069 PetscFunctionBegin; 4070 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4071 PetscValidType(mat, 1); 4072 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4073 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4074 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4075 PetscCheckSameComm(mat, 1, b, 2); 4076 PetscCheckSameComm(mat, 1, y, 3); 4077 PetscCheckSameComm(mat, 1, x, 4); 4078 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4079 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); 4080 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); 4081 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); 4082 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); 4083 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4084 MatCheckPreallocated(mat, 1); 4085 4086 PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y)); 4087 if (mat->factorerrortype) { 4088 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4089 PetscCall(VecSetInf(x)); 4090 } else if (f) { 4091 PetscCall((*f)(mat, b, y, x)); 4092 } else { 4093 /* do the solve then the add manually */ 4094 if (x != y) { 4095 PetscCall(MatSolveTranspose(mat, b, x)); 4096 PetscCall(VecAXPY(x, one, y)); 4097 } else { 4098 PetscCall(VecDuplicate(x, &tmp)); 4099 PetscCall(VecCopy(x, tmp)); 4100 PetscCall(MatSolveTranspose(mat, b, x)); 4101 PetscCall(VecAXPY(x, one, tmp)); 4102 PetscCall(VecDestroy(&tmp)); 4103 } 4104 } 4105 PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y)); 4106 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4107 PetscFunctionReturn(PETSC_SUCCESS); 4108 } 4109 4110 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 4111 /*@ 4112 MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps. 4113 4114 Neighbor-wise Collective 4115 4116 Input Parameters: 4117 + mat - the matrix 4118 . b - the right hand side 4119 . omega - the relaxation factor 4120 . flag - flag indicating the type of SOR (see below) 4121 . shift - diagonal shift 4122 . its - the number of iterations 4123 - lits - the number of local iterations 4124 4125 Output Parameter: 4126 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess) 4127 4128 SOR Flags: 4129 + `SOR_FORWARD_SWEEP` - forward SOR 4130 . `SOR_BACKWARD_SWEEP` - backward SOR 4131 . `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR) 4132 . `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR 4133 . `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR 4134 . `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR 4135 . `SOR_EISENSTAT` - SOR with Eisenstat trick 4136 . `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies 4137 upper/lower triangular part of matrix to 4138 vector (with omega) 4139 - `SOR_ZERO_INITIAL_GUESS` - zero initial guess 4140 4141 Level: developer 4142 4143 Notes: 4144 `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and 4145 `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings 4146 on each processor. 4147 4148 Application programmers will not generally use `MatSOR()` directly, 4149 but instead will employ the `KSP`/`PC` interface. 4150 4151 For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing 4152 4153 Most users should employ the `KSP` interface for linear solvers 4154 instead of working directly with matrix algebra routines such as this. 4155 See, e.g., `KSPCreate()`. 4156 4157 Vectors `x` and `b` CANNOT be the same 4158 4159 The flags are implemented as bitwise inclusive or operations. 4160 For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`) 4161 to specify a zero initial guess for SSOR. 4162 4163 Developer Notes: 4164 We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes 4165 4166 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()` 4167 @*/ 4168 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x) 4169 { 4170 PetscFunctionBegin; 4171 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4172 PetscValidType(mat, 1); 4173 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4174 PetscValidHeaderSpecific(x, VEC_CLASSID, 8); 4175 PetscCheckSameComm(mat, 1, b, 2); 4176 PetscCheckSameComm(mat, 1, x, 8); 4177 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4178 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4179 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); 4180 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); 4181 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); 4182 PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its); 4183 PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits); 4184 PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same"); 4185 4186 MatCheckPreallocated(mat, 1); 4187 PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0)); 4188 PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x); 4189 PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0)); 4190 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4191 PetscFunctionReturn(PETSC_SUCCESS); 4192 } 4193 4194 /* 4195 Default matrix copy routine. 4196 */ 4197 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str) 4198 { 4199 PetscInt i, rstart = 0, rend = 0, nz; 4200 const PetscInt *cwork; 4201 const PetscScalar *vwork; 4202 4203 PetscFunctionBegin; 4204 if (B->assembled) PetscCall(MatZeroEntries(B)); 4205 if (str == SAME_NONZERO_PATTERN) { 4206 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 4207 for (i = rstart; i < rend; i++) { 4208 PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork)); 4209 PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES)); 4210 PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork)); 4211 } 4212 } else { 4213 PetscCall(MatAYPX(B, 0.0, A, str)); 4214 } 4215 PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 4216 PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 4217 PetscFunctionReturn(PETSC_SUCCESS); 4218 } 4219 4220 /*@ 4221 MatCopy - Copies a matrix to another matrix. 4222 4223 Collective 4224 4225 Input Parameters: 4226 + A - the matrix 4227 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN` 4228 4229 Output Parameter: 4230 . B - where the copy is put 4231 4232 Level: intermediate 4233 4234 Notes: 4235 If you use `SAME_NONZERO_PATTERN` then the two matrices must have the same nonzero pattern or the routine will crash. 4236 4237 `MatCopy()` copies the matrix entries of a matrix to another existing 4238 matrix (after first zeroing the second matrix). A related routine is 4239 `MatConvert()`, which first creates a new matrix and then copies the data. 4240 4241 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()` 4242 @*/ 4243 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str) 4244 { 4245 PetscInt i; 4246 4247 PetscFunctionBegin; 4248 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 4249 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 4250 PetscValidType(A, 1); 4251 PetscValidType(B, 2); 4252 PetscCheckSameComm(A, 1, B, 2); 4253 MatCheckPreallocated(B, 2); 4254 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4255 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4256 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, 4257 A->cmap->N, B->cmap->N); 4258 MatCheckPreallocated(A, 1); 4259 if (A == B) PetscFunctionReturn(PETSC_SUCCESS); 4260 4261 PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0)); 4262 if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str); 4263 else PetscCall(MatCopy_Basic(A, B, str)); 4264 4265 B->stencil.dim = A->stencil.dim; 4266 B->stencil.noc = A->stencil.noc; 4267 for (i = 0; i <= A->stencil.dim + (A->stencil.noc ? 0 : -1); i++) { 4268 B->stencil.dims[i] = A->stencil.dims[i]; 4269 B->stencil.starts[i] = A->stencil.starts[i]; 4270 } 4271 4272 PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0)); 4273 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4274 PetscFunctionReturn(PETSC_SUCCESS); 4275 } 4276 4277 /*@C 4278 MatConvert - Converts a matrix to another matrix, either of the same 4279 or different type. 4280 4281 Collective 4282 4283 Input Parameters: 4284 + mat - the matrix 4285 . newtype - new matrix type. Use `MATSAME` to create a new matrix of the 4286 same type as the original matrix. 4287 - reuse - denotes if the destination matrix is to be created or reused. 4288 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 4289 `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). 4290 4291 Output Parameter: 4292 . M - pointer to place new matrix 4293 4294 Level: intermediate 4295 4296 Notes: 4297 `MatConvert()` first creates a new matrix and then copies the data from 4298 the first matrix. A related routine is `MatCopy()`, which copies the matrix 4299 entries of one matrix to another already existing matrix context. 4300 4301 Cannot be used to convert a sequential matrix to parallel or parallel to sequential, 4302 the MPI communicator of the generated matrix is always the same as the communicator 4303 of the input matrix. 4304 4305 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 4306 @*/ 4307 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M) 4308 { 4309 PetscBool sametype, issame, flg; 4310 PetscBool3 issymmetric, ishermitian; 4311 char convname[256], mtype[256]; 4312 Mat B; 4313 4314 PetscFunctionBegin; 4315 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4316 PetscValidType(mat, 1); 4317 PetscAssertPointer(M, 4); 4318 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4319 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4320 MatCheckPreallocated(mat, 1); 4321 4322 PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg)); 4323 if (flg) newtype = mtype; 4324 4325 PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype)); 4326 PetscCall(PetscStrcmp(newtype, "same", &issame)); 4327 PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix"); 4328 if (reuse == MAT_REUSE_MATRIX) { 4329 PetscValidHeaderSpecific(*M, MAT_CLASSID, 4); 4330 PetscCheck(mat != *M, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX"); 4331 } 4332 4333 if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) { 4334 PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4335 PetscFunctionReturn(PETSC_SUCCESS); 4336 } 4337 4338 /* Cache Mat options because some converters use MatHeaderReplace */ 4339 issymmetric = mat->symmetric; 4340 ishermitian = mat->hermitian; 4341 4342 if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) { 4343 PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4344 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4345 } else { 4346 PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL; 4347 const char *prefix[3] = {"seq", "mpi", ""}; 4348 PetscInt i; 4349 /* 4350 Order of precedence: 4351 0) See if newtype is a superclass of the current matrix. 4352 1) See if a specialized converter is known to the current matrix. 4353 2) See if a specialized converter is known to the desired matrix class. 4354 3) See if a good general converter is registered for the desired class 4355 (as of 6/27/03 only MATMPIADJ falls into this category). 4356 4) See if a good general converter is known for the current matrix. 4357 5) Use a really basic converter. 4358 */ 4359 4360 /* 0) See if newtype is a superclass of the current matrix. 4361 i.e mat is mpiaij and newtype is aij */ 4362 for (i = 0; i < 2; i++) { 4363 PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname))); 4364 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4365 PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg)); 4366 PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg)); 4367 if (flg) { 4368 if (reuse == MAT_INPLACE_MATRIX) { 4369 PetscCall(PetscInfo(mat, "Early return\n")); 4370 PetscFunctionReturn(PETSC_SUCCESS); 4371 } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) { 4372 PetscCall(PetscInfo(mat, "Calling MatDuplicate\n")); 4373 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4374 PetscFunctionReturn(PETSC_SUCCESS); 4375 } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) { 4376 PetscCall(PetscInfo(mat, "Calling MatCopy\n")); 4377 PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN)); 4378 PetscFunctionReturn(PETSC_SUCCESS); 4379 } 4380 } 4381 } 4382 /* 1) See if a specialized converter is known to the current matrix and the desired class */ 4383 for (i = 0; i < 3; i++) { 4384 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4385 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4386 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4387 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4388 PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname))); 4389 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4390 PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv)); 4391 PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv)); 4392 if (conv) goto foundconv; 4393 } 4394 4395 /* 2) See if a specialized converter is known to the desired matrix class. */ 4396 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B)); 4397 PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 4398 PetscCall(MatSetType(B, newtype)); 4399 for (i = 0; i < 3; i++) { 4400 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4401 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4402 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4403 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4404 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4405 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4406 PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv)); 4407 PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv)); 4408 if (conv) { 4409 PetscCall(MatDestroy(&B)); 4410 goto foundconv; 4411 } 4412 } 4413 4414 /* 3) See if a good general converter is registered for the desired class */ 4415 conv = B->ops->convertfrom; 4416 PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv)); 4417 PetscCall(MatDestroy(&B)); 4418 if (conv) goto foundconv; 4419 4420 /* 4) See if a good general converter is known for the current matrix */ 4421 if (mat->ops->convert) conv = mat->ops->convert; 4422 PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv)); 4423 if (conv) goto foundconv; 4424 4425 /* 5) Use a really basic converter. */ 4426 PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n")); 4427 conv = MatConvert_Basic; 4428 4429 foundconv: 4430 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4431 PetscCall((*conv)(mat, newtype, reuse, M)); 4432 if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) { 4433 /* the block sizes must be same if the mappings are copied over */ 4434 (*M)->rmap->bs = mat->rmap->bs; 4435 (*M)->cmap->bs = mat->cmap->bs; 4436 PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping)); 4437 PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping)); 4438 (*M)->rmap->mapping = mat->rmap->mapping; 4439 (*M)->cmap->mapping = mat->cmap->mapping; 4440 } 4441 (*M)->stencil.dim = mat->stencil.dim; 4442 (*M)->stencil.noc = mat->stencil.noc; 4443 for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) { 4444 (*M)->stencil.dims[i] = mat->stencil.dims[i]; 4445 (*M)->stencil.starts[i] = mat->stencil.starts[i]; 4446 } 4447 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4448 } 4449 PetscCall(PetscObjectStateIncrease((PetscObject)*M)); 4450 4451 /* Copy Mat options */ 4452 if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE)); 4453 else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE)); 4454 if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE)); 4455 else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE)); 4456 PetscFunctionReturn(PETSC_SUCCESS); 4457 } 4458 4459 /*@C 4460 MatFactorGetSolverType - Returns name of the package providing the factorization routines 4461 4462 Not Collective 4463 4464 Input Parameter: 4465 . mat - the matrix, must be a factored matrix 4466 4467 Output Parameter: 4468 . type - the string name of the package (do not free this string) 4469 4470 Level: intermediate 4471 4472 Fortran Notes: 4473 Pass in an empty string and the package name will be copied into it. Make sure the string is long enough. 4474 4475 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()` 4476 @*/ 4477 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type) 4478 { 4479 PetscErrorCode (*conv)(Mat, MatSolverType *); 4480 4481 PetscFunctionBegin; 4482 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4483 PetscValidType(mat, 1); 4484 PetscAssertPointer(type, 2); 4485 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 4486 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv)); 4487 if (conv) PetscCall((*conv)(mat, type)); 4488 else *type = MATSOLVERPETSC; 4489 PetscFunctionReturn(PETSC_SUCCESS); 4490 } 4491 4492 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType; 4493 struct _MatSolverTypeForSpecifcType { 4494 MatType mtype; 4495 /* no entry for MAT_FACTOR_NONE */ 4496 PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *); 4497 MatSolverTypeForSpecifcType next; 4498 }; 4499 4500 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder; 4501 struct _MatSolverTypeHolder { 4502 char *name; 4503 MatSolverTypeForSpecifcType handlers; 4504 MatSolverTypeHolder next; 4505 }; 4506 4507 static MatSolverTypeHolder MatSolverTypeHolders = NULL; 4508 4509 /*@C 4510 MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type 4511 4512 Input Parameters: 4513 + package - name of the package, for example petsc or superlu 4514 . mtype - the matrix type that works with this package 4515 . ftype - the type of factorization supported by the package 4516 - createfactor - routine that will create the factored matrix ready to be used 4517 4518 Level: developer 4519 4520 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()` 4521 @*/ 4522 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *)) 4523 { 4524 MatSolverTypeHolder next = MatSolverTypeHolders, prev = NULL; 4525 PetscBool flg; 4526 MatSolverTypeForSpecifcType inext, iprev = NULL; 4527 4528 PetscFunctionBegin; 4529 PetscCall(MatInitializePackage()); 4530 if (!next) { 4531 PetscCall(PetscNew(&MatSolverTypeHolders)); 4532 PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name)); 4533 PetscCall(PetscNew(&MatSolverTypeHolders->handlers)); 4534 PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype)); 4535 MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor; 4536 PetscFunctionReturn(PETSC_SUCCESS); 4537 } 4538 while (next) { 4539 PetscCall(PetscStrcasecmp(package, next->name, &flg)); 4540 if (flg) { 4541 PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers"); 4542 inext = next->handlers; 4543 while (inext) { 4544 PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg)); 4545 if (flg) { 4546 inext->createfactor[(int)ftype - 1] = createfactor; 4547 PetscFunctionReturn(PETSC_SUCCESS); 4548 } 4549 iprev = inext; 4550 inext = inext->next; 4551 } 4552 PetscCall(PetscNew(&iprev->next)); 4553 PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype)); 4554 iprev->next->createfactor[(int)ftype - 1] = createfactor; 4555 PetscFunctionReturn(PETSC_SUCCESS); 4556 } 4557 prev = next; 4558 next = next->next; 4559 } 4560 PetscCall(PetscNew(&prev->next)); 4561 PetscCall(PetscStrallocpy(package, &prev->next->name)); 4562 PetscCall(PetscNew(&prev->next->handlers)); 4563 PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype)); 4564 prev->next->handlers->createfactor[(int)ftype - 1] = createfactor; 4565 PetscFunctionReturn(PETSC_SUCCESS); 4566 } 4567 4568 /*@C 4569 MatSolverTypeGet - Gets the function that creates the factor matrix if it exist 4570 4571 Input Parameters: 4572 + type - name of the package, for example petsc or superlu 4573 . ftype - the type of factorization supported by the type 4574 - mtype - the matrix type that works with this type 4575 4576 Output Parameters: 4577 + foundtype - `PETSC_TRUE` if the type was registered 4578 . foundmtype - `PETSC_TRUE` if the type supports the requested mtype 4579 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found 4580 4581 Level: developer 4582 4583 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()` 4584 @*/ 4585 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *)) 4586 { 4587 MatSolverTypeHolder next = MatSolverTypeHolders; 4588 PetscBool flg; 4589 MatSolverTypeForSpecifcType inext; 4590 4591 PetscFunctionBegin; 4592 if (foundtype) *foundtype = PETSC_FALSE; 4593 if (foundmtype) *foundmtype = PETSC_FALSE; 4594 if (createfactor) *createfactor = NULL; 4595 4596 if (type) { 4597 while (next) { 4598 PetscCall(PetscStrcasecmp(type, next->name, &flg)); 4599 if (flg) { 4600 if (foundtype) *foundtype = PETSC_TRUE; 4601 inext = next->handlers; 4602 while (inext) { 4603 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4604 if (flg) { 4605 if (foundmtype) *foundmtype = PETSC_TRUE; 4606 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4607 PetscFunctionReturn(PETSC_SUCCESS); 4608 } 4609 inext = inext->next; 4610 } 4611 } 4612 next = next->next; 4613 } 4614 } else { 4615 while (next) { 4616 inext = next->handlers; 4617 while (inext) { 4618 PetscCall(PetscStrcmp(mtype, inext->mtype, &flg)); 4619 if (flg && inext->createfactor[(int)ftype - 1]) { 4620 if (foundtype) *foundtype = PETSC_TRUE; 4621 if (foundmtype) *foundmtype = PETSC_TRUE; 4622 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4623 PetscFunctionReturn(PETSC_SUCCESS); 4624 } 4625 inext = inext->next; 4626 } 4627 next = next->next; 4628 } 4629 /* try with base classes inext->mtype */ 4630 next = MatSolverTypeHolders; 4631 while (next) { 4632 inext = next->handlers; 4633 while (inext) { 4634 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4635 if (flg && inext->createfactor[(int)ftype - 1]) { 4636 if (foundtype) *foundtype = PETSC_TRUE; 4637 if (foundmtype) *foundmtype = PETSC_TRUE; 4638 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4639 PetscFunctionReturn(PETSC_SUCCESS); 4640 } 4641 inext = inext->next; 4642 } 4643 next = next->next; 4644 } 4645 } 4646 PetscFunctionReturn(PETSC_SUCCESS); 4647 } 4648 4649 PetscErrorCode MatSolverTypeDestroy(void) 4650 { 4651 MatSolverTypeHolder next = MatSolverTypeHolders, prev; 4652 MatSolverTypeForSpecifcType inext, iprev; 4653 4654 PetscFunctionBegin; 4655 while (next) { 4656 PetscCall(PetscFree(next->name)); 4657 inext = next->handlers; 4658 while (inext) { 4659 PetscCall(PetscFree(inext->mtype)); 4660 iprev = inext; 4661 inext = inext->next; 4662 PetscCall(PetscFree(iprev)); 4663 } 4664 prev = next; 4665 next = next->next; 4666 PetscCall(PetscFree(prev)); 4667 } 4668 MatSolverTypeHolders = NULL; 4669 PetscFunctionReturn(PETSC_SUCCESS); 4670 } 4671 4672 /*@C 4673 MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4674 4675 Logically Collective 4676 4677 Input Parameter: 4678 . mat - the matrix 4679 4680 Output Parameter: 4681 . flg - `PETSC_TRUE` if uses the ordering 4682 4683 Level: developer 4684 4685 Note: 4686 Most internal PETSc factorizations use the ordering passed to the factorization routine but external 4687 packages do not, thus we want to skip generating the ordering when it is not needed or used. 4688 4689 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4690 @*/ 4691 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg) 4692 { 4693 PetscFunctionBegin; 4694 *flg = mat->canuseordering; 4695 PetscFunctionReturn(PETSC_SUCCESS); 4696 } 4697 4698 /*@C 4699 MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object 4700 4701 Logically Collective 4702 4703 Input Parameters: 4704 + mat - the matrix obtained with `MatGetFactor()` 4705 - ftype - the factorization type to be used 4706 4707 Output Parameter: 4708 . otype - the preferred ordering type 4709 4710 Level: developer 4711 4712 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4713 @*/ 4714 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype) 4715 { 4716 PetscFunctionBegin; 4717 *otype = mat->preferredordering[ftype]; 4718 PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering"); 4719 PetscFunctionReturn(PETSC_SUCCESS); 4720 } 4721 4722 /*@C 4723 MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic() 4724 4725 Collective 4726 4727 Input Parameters: 4728 + mat - the matrix 4729 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4730 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4731 4732 Output Parameter: 4733 . f - the factor matrix used with MatXXFactorSymbolic() calls. Can be `NULL` in some cases, see notes below. 4734 4735 Options Database Key: 4736 . -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory. 4737 One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices. 4738 4739 Level: intermediate 4740 4741 Notes: 4742 The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization 4743 types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime. 4744 4745 Users usually access the factorization solvers via `KSP` 4746 4747 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4748 such as pastix, superlu, mumps etc. 4749 4750 PETSc must have been ./configure to use the external solver, using the option --download-package 4751 4752 Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption 4753 where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set 4754 call `MatSetOptionsPrefixFactor()` on the originating matrix or `MatSetOptionsPrefix()` on the resulting factor matrix. 4755 4756 Developer Notes: 4757 This should actually be called `MatCreateFactor()` since it creates a new factor object 4758 4759 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, 4760 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4761 @*/ 4762 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f) 4763 { 4764 PetscBool foundtype, foundmtype; 4765 PetscErrorCode (*conv)(Mat, MatFactorType, Mat *); 4766 4767 PetscFunctionBegin; 4768 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4769 PetscValidType(mat, 1); 4770 4771 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4772 MatCheckPreallocated(mat, 1); 4773 4774 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv)); 4775 if (!foundtype) { 4776 if (type) { 4777 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], 4778 ((PetscObject)mat)->type_name, type); 4779 } else { 4780 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); 4781 } 4782 } 4783 PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name); 4784 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); 4785 4786 PetscCall((*conv)(mat, ftype, f)); 4787 if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix)); 4788 PetscFunctionReturn(PETSC_SUCCESS); 4789 } 4790 4791 /*@C 4792 MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type 4793 4794 Not Collective 4795 4796 Input Parameters: 4797 + mat - the matrix 4798 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4799 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4800 4801 Output Parameter: 4802 . flg - PETSC_TRUE if the factorization is available 4803 4804 Level: intermediate 4805 4806 Notes: 4807 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4808 such as pastix, superlu, mumps etc. 4809 4810 PETSc must have been ./configure to use the external solver, using the option --download-package 4811 4812 Developer Notes: 4813 This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object 4814 4815 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatSolverTypeRegister()`, 4816 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4817 @*/ 4818 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg) 4819 { 4820 PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *); 4821 4822 PetscFunctionBegin; 4823 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4824 PetscAssertPointer(flg, 4); 4825 4826 *flg = PETSC_FALSE; 4827 if (!((PetscObject)mat)->type_name) PetscFunctionReturn(PETSC_SUCCESS); 4828 4829 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4830 MatCheckPreallocated(mat, 1); 4831 4832 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv)); 4833 *flg = gconv ? PETSC_TRUE : PETSC_FALSE; 4834 PetscFunctionReturn(PETSC_SUCCESS); 4835 } 4836 4837 /*@ 4838 MatDuplicate - Duplicates a matrix including the non-zero structure. 4839 4840 Collective 4841 4842 Input Parameters: 4843 + mat - the matrix 4844 - op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`. 4845 See the manual page for `MatDuplicateOption()` for an explanation of these options. 4846 4847 Output Parameter: 4848 . M - pointer to place new matrix 4849 4850 Level: intermediate 4851 4852 Notes: 4853 You cannot change the nonzero pattern for the parent or child matrix if you use `MAT_SHARE_NONZERO_PATTERN`. 4854 4855 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. 4856 4857 When original mat is a product of matrix operation, e.g., an output of `MatMatMult()` or `MatCreateSubMatrix()`, only the simple matrix data structure of mat 4858 is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated. 4859 User should not use `MatDuplicate()` to create new matrix M if M is intended to be reused as the product of matrix operation. 4860 4861 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption` 4862 @*/ 4863 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M) 4864 { 4865 Mat B; 4866 VecType vtype; 4867 PetscInt i; 4868 PetscObject dm, container_h, container_d; 4869 void (*viewf)(void); 4870 4871 PetscFunctionBegin; 4872 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4873 PetscValidType(mat, 1); 4874 PetscAssertPointer(M, 3); 4875 PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix"); 4876 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4877 MatCheckPreallocated(mat, 1); 4878 4879 *M = NULL; 4880 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4881 PetscUseTypeMethod(mat, duplicate, op, M); 4882 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4883 B = *M; 4884 4885 PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf)); 4886 if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf)); 4887 PetscCall(MatGetVecType(mat, &vtype)); 4888 PetscCall(MatSetVecType(B, vtype)); 4889 4890 B->stencil.dim = mat->stencil.dim; 4891 B->stencil.noc = mat->stencil.noc; 4892 for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) { 4893 B->stencil.dims[i] = mat->stencil.dims[i]; 4894 B->stencil.starts[i] = mat->stencil.starts[i]; 4895 } 4896 4897 B->nooffproczerorows = mat->nooffproczerorows; 4898 B->nooffprocentries = mat->nooffprocentries; 4899 4900 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm)); 4901 if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm)); 4902 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h)); 4903 if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h)); 4904 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d)); 4905 if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d)); 4906 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4907 PetscFunctionReturn(PETSC_SUCCESS); 4908 } 4909 4910 /*@ 4911 MatGetDiagonal - Gets the diagonal of a matrix as a `Vec` 4912 4913 Logically Collective 4914 4915 Input Parameter: 4916 . mat - the matrix 4917 4918 Output Parameter: 4919 . v - the diagonal of the matrix 4920 4921 Level: intermediate 4922 4923 Note: 4924 If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries 4925 of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v` 4926 is larger than `ndiag`, the values of the remaining entries are unspecified. 4927 4928 Currently only correct in parallel for square matrices. 4929 4930 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()` 4931 @*/ 4932 PetscErrorCode MatGetDiagonal(Mat mat, Vec v) 4933 { 4934 PetscFunctionBegin; 4935 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4936 PetscValidType(mat, 1); 4937 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4938 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4939 MatCheckPreallocated(mat, 1); 4940 if (PetscDefined(USE_DEBUG)) { 4941 PetscInt nv, row, col, ndiag; 4942 4943 PetscCall(VecGetLocalSize(v, &nv)); 4944 PetscCall(MatGetLocalSize(mat, &row, &col)); 4945 ndiag = PetscMin(row, col); 4946 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); 4947 } 4948 4949 PetscUseTypeMethod(mat, getdiagonal, v); 4950 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4951 PetscFunctionReturn(PETSC_SUCCESS); 4952 } 4953 4954 /*@C 4955 MatGetRowMin - Gets the minimum value (of the real part) of each 4956 row of the matrix 4957 4958 Logically Collective 4959 4960 Input Parameter: 4961 . mat - the matrix 4962 4963 Output Parameters: 4964 + v - the vector for storing the maximums 4965 - idx - the indices of the column found for each row (optional) 4966 4967 Level: intermediate 4968 4969 Note: 4970 The result of this call are the same as if one converted the matrix to dense format 4971 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 4972 4973 This code is only implemented for a couple of matrix formats. 4974 4975 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, 4976 `MatGetRowMax()` 4977 @*/ 4978 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[]) 4979 { 4980 PetscFunctionBegin; 4981 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4982 PetscValidType(mat, 1); 4983 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4984 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4985 4986 if (!mat->cmap->N) { 4987 PetscCall(VecSet(v, PETSC_MAX_REAL)); 4988 if (idx) { 4989 PetscInt i, m = mat->rmap->n; 4990 for (i = 0; i < m; i++) idx[i] = -1; 4991 } 4992 } else { 4993 MatCheckPreallocated(mat, 1); 4994 } 4995 PetscUseTypeMethod(mat, getrowmin, v, idx); 4996 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4997 PetscFunctionReturn(PETSC_SUCCESS); 4998 } 4999 5000 /*@C 5001 MatGetRowMinAbs - Gets the minimum value (in absolute value) of each 5002 row of the matrix 5003 5004 Logically Collective 5005 5006 Input Parameter: 5007 . mat - the matrix 5008 5009 Output Parameters: 5010 + v - the vector for storing the minimums 5011 - idx - the indices of the column found for each row (or `NULL` if not needed) 5012 5013 Level: intermediate 5014 5015 Notes: 5016 if a row is completely empty or has only 0.0 values then the idx[] value for that 5017 row is 0 (the first column). 5018 5019 This code is only implemented for a couple of matrix formats. 5020 5021 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()` 5022 @*/ 5023 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[]) 5024 { 5025 PetscFunctionBegin; 5026 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5027 PetscValidType(mat, 1); 5028 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5029 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5030 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5031 5032 if (!mat->cmap->N) { 5033 PetscCall(VecSet(v, 0.0)); 5034 if (idx) { 5035 PetscInt i, m = mat->rmap->n; 5036 for (i = 0; i < m; i++) idx[i] = -1; 5037 } 5038 } else { 5039 MatCheckPreallocated(mat, 1); 5040 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5041 PetscUseTypeMethod(mat, getrowminabs, v, idx); 5042 } 5043 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5044 PetscFunctionReturn(PETSC_SUCCESS); 5045 } 5046 5047 /*@C 5048 MatGetRowMax - Gets the maximum 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) 5059 5060 Level: intermediate 5061 5062 Notes: 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()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5069 @*/ 5070 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[]) 5071 { 5072 PetscFunctionBegin; 5073 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5074 PetscValidType(mat, 1); 5075 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5076 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5077 5078 if (!mat->cmap->N) { 5079 PetscCall(VecSet(v, PETSC_MIN_REAL)); 5080 if (idx) { 5081 PetscInt i, m = mat->rmap->n; 5082 for (i = 0; i < m; i++) idx[i] = -1; 5083 } 5084 } else { 5085 MatCheckPreallocated(mat, 1); 5086 PetscUseTypeMethod(mat, getrowmax, v, idx); 5087 } 5088 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5089 PetscFunctionReturn(PETSC_SUCCESS); 5090 } 5091 5092 /*@C 5093 MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each 5094 row of the matrix 5095 5096 Logically Collective 5097 5098 Input Parameter: 5099 . mat - the matrix 5100 5101 Output Parameters: 5102 + v - the vector for storing the maximums 5103 - idx - the indices of the column found for each row (or `NULL` if not needed) 5104 5105 Level: intermediate 5106 5107 Notes: 5108 if a row is completely empty or has only 0.0 values then the idx[] value for that 5109 row is 0 (the first column). 5110 5111 This code is only implemented for a couple of matrix formats. 5112 5113 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5114 @*/ 5115 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[]) 5116 { 5117 PetscFunctionBegin; 5118 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5119 PetscValidType(mat, 1); 5120 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5121 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5122 5123 if (!mat->cmap->N) { 5124 PetscCall(VecSet(v, 0.0)); 5125 if (idx) { 5126 PetscInt i, m = mat->rmap->n; 5127 for (i = 0; i < m; i++) idx[i] = -1; 5128 } 5129 } else { 5130 MatCheckPreallocated(mat, 1); 5131 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5132 PetscUseTypeMethod(mat, getrowmaxabs, v, idx); 5133 } 5134 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5135 PetscFunctionReturn(PETSC_SUCCESS); 5136 } 5137 5138 /*@ 5139 MatGetRowSum - Gets the sum of each row of the matrix 5140 5141 Logically or Neighborhood Collective 5142 5143 Input Parameter: 5144 . mat - the matrix 5145 5146 Output Parameter: 5147 . v - the vector for storing the sum of rows 5148 5149 Level: intermediate 5150 5151 Notes: 5152 This code is slow since it is not currently specialized for different formats 5153 5154 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()` 5155 @*/ 5156 PetscErrorCode MatGetRowSum(Mat mat, Vec v) 5157 { 5158 Vec ones; 5159 5160 PetscFunctionBegin; 5161 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5162 PetscValidType(mat, 1); 5163 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5164 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5165 MatCheckPreallocated(mat, 1); 5166 PetscCall(MatCreateVecs(mat, &ones, NULL)); 5167 PetscCall(VecSet(ones, 1.)); 5168 PetscCall(MatMult(mat, ones, v)); 5169 PetscCall(VecDestroy(&ones)); 5170 PetscFunctionReturn(PETSC_SUCCESS); 5171 } 5172 5173 /*@ 5174 MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) 5175 when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B) 5176 5177 Collective 5178 5179 Input Parameter: 5180 . mat - the matrix to provide the transpose 5181 5182 Output Parameter: 5183 . 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 5184 5185 Level: advanced 5186 5187 Note: 5188 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 5189 routine allows bypassing that call. 5190 5191 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5192 @*/ 5193 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B) 5194 { 5195 PetscContainer rB = NULL; 5196 MatParentState *rb = NULL; 5197 5198 PetscFunctionBegin; 5199 PetscCall(PetscNew(&rb)); 5200 rb->id = ((PetscObject)mat)->id; 5201 rb->state = 0; 5202 PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate)); 5203 PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB)); 5204 PetscCall(PetscContainerSetPointer(rB, rb)); 5205 PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault)); 5206 PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB)); 5207 PetscCall(PetscObjectDereference((PetscObject)rB)); 5208 PetscFunctionReturn(PETSC_SUCCESS); 5209 } 5210 5211 /*@ 5212 MatTranspose - Computes an in-place or out-of-place transpose of a matrix. 5213 5214 Collective 5215 5216 Input Parameters: 5217 + mat - the matrix to transpose 5218 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5219 5220 Output Parameter: 5221 . B - the transpose 5222 5223 Level: intermediate 5224 5225 Notes: 5226 If you use `MAT_INPLACE_MATRIX` then you must pass in &mat for B 5227 5228 `MAT_REUSE_MATRIX` uses the B matrix obtained from a previous call to this function with `MAT_INITIAL_MATRIX`. If you already have a matrix to contain the 5229 transpose, call `MatTransposeSetPrecursor`(mat,B) before calling this routine. 5230 5231 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. 5232 5233 Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed. 5234 5235 If mat is unchanged from the last call this function returns immediately without recomputing the result 5236 5237 If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()` 5238 5239 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`, 5240 `MatTransposeSymbolic()`, `MatCreateTranspose()` 5241 @*/ 5242 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B) 5243 { 5244 PetscContainer rB = NULL; 5245 MatParentState *rb = NULL; 5246 5247 PetscFunctionBegin; 5248 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5249 PetscValidType(mat, 1); 5250 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5251 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5252 PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first"); 5253 PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX"); 5254 MatCheckPreallocated(mat, 1); 5255 if (reuse == MAT_REUSE_MATRIX) { 5256 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5257 PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor()."); 5258 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5259 PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5260 if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS); 5261 } 5262 5263 PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0)); 5264 if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) { 5265 PetscUseTypeMethod(mat, transpose, reuse, B); 5266 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5267 } 5268 PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0)); 5269 5270 if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B)); 5271 if (reuse != MAT_INPLACE_MATRIX) { 5272 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5273 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5274 rb->state = ((PetscObject)mat)->state; 5275 rb->nonzerostate = mat->nonzerostate; 5276 } 5277 PetscFunctionReturn(PETSC_SUCCESS); 5278 } 5279 5280 /*@ 5281 MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix. 5282 5283 Collective 5284 5285 Input Parameter: 5286 . A - the matrix to transpose 5287 5288 Output Parameter: 5289 . 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 5290 numerical portion. 5291 5292 Level: intermediate 5293 5294 Note: 5295 This is not supported for many matrix types, use `MatTranspose()` in those cases 5296 5297 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5298 @*/ 5299 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B) 5300 { 5301 PetscFunctionBegin; 5302 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5303 PetscValidType(A, 1); 5304 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5305 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5306 PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0)); 5307 PetscUseTypeMethod(A, transposesymbolic, B); 5308 PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0)); 5309 5310 PetscCall(MatTransposeSetPrecursor(A, *B)); 5311 PetscFunctionReturn(PETSC_SUCCESS); 5312 } 5313 5314 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B) 5315 { 5316 PetscContainer rB; 5317 MatParentState *rb; 5318 5319 PetscFunctionBegin; 5320 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5321 PetscValidType(A, 1); 5322 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5323 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5324 PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB)); 5325 PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()"); 5326 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5327 PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5328 PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure"); 5329 PetscFunctionReturn(PETSC_SUCCESS); 5330 } 5331 5332 /*@ 5333 MatIsTranspose - Test whether a matrix is another one's transpose, 5334 or its own, in which case it tests symmetry. 5335 5336 Collective 5337 5338 Input Parameters: 5339 + A - the matrix to test 5340 . B - the matrix to test against, this can equal the first parameter 5341 - tol - tolerance, differences between entries smaller than this are counted as zero 5342 5343 Output Parameter: 5344 . flg - the result 5345 5346 Level: intermediate 5347 5348 Notes: 5349 Only available for `MATAIJ` matrices. 5350 5351 The sequential algorithm has a running time of the order of the number of nonzeros; the parallel 5352 test involves parallel copies of the block off-diagonal parts of the matrix. 5353 5354 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()` 5355 @*/ 5356 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5357 { 5358 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5359 5360 PetscFunctionBegin; 5361 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5362 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5363 PetscAssertPointer(flg, 4); 5364 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f)); 5365 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g)); 5366 *flg = PETSC_FALSE; 5367 if (f && g) { 5368 PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test"); 5369 PetscCall((*f)(A, B, tol, flg)); 5370 } else { 5371 MatType mattype; 5372 5373 PetscCall(MatGetType(f ? B : A, &mattype)); 5374 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype); 5375 } 5376 PetscFunctionReturn(PETSC_SUCCESS); 5377 } 5378 5379 /*@ 5380 MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate. 5381 5382 Collective 5383 5384 Input Parameters: 5385 + mat - the matrix to transpose and complex conjugate 5386 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5387 5388 Output Parameter: 5389 . B - the Hermitian transpose 5390 5391 Level: intermediate 5392 5393 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse` 5394 @*/ 5395 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B) 5396 { 5397 PetscFunctionBegin; 5398 PetscCall(MatTranspose(mat, reuse, B)); 5399 #if defined(PETSC_USE_COMPLEX) 5400 PetscCall(MatConjugate(*B)); 5401 #endif 5402 PetscFunctionReturn(PETSC_SUCCESS); 5403 } 5404 5405 /*@ 5406 MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose, 5407 5408 Collective 5409 5410 Input Parameters: 5411 + A - the matrix to test 5412 . B - the matrix to test against, this can equal the first parameter 5413 - tol - tolerance, differences between entries smaller than this are counted as zero 5414 5415 Output Parameter: 5416 . flg - the result 5417 5418 Level: intermediate 5419 5420 Notes: 5421 Only available for `MATAIJ` matrices. 5422 5423 The sequential algorithm 5424 has a running time of the order of the number of nonzeros; the parallel 5425 test involves parallel copies of the block off-diagonal parts of the matrix. 5426 5427 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()` 5428 @*/ 5429 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5430 { 5431 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5432 5433 PetscFunctionBegin; 5434 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5435 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5436 PetscAssertPointer(flg, 4); 5437 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f)); 5438 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g)); 5439 if (f && g) { 5440 PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test"); 5441 PetscCall((*f)(A, B, tol, flg)); 5442 } 5443 PetscFunctionReturn(PETSC_SUCCESS); 5444 } 5445 5446 /*@ 5447 MatPermute - Creates a new matrix with rows and columns permuted from the 5448 original. 5449 5450 Collective 5451 5452 Input Parameters: 5453 + mat - the matrix to permute 5454 . row - row permutation, each processor supplies only the permutation for its rows 5455 - col - column permutation, each processor supplies only the permutation for its columns 5456 5457 Output Parameter: 5458 . B - the permuted matrix 5459 5460 Level: advanced 5461 5462 Note: 5463 The index sets map from row/col of permuted matrix to row/col of original matrix. 5464 The index sets should be on the same communicator as mat and have the same local sizes. 5465 5466 Developer Notes: 5467 If you want to implement `MatPermute()` for a matrix type, and your approach doesn't 5468 exploit the fact that row and col are permutations, consider implementing the 5469 more general `MatCreateSubMatrix()` instead. 5470 5471 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()` 5472 @*/ 5473 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B) 5474 { 5475 PetscFunctionBegin; 5476 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5477 PetscValidType(mat, 1); 5478 PetscValidHeaderSpecific(row, IS_CLASSID, 2); 5479 PetscValidHeaderSpecific(col, IS_CLASSID, 3); 5480 PetscAssertPointer(B, 4); 5481 PetscCheckSameComm(mat, 1, row, 2); 5482 if (row != col) PetscCheckSameComm(row, 2, col, 3); 5483 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5484 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5485 PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name); 5486 MatCheckPreallocated(mat, 1); 5487 5488 if (mat->ops->permute) { 5489 PetscUseTypeMethod(mat, permute, row, col, B); 5490 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5491 } else { 5492 PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B)); 5493 } 5494 PetscFunctionReturn(PETSC_SUCCESS); 5495 } 5496 5497 /*@ 5498 MatEqual - Compares two matrices. 5499 5500 Collective 5501 5502 Input Parameters: 5503 + A - the first matrix 5504 - B - the second matrix 5505 5506 Output Parameter: 5507 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise. 5508 5509 Level: intermediate 5510 5511 .seealso: [](ch_matrices), `Mat` 5512 @*/ 5513 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg) 5514 { 5515 PetscFunctionBegin; 5516 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5517 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5518 PetscValidType(A, 1); 5519 PetscValidType(B, 2); 5520 PetscAssertPointer(flg, 3); 5521 PetscCheckSameComm(A, 1, B, 2); 5522 MatCheckPreallocated(A, 1); 5523 MatCheckPreallocated(B, 2); 5524 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5525 PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5526 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, 5527 B->cmap->N); 5528 if (A->ops->equal && A->ops->equal == B->ops->equal) { 5529 PetscUseTypeMethod(A, equal, B, flg); 5530 } else { 5531 PetscCall(MatMultEqual(A, B, 10, flg)); 5532 } 5533 PetscFunctionReturn(PETSC_SUCCESS); 5534 } 5535 5536 /*@ 5537 MatDiagonalScale - Scales a matrix on the left and right by diagonal 5538 matrices that are stored as vectors. Either of the two scaling 5539 matrices can be `NULL`. 5540 5541 Collective 5542 5543 Input Parameters: 5544 + mat - the matrix to be scaled 5545 . l - the left scaling vector (or `NULL`) 5546 - r - the right scaling vector (or `NULL`) 5547 5548 Level: intermediate 5549 5550 Note: 5551 `MatDiagonalScale()` computes A = LAR, where 5552 L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector) 5553 The L scales the rows of the matrix, the R scales the columns of the matrix. 5554 5555 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()` 5556 @*/ 5557 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r) 5558 { 5559 PetscFunctionBegin; 5560 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5561 PetscValidType(mat, 1); 5562 if (l) { 5563 PetscValidHeaderSpecific(l, VEC_CLASSID, 2); 5564 PetscCheckSameComm(mat, 1, l, 2); 5565 } 5566 if (r) { 5567 PetscValidHeaderSpecific(r, VEC_CLASSID, 3); 5568 PetscCheckSameComm(mat, 1, r, 3); 5569 } 5570 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5571 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5572 MatCheckPreallocated(mat, 1); 5573 if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS); 5574 5575 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5576 PetscUseTypeMethod(mat, diagonalscale, l, r); 5577 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5578 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5579 if (l != r) mat->symmetric = PETSC_BOOL3_FALSE; 5580 PetscFunctionReturn(PETSC_SUCCESS); 5581 } 5582 5583 /*@ 5584 MatScale - Scales all elements of a matrix by a given number. 5585 5586 Logically Collective 5587 5588 Input Parameters: 5589 + mat - the matrix to be scaled 5590 - a - the scaling value 5591 5592 Level: intermediate 5593 5594 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 5595 @*/ 5596 PetscErrorCode MatScale(Mat mat, PetscScalar a) 5597 { 5598 PetscFunctionBegin; 5599 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5600 PetscValidType(mat, 1); 5601 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5602 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5603 PetscValidLogicalCollectiveScalar(mat, a, 2); 5604 MatCheckPreallocated(mat, 1); 5605 5606 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5607 if (a != (PetscScalar)1.0) { 5608 PetscUseTypeMethod(mat, scale, a); 5609 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5610 } 5611 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5612 PetscFunctionReturn(PETSC_SUCCESS); 5613 } 5614 5615 /*@ 5616 MatNorm - Calculates various norms of a matrix. 5617 5618 Collective 5619 5620 Input Parameters: 5621 + mat - the matrix 5622 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY` 5623 5624 Output Parameter: 5625 . nrm - the resulting norm 5626 5627 Level: intermediate 5628 5629 .seealso: [](ch_matrices), `Mat` 5630 @*/ 5631 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm) 5632 { 5633 PetscFunctionBegin; 5634 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5635 PetscValidType(mat, 1); 5636 PetscAssertPointer(nrm, 3); 5637 5638 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5639 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5640 MatCheckPreallocated(mat, 1); 5641 5642 PetscUseTypeMethod(mat, norm, type, nrm); 5643 PetscFunctionReturn(PETSC_SUCCESS); 5644 } 5645 5646 /* 5647 This variable is used to prevent counting of MatAssemblyBegin() that 5648 are called from within a MatAssemblyEnd(). 5649 */ 5650 static PetscInt MatAssemblyEnd_InUse = 0; 5651 /*@ 5652 MatAssemblyBegin - Begins assembling the matrix. This routine should 5653 be called after completing all calls to `MatSetValues()`. 5654 5655 Collective 5656 5657 Input Parameters: 5658 + mat - the matrix 5659 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5660 5661 Level: beginner 5662 5663 Notes: 5664 `MatSetValues()` generally caches the values that belong to other MPI processes. The matrix is ready to 5665 use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called. 5666 5667 Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES` 5668 in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before 5669 using the matrix. 5670 5671 ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the 5672 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 5673 a global collective operation requiring all processes that share the matrix. 5674 5675 Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed 5676 out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros 5677 before `MAT_FINAL_ASSEMBLY` so the space is not compressed out. 5678 5679 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()` 5680 @*/ 5681 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type) 5682 { 5683 PetscFunctionBegin; 5684 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5685 PetscValidType(mat, 1); 5686 MatCheckPreallocated(mat, 1); 5687 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?"); 5688 if (mat->assembled) { 5689 mat->was_assembled = PETSC_TRUE; 5690 mat->assembled = PETSC_FALSE; 5691 } 5692 5693 if (!MatAssemblyEnd_InUse) { 5694 PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0)); 5695 PetscTryTypeMethod(mat, assemblybegin, type); 5696 PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0)); 5697 } else PetscTryTypeMethod(mat, assemblybegin, type); 5698 PetscFunctionReturn(PETSC_SUCCESS); 5699 } 5700 5701 /*@ 5702 MatAssembled - Indicates if a matrix has been assembled and is ready for 5703 use; for example, in matrix-vector product. 5704 5705 Not Collective 5706 5707 Input Parameter: 5708 . mat - the matrix 5709 5710 Output Parameter: 5711 . assembled - `PETSC_TRUE` or `PETSC_FALSE` 5712 5713 Level: advanced 5714 5715 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()` 5716 @*/ 5717 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled) 5718 { 5719 PetscFunctionBegin; 5720 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5721 PetscAssertPointer(assembled, 2); 5722 *assembled = mat->assembled; 5723 PetscFunctionReturn(PETSC_SUCCESS); 5724 } 5725 5726 /*@ 5727 MatAssemblyEnd - Completes assembling the matrix. This routine should 5728 be called after `MatAssemblyBegin()`. 5729 5730 Collective 5731 5732 Input Parameters: 5733 + mat - the matrix 5734 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5735 5736 Options Database Keys: 5737 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 5738 . -mat_view ::ascii_info_detail - Prints more detailed info 5739 . -mat_view - Prints matrix in ASCII format 5740 . -mat_view ::ascii_matlab - Prints matrix in MATLAB format 5741 . -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 5742 . -display <name> - Sets display name (default is host) 5743 . -draw_pause <sec> - Sets number of seconds to pause after display 5744 . -mat_view socket - Sends matrix to socket, can be accessed from MATLAB (See [Using MATLAB with PETSc](ch_matlab)) 5745 . -viewer_socket_machine <machine> - Machine to use for socket 5746 . -viewer_socket_port <port> - Port number to use for socket 5747 - -mat_view binary:filename[:append] - Save matrix to file in binary format 5748 5749 Level: beginner 5750 5751 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()` 5752 @*/ 5753 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type) 5754 { 5755 static PetscInt inassm = 0; 5756 PetscBool flg = PETSC_FALSE; 5757 5758 PetscFunctionBegin; 5759 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5760 PetscValidType(mat, 1); 5761 5762 inassm++; 5763 MatAssemblyEnd_InUse++; 5764 if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */ 5765 PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0)); 5766 PetscTryTypeMethod(mat, assemblyend, type); 5767 PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0)); 5768 } else PetscTryTypeMethod(mat, assemblyend, type); 5769 5770 /* Flush assembly is not a true assembly */ 5771 if (type != MAT_FLUSH_ASSEMBLY) { 5772 if (mat->num_ass) { 5773 if (!mat->symmetry_eternal) { 5774 mat->symmetric = PETSC_BOOL3_UNKNOWN; 5775 mat->hermitian = PETSC_BOOL3_UNKNOWN; 5776 } 5777 if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN; 5778 if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN; 5779 } 5780 mat->num_ass++; 5781 mat->assembled = PETSC_TRUE; 5782 mat->ass_nonzerostate = mat->nonzerostate; 5783 } 5784 5785 mat->insertmode = NOT_SET_VALUES; 5786 MatAssemblyEnd_InUse--; 5787 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5788 if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) { 5789 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 5790 5791 if (mat->checksymmetryonassembly) { 5792 PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg)); 5793 if (flg) { 5794 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5795 } else { 5796 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5797 } 5798 } 5799 if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL)); 5800 } 5801 inassm--; 5802 PetscFunctionReturn(PETSC_SUCCESS); 5803 } 5804 5805 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 5806 /*@ 5807 MatSetOption - Sets a parameter option for a matrix. Some options 5808 may be specific to certain storage formats. Some options 5809 determine how values will be inserted (or added). Sorted, 5810 row-oriented input will generally assemble the fastest. The default 5811 is row-oriented. 5812 5813 Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption` 5814 5815 Input Parameters: 5816 + mat - the matrix 5817 . op - the option, one of those listed below (and possibly others), 5818 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5819 5820 Options Describing Matrix Structure: 5821 + `MAT_SPD` - symmetric positive definite 5822 . `MAT_SYMMETRIC` - symmetric in terms of both structure and value 5823 . `MAT_HERMITIAN` - transpose is the complex conjugation 5824 . `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure 5825 . `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix 5826 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix 5827 . `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix 5828 5829 These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they 5830 do not need to be computed (usually at a high cost) 5831 5832 Options For Use with `MatSetValues()`: 5833 Insert a logically dense subblock, which can be 5834 . `MAT_ROW_ORIENTED` - row-oriented (default) 5835 5836 These options reflect the data you pass in with `MatSetValues()`; it has 5837 nothing to do with how the data is stored internally in the matrix 5838 data structure. 5839 5840 When (re)assembling a matrix, we can restrict the input for 5841 efficiency/debugging purposes. These options include 5842 . `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow) 5843 . `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated 5844 . `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries 5845 . `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry 5846 . `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly 5847 . `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if 5848 any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves 5849 performance for very large process counts. 5850 - `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset 5851 of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly 5852 functions, instead sending only neighbor messages. 5853 5854 Level: intermediate 5855 5856 Notes: 5857 Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg! 5858 5859 Some options are relevant only for particular matrix types and 5860 are thus ignored by others. Other options are not supported by 5861 certain matrix types and will generate an error message if set. 5862 5863 If using Fortran to compute a matrix, one may need to 5864 use the column-oriented option (or convert to the row-oriented 5865 format). 5866 5867 `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion 5868 that would generate a new entry in the nonzero structure is instead 5869 ignored. Thus, if memory has not already been allocated for this particular 5870 data, then the insertion is ignored. For dense matrices, in which 5871 the entire array is allocated, no entries are ever ignored. 5872 Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction 5873 5874 `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion 5875 that would generate a new entry in the nonzero structure instead produces 5876 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 5877 5878 `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion 5879 that would generate a new entry that has not been preallocated will 5880 instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats 5881 only.) This is a useful flag when debugging matrix memory preallocation. 5882 If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 5883 5884 `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for 5885 other processors should be dropped, rather than stashed. 5886 This is useful if you know that the "owning" processor is also 5887 always generating the correct matrix entries, so that PETSc need 5888 not transfer duplicate entries generated on another processor. 5889 5890 `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the 5891 searches during matrix assembly. When this flag is set, the hash table 5892 is created during the first matrix assembly. This hash table is 5893 used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()` 5894 to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag 5895 should be used with `MAT_USE_HASH_TABLE` flag. This option is currently 5896 supported by `MATMPIBAIJ` format only. 5897 5898 `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries 5899 are kept in the nonzero structure 5900 5901 `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating 5902 a zero location in the matrix 5903 5904 `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types 5905 5906 `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the 5907 zero row routines and thus improves performance for very large process counts. 5908 5909 `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular 5910 part of the matrix (since they should match the upper triangular part). 5911 5912 `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a 5913 single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common 5914 with finite difference schemes with non-periodic boundary conditions. 5915 5916 Developer Notes: 5917 `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other 5918 places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURALLY_SYMMETRIC` or `MAT_SPD` would need to be changed back 5919 to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had 5920 not changed. 5921 5922 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()` 5923 @*/ 5924 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg) 5925 { 5926 PetscFunctionBegin; 5927 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5928 if (op > 0) { 5929 PetscValidLogicalCollectiveEnum(mat, op, 2); 5930 PetscValidLogicalCollectiveBool(mat, flg, 3); 5931 } 5932 5933 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); 5934 5935 switch (op) { 5936 case MAT_FORCE_DIAGONAL_ENTRIES: 5937 mat->force_diagonals = flg; 5938 PetscFunctionReturn(PETSC_SUCCESS); 5939 case MAT_NO_OFF_PROC_ENTRIES: 5940 mat->nooffprocentries = flg; 5941 PetscFunctionReturn(PETSC_SUCCESS); 5942 case MAT_SUBSET_OFF_PROC_ENTRIES: 5943 mat->assembly_subset = flg; 5944 if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */ 5945 #if !defined(PETSC_HAVE_MPIUNI) 5946 PetscCall(MatStashScatterDestroy_BTS(&mat->stash)); 5947 #endif 5948 mat->stash.first_assembly_done = PETSC_FALSE; 5949 } 5950 PetscFunctionReturn(PETSC_SUCCESS); 5951 case MAT_NO_OFF_PROC_ZERO_ROWS: 5952 mat->nooffproczerorows = flg; 5953 PetscFunctionReturn(PETSC_SUCCESS); 5954 case MAT_SPD: 5955 if (flg) { 5956 mat->spd = PETSC_BOOL3_TRUE; 5957 mat->symmetric = PETSC_BOOL3_TRUE; 5958 mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5959 } else { 5960 mat->spd = PETSC_BOOL3_FALSE; 5961 } 5962 break; 5963 case MAT_SYMMETRIC: 5964 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5965 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5966 #if !defined(PETSC_USE_COMPLEX) 5967 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5968 #endif 5969 break; 5970 case MAT_HERMITIAN: 5971 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5972 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5973 #if !defined(PETSC_USE_COMPLEX) 5974 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5975 #endif 5976 break; 5977 case MAT_STRUCTURALLY_SYMMETRIC: 5978 mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5979 break; 5980 case MAT_SYMMETRY_ETERNAL: 5981 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"); 5982 mat->symmetry_eternal = flg; 5983 if (flg) mat->structural_symmetry_eternal = PETSC_TRUE; 5984 break; 5985 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 5986 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"); 5987 mat->structural_symmetry_eternal = flg; 5988 break; 5989 case MAT_SPD_ETERNAL: 5990 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"); 5991 mat->spd_eternal = flg; 5992 if (flg) { 5993 mat->structural_symmetry_eternal = PETSC_TRUE; 5994 mat->symmetry_eternal = PETSC_TRUE; 5995 } 5996 break; 5997 case MAT_STRUCTURE_ONLY: 5998 mat->structure_only = flg; 5999 break; 6000 case MAT_SORTED_FULL: 6001 mat->sortedfull = flg; 6002 break; 6003 default: 6004 break; 6005 } 6006 PetscTryTypeMethod(mat, setoption, op, flg); 6007 PetscFunctionReturn(PETSC_SUCCESS); 6008 } 6009 6010 /*@ 6011 MatGetOption - Gets a parameter option that has been set for a matrix. 6012 6013 Logically Collective 6014 6015 Input Parameters: 6016 + mat - the matrix 6017 - op - the option, this only responds to certain options, check the code for which ones 6018 6019 Output Parameter: 6020 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 6021 6022 Level: intermediate 6023 6024 Notes: 6025 Can only be called after `MatSetSizes()` and `MatSetType()` have been set. 6026 6027 Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or 6028 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6029 6030 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, 6031 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6032 @*/ 6033 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg) 6034 { 6035 PetscFunctionBegin; 6036 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6037 PetscValidType(mat, 1); 6038 6039 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); 6040 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()"); 6041 6042 switch (op) { 6043 case MAT_NO_OFF_PROC_ENTRIES: 6044 *flg = mat->nooffprocentries; 6045 break; 6046 case MAT_NO_OFF_PROC_ZERO_ROWS: 6047 *flg = mat->nooffproczerorows; 6048 break; 6049 case MAT_SYMMETRIC: 6050 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()"); 6051 break; 6052 case MAT_HERMITIAN: 6053 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()"); 6054 break; 6055 case MAT_STRUCTURALLY_SYMMETRIC: 6056 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()"); 6057 break; 6058 case MAT_SPD: 6059 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()"); 6060 break; 6061 case MAT_SYMMETRY_ETERNAL: 6062 *flg = mat->symmetry_eternal; 6063 break; 6064 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6065 *flg = mat->symmetry_eternal; 6066 break; 6067 default: 6068 break; 6069 } 6070 PetscFunctionReturn(PETSC_SUCCESS); 6071 } 6072 6073 /*@ 6074 MatZeroEntries - Zeros all entries of a matrix. For sparse matrices 6075 this routine retains the old nonzero structure. 6076 6077 Logically Collective 6078 6079 Input Parameter: 6080 . mat - the matrix 6081 6082 Level: intermediate 6083 6084 Note: 6085 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. 6086 See the Performance chapter of the users manual for information on preallocating matrices. 6087 6088 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()` 6089 @*/ 6090 PetscErrorCode MatZeroEntries(Mat mat) 6091 { 6092 PetscFunctionBegin; 6093 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6094 PetscValidType(mat, 1); 6095 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6096 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"); 6097 MatCheckPreallocated(mat, 1); 6098 6099 PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0)); 6100 PetscUseTypeMethod(mat, zeroentries); 6101 PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0)); 6102 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6103 PetscFunctionReturn(PETSC_SUCCESS); 6104 } 6105 6106 /*@ 6107 MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal) 6108 of a set of rows and columns of a matrix. 6109 6110 Collective 6111 6112 Input Parameters: 6113 + mat - the matrix 6114 . numRows - the number of rows/columns to zero 6115 . rows - the global row indices 6116 . diag - value put in the diagonal of the eliminated rows 6117 . x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call 6118 - b - optional vector of the right hand side, that will be adjusted by provided solution entries 6119 6120 Level: intermediate 6121 6122 Notes: 6123 This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6124 6125 For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`. 6126 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 6127 6128 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6129 Krylov method to take advantage of the known solution on the zeroed rows. 6130 6131 For the parallel case, all processes that share the matrix (i.e., 6132 those in the communicator used for matrix creation) MUST call this 6133 routine, regardless of whether any rows being zeroed are owned by 6134 them. 6135 6136 Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix. 6137 6138 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6139 list only rows local to itself). 6140 6141 The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine. 6142 6143 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6144 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6145 @*/ 6146 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6147 { 6148 PetscFunctionBegin; 6149 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6150 PetscValidType(mat, 1); 6151 if (numRows) PetscAssertPointer(rows, 3); 6152 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6153 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6154 MatCheckPreallocated(mat, 1); 6155 6156 PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b); 6157 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6158 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6159 PetscFunctionReturn(PETSC_SUCCESS); 6160 } 6161 6162 /*@ 6163 MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal) 6164 of a set of rows and columns of a matrix. 6165 6166 Collective 6167 6168 Input Parameters: 6169 + mat - the matrix 6170 . is - the rows to zero 6171 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6172 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6173 - b - optional vector of right hand side, that will be adjusted by provided solution 6174 6175 Level: intermediate 6176 6177 Note: 6178 See `MatZeroRowsColumns()` for details on how this routine operates. 6179 6180 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6181 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()` 6182 @*/ 6183 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6184 { 6185 PetscInt numRows; 6186 const PetscInt *rows; 6187 6188 PetscFunctionBegin; 6189 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6190 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6191 PetscValidType(mat, 1); 6192 PetscValidType(is, 2); 6193 PetscCall(ISGetLocalSize(is, &numRows)); 6194 PetscCall(ISGetIndices(is, &rows)); 6195 PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b)); 6196 PetscCall(ISRestoreIndices(is, &rows)); 6197 PetscFunctionReturn(PETSC_SUCCESS); 6198 } 6199 6200 /*@ 6201 MatZeroRows - Zeros all entries (except possibly the main diagonal) 6202 of a set of rows of a matrix. 6203 6204 Collective 6205 6206 Input Parameters: 6207 + mat - the matrix 6208 . numRows - the number of rows to zero 6209 . rows - the global row indices 6210 . diag - value put in the diagonal of the zeroed rows 6211 . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call 6212 - b - optional vector of right hand side, that will be adjusted by provided solution entries 6213 6214 Level: intermediate 6215 6216 Notes: 6217 This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6218 6219 For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`. 6220 6221 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6222 Krylov method to take advantage of the known solution on the zeroed rows. 6223 6224 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) 6225 from the matrix. 6226 6227 Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix 6228 but does not release memory. Because of this removal matrix-vector products with the adjusted matrix will be a bit faster. For the dense and block diagonal 6229 formats this does not alter the nonzero structure. 6230 6231 If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure 6232 of the matrix is not changed the values are 6233 merely zeroed. 6234 6235 The user can set a value in the diagonal entry (or for the `MATAIJ` format 6236 formats can optionally remove the main diagonal entry from the 6237 nonzero structure as well, by passing 0.0 as the final argument). 6238 6239 For the parallel case, all processes that share the matrix (i.e., 6240 those in the communicator used for matrix creation) MUST call this 6241 routine, regardless of whether any rows being zeroed are owned by 6242 them. 6243 6244 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6245 list only rows local to itself). 6246 6247 You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it 6248 owns that are to be zeroed. This saves a global synchronization in the implementation. 6249 6250 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6251 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE` 6252 @*/ 6253 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6254 { 6255 PetscFunctionBegin; 6256 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6257 PetscValidType(mat, 1); 6258 if (numRows) PetscAssertPointer(rows, 3); 6259 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6260 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6261 MatCheckPreallocated(mat, 1); 6262 6263 PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b); 6264 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6265 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6266 PetscFunctionReturn(PETSC_SUCCESS); 6267 } 6268 6269 /*@ 6270 MatZeroRowsIS - Zeros all entries (except possibly the main diagonal) 6271 of a set of rows of a matrix. 6272 6273 Collective 6274 6275 Input Parameters: 6276 + mat - the matrix 6277 . is - index set of rows to remove (if `NULL` then no row is removed) 6278 . diag - value put in all diagonals of eliminated rows 6279 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6280 - b - optional vector of right hand side, that will be adjusted by provided solution 6281 6282 Level: intermediate 6283 6284 Note: 6285 See `MatZeroRows()` for details on how this routine operates. 6286 6287 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6288 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6289 @*/ 6290 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6291 { 6292 PetscInt numRows = 0; 6293 const PetscInt *rows = NULL; 6294 6295 PetscFunctionBegin; 6296 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6297 PetscValidType(mat, 1); 6298 if (is) { 6299 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6300 PetscCall(ISGetLocalSize(is, &numRows)); 6301 PetscCall(ISGetIndices(is, &rows)); 6302 } 6303 PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b)); 6304 if (is) PetscCall(ISRestoreIndices(is, &rows)); 6305 PetscFunctionReturn(PETSC_SUCCESS); 6306 } 6307 6308 /*@ 6309 MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal) 6310 of a set of rows of a matrix. These rows must be local to the process. 6311 6312 Collective 6313 6314 Input Parameters: 6315 + mat - the matrix 6316 . numRows - the number of rows to remove 6317 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6318 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6319 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6320 - b - optional vector of right hand side, that will be adjusted by provided solution 6321 6322 Level: intermediate 6323 6324 Notes: 6325 See `MatZeroRows()` for details on how this routine operates. 6326 6327 The grid coordinates are across the entire grid, not just the local portion 6328 6329 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6330 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6331 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6332 `DM_BOUNDARY_PERIODIC` boundary type. 6333 6334 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 6335 a single value per point) you can skip filling those indices. 6336 6337 Fortran Notes: 6338 `idxm` and `idxn` should be declared as 6339 $ MatStencil idxm(4, m) 6340 and the values inserted using 6341 .vb 6342 idxm(MatStencil_i, 1) = i 6343 idxm(MatStencil_j, 1) = j 6344 idxm(MatStencil_k, 1) = k 6345 idxm(MatStencil_c, 1) = c 6346 etc 6347 .ve 6348 6349 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6350 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6351 @*/ 6352 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6353 { 6354 PetscInt dim = mat->stencil.dim; 6355 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6356 PetscInt *dims = mat->stencil.dims + 1; 6357 PetscInt *starts = mat->stencil.starts; 6358 PetscInt *dxm = (PetscInt *)rows; 6359 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6360 6361 PetscFunctionBegin; 6362 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6363 PetscValidType(mat, 1); 6364 if (numRows) PetscAssertPointer(rows, 3); 6365 6366 PetscCall(PetscMalloc1(numRows, &jdxm)); 6367 for (i = 0; i < numRows; ++i) { 6368 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6369 for (j = 0; j < 3 - sdim; ++j) dxm++; 6370 /* Local index in X dir */ 6371 tmp = *dxm++ - starts[0]; 6372 /* Loop over remaining dimensions */ 6373 for (j = 0; j < dim - 1; ++j) { 6374 /* If nonlocal, set index to be negative */ 6375 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6376 /* Update local index */ 6377 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6378 } 6379 /* Skip component slot if necessary */ 6380 if (mat->stencil.noc) dxm++; 6381 /* Local row number */ 6382 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6383 } 6384 PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b)); 6385 PetscCall(PetscFree(jdxm)); 6386 PetscFunctionReturn(PETSC_SUCCESS); 6387 } 6388 6389 /*@ 6390 MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal) 6391 of a set of rows and columns of a matrix. 6392 6393 Collective 6394 6395 Input Parameters: 6396 + mat - the matrix 6397 . numRows - the number of rows/columns to remove 6398 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6399 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6400 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6401 - b - optional vector of right hand side, that will be adjusted by provided solution 6402 6403 Level: intermediate 6404 6405 Notes: 6406 See `MatZeroRowsColumns()` for details on how this routine operates. 6407 6408 The grid coordinates are across the entire grid, not just the local portion 6409 6410 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6411 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6412 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6413 `DM_BOUNDARY_PERIODIC` boundary type. 6414 6415 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 6416 a single value per point) you can skip filling those indices. 6417 6418 Fortran Notes: 6419 `idxm` and `idxn` should be declared as 6420 $ MatStencil idxm(4, m) 6421 and the values inserted using 6422 .vb 6423 idxm(MatStencil_i, 1) = i 6424 idxm(MatStencil_j, 1) = j 6425 idxm(MatStencil_k, 1) = k 6426 idxm(MatStencil_c, 1) = c 6427 etc 6428 .ve 6429 6430 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6431 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()` 6432 @*/ 6433 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6434 { 6435 PetscInt dim = mat->stencil.dim; 6436 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6437 PetscInt *dims = mat->stencil.dims + 1; 6438 PetscInt *starts = mat->stencil.starts; 6439 PetscInt *dxm = (PetscInt *)rows; 6440 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6441 6442 PetscFunctionBegin; 6443 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6444 PetscValidType(mat, 1); 6445 if (numRows) PetscAssertPointer(rows, 3); 6446 6447 PetscCall(PetscMalloc1(numRows, &jdxm)); 6448 for (i = 0; i < numRows; ++i) { 6449 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6450 for (j = 0; j < 3 - sdim; ++j) dxm++; 6451 /* Local index in X dir */ 6452 tmp = *dxm++ - starts[0]; 6453 /* Loop over remaining dimensions */ 6454 for (j = 0; j < dim - 1; ++j) { 6455 /* If nonlocal, set index to be negative */ 6456 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6457 /* Update local index */ 6458 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6459 } 6460 /* Skip component slot if necessary */ 6461 if (mat->stencil.noc) dxm++; 6462 /* Local row number */ 6463 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6464 } 6465 PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b)); 6466 PetscCall(PetscFree(jdxm)); 6467 PetscFunctionReturn(PETSC_SUCCESS); 6468 } 6469 6470 /*@C 6471 MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal) 6472 of a set of rows of a matrix; using local numbering of rows. 6473 6474 Collective 6475 6476 Input Parameters: 6477 + mat - the matrix 6478 . numRows - the number of rows to remove 6479 . rows - the local row indices 6480 . diag - value put in all diagonals of eliminated rows 6481 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6482 - b - optional vector of right hand side, that will be adjusted by provided solution 6483 6484 Level: intermediate 6485 6486 Notes: 6487 Before calling `MatZeroRowsLocal()`, the user must first set the 6488 local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`. 6489 6490 See `MatZeroRows()` for details on how this routine operates. 6491 6492 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`, 6493 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6494 @*/ 6495 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6496 { 6497 PetscFunctionBegin; 6498 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6499 PetscValidType(mat, 1); 6500 if (numRows) PetscAssertPointer(rows, 3); 6501 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6502 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6503 MatCheckPreallocated(mat, 1); 6504 6505 if (mat->ops->zerorowslocal) { 6506 PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b); 6507 } else { 6508 IS is, newis; 6509 const PetscInt *newRows; 6510 6511 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6512 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6513 PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis)); 6514 PetscCall(ISGetIndices(newis, &newRows)); 6515 PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b); 6516 PetscCall(ISRestoreIndices(newis, &newRows)); 6517 PetscCall(ISDestroy(&newis)); 6518 PetscCall(ISDestroy(&is)); 6519 } 6520 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6521 PetscFunctionReturn(PETSC_SUCCESS); 6522 } 6523 6524 /*@ 6525 MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal) 6526 of a set of rows of a matrix; using local numbering of rows. 6527 6528 Collective 6529 6530 Input Parameters: 6531 + mat - the matrix 6532 . is - index set of rows to remove 6533 . diag - value put in all diagonals of eliminated rows 6534 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6535 - b - optional vector of right hand side, that will be adjusted by provided solution 6536 6537 Level: intermediate 6538 6539 Notes: 6540 Before calling `MatZeroRowsLocalIS()`, the user must first set the 6541 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6542 6543 See `MatZeroRows()` for details on how this routine operates. 6544 6545 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6546 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6547 @*/ 6548 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6549 { 6550 PetscInt numRows; 6551 const PetscInt *rows; 6552 6553 PetscFunctionBegin; 6554 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6555 PetscValidType(mat, 1); 6556 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6557 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6558 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6559 MatCheckPreallocated(mat, 1); 6560 6561 PetscCall(ISGetLocalSize(is, &numRows)); 6562 PetscCall(ISGetIndices(is, &rows)); 6563 PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b)); 6564 PetscCall(ISRestoreIndices(is, &rows)); 6565 PetscFunctionReturn(PETSC_SUCCESS); 6566 } 6567 6568 /*@ 6569 MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal) 6570 of a set of rows and columns of a matrix; using local numbering of rows. 6571 6572 Collective 6573 6574 Input Parameters: 6575 + mat - the matrix 6576 . numRows - the number of rows to remove 6577 . rows - the global row indices 6578 . diag - value put in all diagonals of eliminated rows 6579 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6580 - b - optional vector of right hand side, that will be adjusted by provided solution 6581 6582 Level: intermediate 6583 6584 Notes: 6585 Before calling `MatZeroRowsColumnsLocal()`, the user must first set the 6586 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6587 6588 See `MatZeroRowsColumns()` for details on how this routine operates. 6589 6590 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6591 `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6592 @*/ 6593 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6594 { 6595 IS is, newis; 6596 const PetscInt *newRows; 6597 6598 PetscFunctionBegin; 6599 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6600 PetscValidType(mat, 1); 6601 if (numRows) PetscAssertPointer(rows, 3); 6602 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6603 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6604 MatCheckPreallocated(mat, 1); 6605 6606 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6607 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6608 PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis)); 6609 PetscCall(ISGetIndices(newis, &newRows)); 6610 PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b); 6611 PetscCall(ISRestoreIndices(newis, &newRows)); 6612 PetscCall(ISDestroy(&newis)); 6613 PetscCall(ISDestroy(&is)); 6614 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6615 PetscFunctionReturn(PETSC_SUCCESS); 6616 } 6617 6618 /*@ 6619 MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal) 6620 of a set of rows and columns of a matrix; using local numbering of rows. 6621 6622 Collective 6623 6624 Input Parameters: 6625 + mat - the matrix 6626 . is - index set of rows to remove 6627 . diag - value put in all diagonals of eliminated rows 6628 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6629 - b - optional vector of right hand side, that will be adjusted by provided solution 6630 6631 Level: intermediate 6632 6633 Notes: 6634 Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the 6635 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6636 6637 See `MatZeroRowsColumns()` for details on how this routine operates. 6638 6639 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6640 `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6641 @*/ 6642 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6643 { 6644 PetscInt numRows; 6645 const PetscInt *rows; 6646 6647 PetscFunctionBegin; 6648 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6649 PetscValidType(mat, 1); 6650 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6651 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6652 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6653 MatCheckPreallocated(mat, 1); 6654 6655 PetscCall(ISGetLocalSize(is, &numRows)); 6656 PetscCall(ISGetIndices(is, &rows)); 6657 PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b)); 6658 PetscCall(ISRestoreIndices(is, &rows)); 6659 PetscFunctionReturn(PETSC_SUCCESS); 6660 } 6661 6662 /*@C 6663 MatGetSize - Returns the numbers of rows and columns in a matrix. 6664 6665 Not Collective 6666 6667 Input Parameter: 6668 . mat - the matrix 6669 6670 Output Parameters: 6671 + m - the number of global rows 6672 - n - the number of global columns 6673 6674 Level: beginner 6675 6676 Note: 6677 Both output parameters can be `NULL` on input. 6678 6679 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()` 6680 @*/ 6681 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n) 6682 { 6683 PetscFunctionBegin; 6684 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6685 if (m) *m = mat->rmap->N; 6686 if (n) *n = mat->cmap->N; 6687 PetscFunctionReturn(PETSC_SUCCESS); 6688 } 6689 6690 /*@C 6691 MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns 6692 of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`. 6693 6694 Not Collective 6695 6696 Input Parameter: 6697 . mat - the matrix 6698 6699 Output Parameters: 6700 + m - the number of local rows, use `NULL` to not obtain this value 6701 - n - the number of local columns, use `NULL` to not obtain this value 6702 6703 Level: beginner 6704 6705 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()` 6706 @*/ 6707 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n) 6708 { 6709 PetscFunctionBegin; 6710 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6711 if (m) PetscAssertPointer(m, 2); 6712 if (n) PetscAssertPointer(n, 3); 6713 if (m) *m = mat->rmap->n; 6714 if (n) *n = mat->cmap->n; 6715 PetscFunctionReturn(PETSC_SUCCESS); 6716 } 6717 6718 /*@C 6719 MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a 6720 vector one multiplies this matrix by that are owned by this processor. 6721 6722 Not Collective, unless matrix has not been allocated, then collective 6723 6724 Input Parameter: 6725 . mat - the matrix 6726 6727 Output Parameters: 6728 + m - the global index of the first local column, use `NULL` to not obtain this value 6729 - n - one more than the global index of the last local column, use `NULL` to not obtain this value 6730 6731 Level: developer 6732 6733 Notes: 6734 Retursns the columns of the "diagonal block" for most sparse matrix formats. See [Matrix 6735 Layouts](sec_matlayout) for details on matrix layouts. 6736 6737 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout` 6738 @*/ 6739 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n) 6740 { 6741 PetscFunctionBegin; 6742 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6743 PetscValidType(mat, 1); 6744 if (m) PetscAssertPointer(m, 2); 6745 if (n) PetscAssertPointer(n, 3); 6746 MatCheckPreallocated(mat, 1); 6747 if (m) *m = mat->cmap->rstart; 6748 if (n) *n = mat->cmap->rend; 6749 PetscFunctionReturn(PETSC_SUCCESS); 6750 } 6751 6752 /*@C 6753 MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6754 this MPI process. 6755 6756 Not Collective 6757 6758 Input Parameter: 6759 . mat - the matrix 6760 6761 Output Parameters: 6762 + m - the global index of the first local row, use `NULL` to not obtain this value 6763 - n - one more than the global index of the last local row, use `NULL` to not obtain this value 6764 6765 Level: beginner 6766 6767 Note: 6768 For all matrices it returns the range of matrix rows associated with rows of a vector that 6769 would contain the result of a matrix vector product with this matrix. See [Matrix 6770 Layouts](sec_matlayout) for details on matrix layouts. 6771 6772 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, 6773 `PetscLayout` 6774 @*/ 6775 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n) 6776 { 6777 PetscFunctionBegin; 6778 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6779 PetscValidType(mat, 1); 6780 if (m) PetscAssertPointer(m, 2); 6781 if (n) PetscAssertPointer(n, 3); 6782 MatCheckPreallocated(mat, 1); 6783 if (m) *m = mat->rmap->rstart; 6784 if (n) *n = mat->rmap->rend; 6785 PetscFunctionReturn(PETSC_SUCCESS); 6786 } 6787 6788 /*@C 6789 MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and 6790 `MATSCALAPACK`, returns the range of matrix rows owned by each process. 6791 6792 Not Collective, unless matrix has not been allocated 6793 6794 Input Parameter: 6795 . mat - the matrix 6796 6797 Output Parameter: 6798 . ranges - start of each processors portion plus one more than the total length at the end 6799 6800 Level: beginner 6801 6802 Notes: 6803 For all matrices it returns the ranges of matrix rows associated with rows of a vector that 6804 would contain the result of a matrix vector product with this matrix. See [Matrix 6805 Layouts](sec_matlayout) for details on matrix layouts. 6806 6807 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout` 6808 @*/ 6809 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges) 6810 { 6811 PetscFunctionBegin; 6812 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6813 PetscValidType(mat, 1); 6814 MatCheckPreallocated(mat, 1); 6815 PetscCall(PetscLayoutGetRanges(mat->rmap, ranges)); 6816 PetscFunctionReturn(PETSC_SUCCESS); 6817 } 6818 6819 /*@C 6820 MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a 6821 vector one multiplies this vector by that are owned by each processor. 6822 6823 Not Collective, unless matrix has not been allocated 6824 6825 Input Parameter: 6826 . mat - the matrix 6827 6828 Output Parameter: 6829 . ranges - start of each processors portion plus one more than the total length at the end 6830 6831 Level: beginner 6832 6833 Notes: 6834 Returns the columns of the "diagonal blocks", for most sparse matrix formats. See [Matrix 6835 Layouts](sec_matlayout) for details on matrix layouts. 6836 6837 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()` 6838 @*/ 6839 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges) 6840 { 6841 PetscFunctionBegin; 6842 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6843 PetscValidType(mat, 1); 6844 MatCheckPreallocated(mat, 1); 6845 PetscCall(PetscLayoutGetRanges(mat->cmap, ranges)); 6846 PetscFunctionReturn(PETSC_SUCCESS); 6847 } 6848 6849 /*@C 6850 MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. 6851 6852 Not Collective 6853 6854 Input Parameter: 6855 . A - matrix 6856 6857 Output Parameters: 6858 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value 6859 - cols - columns in which this process owns elements, use `NULL` to not obtain this value 6860 6861 Level: intermediate 6862 6863 Notes: 6864 For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this corresponds to values 6865 returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and 6866 `MATSCALAPACK` the ownership is more complicated. See [Matrix Layouts](sec_matlayout) for 6867 details on matrix layouts. 6868 6869 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK`` 6870 @*/ 6871 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols) 6872 { 6873 PetscErrorCode (*f)(Mat, IS *, IS *); 6874 6875 PetscFunctionBegin; 6876 MatCheckPreallocated(A, 1); 6877 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f)); 6878 if (f) { 6879 PetscCall((*f)(A, rows, cols)); 6880 } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */ 6881 if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows)); 6882 if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols)); 6883 } 6884 PetscFunctionReturn(PETSC_SUCCESS); 6885 } 6886 6887 /*@C 6888 MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()` 6889 Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()` 6890 to complete the factorization. 6891 6892 Collective 6893 6894 Input Parameters: 6895 + fact - the factorized matrix obtained with `MatGetFactor()` 6896 . mat - the matrix 6897 . row - row permutation 6898 . col - column permutation 6899 - info - structure containing 6900 .vb 6901 levels - number of levels of fill. 6902 expected fill - as ratio of original fill. 6903 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 6904 missing diagonal entries) 6905 .ve 6906 6907 Level: developer 6908 6909 Notes: 6910 See [Matrix Factorization](sec_matfactor) for additional information. 6911 6912 Most users should employ the `KSP` interface for linear solvers 6913 instead of working directly with matrix algebra routines such as this. 6914 See, e.g., `KSPCreate()`. 6915 6916 Uses the definition of level of fill as in Y. Saad, 2003 6917 6918 Developer Notes: 6919 The Fortran interface is not autogenerated as the 6920 interface definition cannot be generated correctly [due to `MatFactorInfo`] 6921 6922 References: 6923 . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003 6924 6925 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 6926 `MatGetOrdering()`, `MatFactorInfo` 6927 @*/ 6928 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 6929 { 6930 PetscFunctionBegin; 6931 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 6932 PetscValidType(mat, 2); 6933 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 6934 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 6935 PetscAssertPointer(info, 5); 6936 PetscAssertPointer(fact, 1); 6937 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels); 6938 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 6939 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6940 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6941 MatCheckPreallocated(mat, 2); 6942 6943 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0)); 6944 PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info); 6945 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0)); 6946 PetscFunctionReturn(PETSC_SUCCESS); 6947 } 6948 6949 /*@C 6950 MatICCFactorSymbolic - Performs symbolic incomplete 6951 Cholesky factorization for a symmetric matrix. Use 6952 `MatCholeskyFactorNumeric()` to complete the factorization. 6953 6954 Collective 6955 6956 Input Parameters: 6957 + fact - the factorized matrix obtained with `MatGetFactor()` 6958 . mat - the matrix to be factored 6959 . perm - row and column permutation 6960 - info - structure containing 6961 .vb 6962 levels - number of levels of fill. 6963 expected fill - as ratio of original fill. 6964 .ve 6965 6966 Level: developer 6967 6968 Notes: 6969 Most users should employ the `KSP` interface for linear solvers 6970 instead of working directly with matrix algebra routines such as this. 6971 See, e.g., `KSPCreate()`. 6972 6973 This uses the definition of level of fill as in Y. Saad, 2003 6974 6975 Developer Notes: 6976 The Fortran interface is not autogenerated as the 6977 interface definition cannot be generated correctly [due to `MatFactorInfo`] 6978 6979 References: 6980 . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003 6981 6982 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 6983 @*/ 6984 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 6985 { 6986 PetscFunctionBegin; 6987 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 6988 PetscValidType(mat, 2); 6989 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 6990 PetscAssertPointer(info, 4); 6991 PetscAssertPointer(fact, 1); 6992 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6993 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels); 6994 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 6995 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6996 MatCheckPreallocated(mat, 2); 6997 6998 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 6999 PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info); 7000 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 7001 PetscFunctionReturn(PETSC_SUCCESS); 7002 } 7003 7004 /*@C 7005 MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat 7006 points to an array of valid matrices, they may be reused to store the new 7007 submatrices. 7008 7009 Collective 7010 7011 Input Parameters: 7012 + mat - the matrix 7013 . n - the number of submatrixes to be extracted (on this processor, may be zero) 7014 . irow - index set of rows to extract 7015 . icol - index set of columns to extract 7016 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7017 7018 Output Parameter: 7019 . submat - the array of submatrices 7020 7021 Level: advanced 7022 7023 Notes: 7024 `MatCreateSubMatrices()` can extract ONLY sequential submatrices 7025 (from both sequential and parallel matrices). Use `MatCreateSubMatrix()` 7026 to extract a parallel submatrix. 7027 7028 Some matrix types place restrictions on the row and column 7029 indices, such as that they be sorted or that they be equal to each other. 7030 7031 The index sets may not have duplicate entries. 7032 7033 When extracting submatrices from a parallel matrix, each processor can 7034 form a different submatrix by setting the rows and columns of its 7035 individual index sets according to the local submatrix desired. 7036 7037 When finished using the submatrices, the user should destroy 7038 them with `MatDestroySubMatrices()`. 7039 7040 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 7041 original matrix has not changed from that last call to `MatCreateSubMatrices()`. 7042 7043 This routine creates the matrices in submat; you should NOT create them before 7044 calling it. It also allocates the array of matrix pointers submat. 7045 7046 For `MATBAIJ` matrices the index sets must respect the block structure, that is if they 7047 request one row/column in a block, they must request all rows/columns that are in 7048 that block. For example, if the block size is 2 you cannot request just row 0 and 7049 column 0. 7050 7051 Fortran Notes: 7052 The Fortran interface is slightly different from that given below; it 7053 requires one to pass in as `submat` a `Mat` (integer) array of size at least n+1. 7054 7055 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7056 @*/ 7057 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7058 { 7059 PetscInt i; 7060 PetscBool eq; 7061 7062 PetscFunctionBegin; 7063 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7064 PetscValidType(mat, 1); 7065 if (n) { 7066 PetscAssertPointer(irow, 3); 7067 for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3); 7068 PetscAssertPointer(icol, 4); 7069 for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4); 7070 } 7071 PetscAssertPointer(submat, 6); 7072 if (n && scall == MAT_REUSE_MATRIX) { 7073 PetscAssertPointer(*submat, 6); 7074 for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6); 7075 } 7076 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7077 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7078 MatCheckPreallocated(mat, 1); 7079 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7080 PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat); 7081 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7082 for (i = 0; i < n; i++) { 7083 (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */ 7084 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7085 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7086 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 7087 if (mat->boundtocpu && mat->bindingpropagates) { 7088 PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE)); 7089 PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE)); 7090 } 7091 #endif 7092 } 7093 PetscFunctionReturn(PETSC_SUCCESS); 7094 } 7095 7096 /*@C 7097 MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms). 7098 7099 Collective 7100 7101 Input Parameters: 7102 + mat - the matrix 7103 . n - the number of submatrixes to be extracted 7104 . irow - index set of rows to extract 7105 . icol - index set of columns to extract 7106 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7107 7108 Output Parameter: 7109 . submat - the array of submatrices 7110 7111 Level: advanced 7112 7113 Note: 7114 This is used by `PCGASM` 7115 7116 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7117 @*/ 7118 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7119 { 7120 PetscInt i; 7121 PetscBool eq; 7122 7123 PetscFunctionBegin; 7124 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7125 PetscValidType(mat, 1); 7126 if (n) { 7127 PetscAssertPointer(irow, 3); 7128 PetscValidHeaderSpecific(*irow, IS_CLASSID, 3); 7129 PetscAssertPointer(icol, 4); 7130 PetscValidHeaderSpecific(*icol, IS_CLASSID, 4); 7131 } 7132 PetscAssertPointer(submat, 6); 7133 if (n && scall == MAT_REUSE_MATRIX) { 7134 PetscAssertPointer(*submat, 6); 7135 PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6); 7136 } 7137 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7138 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7139 MatCheckPreallocated(mat, 1); 7140 7141 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7142 PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat); 7143 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7144 for (i = 0; i < n; i++) { 7145 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7146 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7147 } 7148 PetscFunctionReturn(PETSC_SUCCESS); 7149 } 7150 7151 /*@C 7152 MatDestroyMatrices - Destroys an array of matrices. 7153 7154 Collective 7155 7156 Input Parameters: 7157 + n - the number of local matrices 7158 - mat - the matrices (this is a pointer to the array of matrices) 7159 7160 Level: advanced 7161 7162 Note: 7163 Frees not only the matrices, but also the array that contains the matrices 7164 7165 Fortran Notes: 7166 This does not free the array. 7167 7168 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()` 7169 @*/ 7170 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[]) 7171 { 7172 PetscInt i; 7173 7174 PetscFunctionBegin; 7175 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7176 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7177 PetscAssertPointer(mat, 2); 7178 7179 for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i])); 7180 7181 /* memory is allocated even if n = 0 */ 7182 PetscCall(PetscFree(*mat)); 7183 PetscFunctionReturn(PETSC_SUCCESS); 7184 } 7185 7186 /*@C 7187 MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`. 7188 7189 Collective 7190 7191 Input Parameters: 7192 + n - the number of local matrices 7193 - mat - the matrices (this is a pointer to the array of matrices, just to match the calling 7194 sequence of `MatCreateSubMatrices()`) 7195 7196 Level: advanced 7197 7198 Note: 7199 Frees not only the matrices, but also the array that contains the matrices 7200 7201 Fortran Notes: 7202 This does not free the array. 7203 7204 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7205 @*/ 7206 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[]) 7207 { 7208 Mat mat0; 7209 7210 PetscFunctionBegin; 7211 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7212 /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */ 7213 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7214 PetscAssertPointer(mat, 2); 7215 7216 mat0 = (*mat)[0]; 7217 if (mat0 && mat0->ops->destroysubmatrices) { 7218 PetscCall((*mat0->ops->destroysubmatrices)(n, mat)); 7219 } else { 7220 PetscCall(MatDestroyMatrices(n, mat)); 7221 } 7222 PetscFunctionReturn(PETSC_SUCCESS); 7223 } 7224 7225 /*@C 7226 MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process 7227 7228 Collective 7229 7230 Input Parameter: 7231 . mat - the matrix 7232 7233 Output Parameter: 7234 . matstruct - the sequential matrix with the nonzero structure of mat 7235 7236 Level: developer 7237 7238 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7239 @*/ 7240 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct) 7241 { 7242 PetscFunctionBegin; 7243 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7244 PetscAssertPointer(matstruct, 2); 7245 7246 PetscValidType(mat, 1); 7247 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7248 MatCheckPreallocated(mat, 1); 7249 7250 PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7251 PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct); 7252 PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7253 PetscFunctionReturn(PETSC_SUCCESS); 7254 } 7255 7256 /*@C 7257 MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`. 7258 7259 Collective 7260 7261 Input Parameter: 7262 . mat - the matrix (this is a pointer to the array of matrices, just to match the calling 7263 sequence of `MatGetSeqNonzeroStructure()`) 7264 7265 Level: advanced 7266 7267 Note: 7268 Frees not only the matrices, but also the array that contains the matrices 7269 7270 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()` 7271 @*/ 7272 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat) 7273 { 7274 PetscFunctionBegin; 7275 PetscAssertPointer(mat, 1); 7276 PetscCall(MatDestroy(mat)); 7277 PetscFunctionReturn(PETSC_SUCCESS); 7278 } 7279 7280 /*@ 7281 MatIncreaseOverlap - Given a set of submatrices indicated by index sets, 7282 replaces the index sets by larger ones that represent submatrices with 7283 additional overlap. 7284 7285 Collective 7286 7287 Input Parameters: 7288 + mat - the matrix 7289 . n - the number of index sets 7290 . is - the array of index sets (these index sets will changed during the call) 7291 - ov - the additional overlap requested 7292 7293 Options Database Key: 7294 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7295 7296 Level: developer 7297 7298 Note: 7299 The computed overlap preserves the matrix block sizes when the blocks are square. 7300 That is: if a matrix nonzero for a given block would increase the overlap all columns associated with 7301 that block are included in the overlap regardless of whether each specific column would increase the overlap. 7302 7303 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()` 7304 @*/ 7305 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov) 7306 { 7307 PetscInt i, bs, cbs; 7308 7309 PetscFunctionBegin; 7310 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7311 PetscValidType(mat, 1); 7312 PetscValidLogicalCollectiveInt(mat, n, 2); 7313 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7314 if (n) { 7315 PetscAssertPointer(is, 3); 7316 for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3); 7317 } 7318 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7319 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7320 MatCheckPreallocated(mat, 1); 7321 7322 if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS); 7323 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7324 PetscUseTypeMethod(mat, increaseoverlap, n, is, ov); 7325 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7326 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 7327 if (bs == cbs) { 7328 for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs)); 7329 } 7330 PetscFunctionReturn(PETSC_SUCCESS); 7331 } 7332 7333 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt); 7334 7335 /*@ 7336 MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across 7337 a sub communicator, replaces the index sets by larger ones that represent submatrices with 7338 additional overlap. 7339 7340 Collective 7341 7342 Input Parameters: 7343 + mat - the matrix 7344 . n - the number of index sets 7345 . is - the array of index sets (these index sets will changed during the call) 7346 - ov - the additional overlap requested 7347 7348 ` Options Database Key: 7349 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7350 7351 Level: developer 7352 7353 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()` 7354 @*/ 7355 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov) 7356 { 7357 PetscInt i; 7358 7359 PetscFunctionBegin; 7360 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7361 PetscValidType(mat, 1); 7362 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7363 if (n) { 7364 PetscAssertPointer(is, 3); 7365 PetscValidHeaderSpecific(*is, IS_CLASSID, 3); 7366 } 7367 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7368 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7369 MatCheckPreallocated(mat, 1); 7370 if (!ov) PetscFunctionReturn(PETSC_SUCCESS); 7371 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7372 for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov)); 7373 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7374 PetscFunctionReturn(PETSC_SUCCESS); 7375 } 7376 7377 /*@ 7378 MatGetBlockSize - Returns the matrix block size. 7379 7380 Not Collective 7381 7382 Input Parameter: 7383 . mat - the matrix 7384 7385 Output Parameter: 7386 . bs - block size 7387 7388 Level: intermediate 7389 7390 Notes: 7391 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7392 7393 If the block size has not been set yet this routine returns 1. 7394 7395 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()` 7396 @*/ 7397 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs) 7398 { 7399 PetscFunctionBegin; 7400 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7401 PetscAssertPointer(bs, 2); 7402 *bs = PetscAbs(mat->rmap->bs); 7403 PetscFunctionReturn(PETSC_SUCCESS); 7404 } 7405 7406 /*@ 7407 MatGetBlockSizes - Returns the matrix block row and column sizes. 7408 7409 Not Collective 7410 7411 Input Parameter: 7412 . mat - the matrix 7413 7414 Output Parameters: 7415 + rbs - row block size 7416 - cbs - column block size 7417 7418 Level: intermediate 7419 7420 Notes: 7421 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7422 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7423 7424 If a block size has not been set yet this routine returns 1. 7425 7426 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()` 7427 @*/ 7428 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs) 7429 { 7430 PetscFunctionBegin; 7431 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7432 if (rbs) PetscAssertPointer(rbs, 2); 7433 if (cbs) PetscAssertPointer(cbs, 3); 7434 if (rbs) *rbs = PetscAbs(mat->rmap->bs); 7435 if (cbs) *cbs = PetscAbs(mat->cmap->bs); 7436 PetscFunctionReturn(PETSC_SUCCESS); 7437 } 7438 7439 /*@ 7440 MatSetBlockSize - Sets the matrix block size. 7441 7442 Logically Collective 7443 7444 Input Parameters: 7445 + mat - the matrix 7446 - bs - block size 7447 7448 Level: intermediate 7449 7450 Notes: 7451 Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix. 7452 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7453 7454 For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size 7455 is compatible with the matrix local sizes. 7456 7457 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()` 7458 @*/ 7459 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs) 7460 { 7461 PetscFunctionBegin; 7462 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7463 PetscValidLogicalCollectiveInt(mat, bs, 2); 7464 PetscCall(MatSetBlockSizes(mat, bs, bs)); 7465 PetscFunctionReturn(PETSC_SUCCESS); 7466 } 7467 7468 typedef struct { 7469 PetscInt n; 7470 IS *is; 7471 Mat *mat; 7472 PetscObjectState nonzerostate; 7473 Mat C; 7474 } EnvelopeData; 7475 7476 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata) 7477 { 7478 for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i])); 7479 PetscCall(PetscFree(edata->is)); 7480 PetscCall(PetscFree(edata)); 7481 return PETSC_SUCCESS; 7482 } 7483 7484 /*@ 7485 MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores 7486 the sizes of these blocks in the matrix. An individual block may lie over several processes. 7487 7488 Collective 7489 7490 Input Parameter: 7491 . mat - the matrix 7492 7493 Level: intermediate 7494 7495 Notes: 7496 There can be zeros within the blocks 7497 7498 The blocks can overlap between processes, including laying on more than two processes 7499 7500 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()` 7501 @*/ 7502 PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat) 7503 { 7504 PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend; 7505 PetscInt *diag, *odiag, sc; 7506 VecScatter scatter; 7507 PetscScalar *seqv; 7508 const PetscScalar *parv; 7509 const PetscInt *ia, *ja; 7510 PetscBool set, flag, done; 7511 Mat AA = mat, A; 7512 MPI_Comm comm; 7513 PetscMPIInt rank, size, tag; 7514 MPI_Status status; 7515 PetscContainer container; 7516 EnvelopeData *edata; 7517 Vec seq, par; 7518 IS isglobal; 7519 7520 PetscFunctionBegin; 7521 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7522 PetscCall(MatIsSymmetricKnown(mat, &set, &flag)); 7523 if (!set || !flag) { 7524 /* TODO: only needs nonzero structure of transpose */ 7525 PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA)); 7526 PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN)); 7527 } 7528 PetscCall(MatAIJGetLocalMat(AA, &A)); 7529 PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7530 PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix"); 7531 7532 PetscCall(MatGetLocalSize(mat, &n, NULL)); 7533 PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag)); 7534 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 7535 PetscCallMPI(MPI_Comm_size(comm, &size)); 7536 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7537 7538 PetscCall(PetscMalloc2(n, &sizes, n, &starts)); 7539 7540 if (rank > 0) { 7541 PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7542 PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7543 } 7544 PetscCall(MatGetOwnershipRange(mat, &rstart, NULL)); 7545 for (i = 0; i < n; i++) { 7546 env = PetscMax(env, ja[ia[i + 1] - 1]); 7547 II = rstart + i; 7548 if (env == II) { 7549 starts[lblocks] = tbs; 7550 sizes[lblocks++] = 1 + II - tbs; 7551 tbs = 1 + II; 7552 } 7553 } 7554 if (rank < size - 1) { 7555 PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm)); 7556 PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm)); 7557 } 7558 7559 PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7560 if (!set || !flag) PetscCall(MatDestroy(&AA)); 7561 PetscCall(MatDestroy(&A)); 7562 7563 PetscCall(PetscNew(&edata)); 7564 PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate)); 7565 edata->n = lblocks; 7566 /* create IS needed for extracting blocks from the original matrix */ 7567 PetscCall(PetscMalloc1(lblocks, &edata->is)); 7568 for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i])); 7569 7570 /* Create the resulting inverse matrix structure with preallocation information */ 7571 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C)); 7572 PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 7573 PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat)); 7574 PetscCall(MatSetType(edata->C, MATAIJ)); 7575 7576 /* Communicate the start and end of each row, from each block to the correct rank */ 7577 /* TODO: Use PetscSF instead of VecScatter */ 7578 for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i]; 7579 PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq)); 7580 PetscCall(VecGetArrayWrite(seq, &seqv)); 7581 for (PetscInt i = 0; i < lblocks; i++) { 7582 for (PetscInt j = 0; j < sizes[i]; j++) { 7583 seqv[cnt] = starts[i]; 7584 seqv[cnt + 1] = starts[i] + sizes[i]; 7585 cnt += 2; 7586 } 7587 } 7588 PetscCall(VecRestoreArrayWrite(seq, &seqv)); 7589 PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 7590 sc -= cnt; 7591 PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par)); 7592 PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal)); 7593 PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter)); 7594 PetscCall(ISDestroy(&isglobal)); 7595 PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7596 PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7597 PetscCall(VecScatterDestroy(&scatter)); 7598 PetscCall(VecDestroy(&seq)); 7599 PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend)); 7600 PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag)); 7601 PetscCall(VecGetArrayRead(par, &parv)); 7602 cnt = 0; 7603 PetscCall(MatGetSize(mat, NULL, &n)); 7604 for (PetscInt i = 0; i < mat->rmap->n; i++) { 7605 PetscInt start, end, d = 0, od = 0; 7606 7607 start = (PetscInt)PetscRealPart(parv[cnt]); 7608 end = (PetscInt)PetscRealPart(parv[cnt + 1]); 7609 cnt += 2; 7610 7611 if (start < cstart) { 7612 od += cstart - start + n - cend; 7613 d += cend - cstart; 7614 } else if (start < cend) { 7615 od += n - cend; 7616 d += cend - start; 7617 } else od += n - start; 7618 if (end <= cstart) { 7619 od -= cstart - end + n - cend; 7620 d -= cend - cstart; 7621 } else if (end < cend) { 7622 od -= n - cend; 7623 d -= cend - end; 7624 } else od -= n - end; 7625 7626 odiag[i] = od; 7627 diag[i] = d; 7628 } 7629 PetscCall(VecRestoreArrayRead(par, &parv)); 7630 PetscCall(VecDestroy(&par)); 7631 PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL)); 7632 PetscCall(PetscFree2(diag, odiag)); 7633 PetscCall(PetscFree2(sizes, starts)); 7634 7635 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container)); 7636 PetscCall(PetscContainerSetPointer(container, edata)); 7637 PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy)); 7638 PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container)); 7639 PetscCall(PetscObjectDereference((PetscObject)container)); 7640 PetscFunctionReturn(PETSC_SUCCESS); 7641 } 7642 7643 /*@ 7644 MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A 7645 7646 Collective 7647 7648 Input Parameters: 7649 + A - the matrix 7650 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine 7651 7652 Output Parameter: 7653 . C - matrix with inverted block diagonal of `A` 7654 7655 Level: advanced 7656 7657 Note: 7658 For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal. 7659 7660 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()` 7661 @*/ 7662 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C) 7663 { 7664 PetscContainer container; 7665 EnvelopeData *edata; 7666 PetscObjectState nonzerostate; 7667 7668 PetscFunctionBegin; 7669 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7670 if (!container) { 7671 PetscCall(MatComputeVariableBlockEnvelope(A)); 7672 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7673 } 7674 PetscCall(PetscContainerGetPointer(container, (void **)&edata)); 7675 PetscCall(MatGetNonzeroState(A, &nonzerostate)); 7676 PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure"); 7677 PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output"); 7678 7679 PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat)); 7680 *C = edata->C; 7681 7682 for (PetscInt i = 0; i < edata->n; i++) { 7683 Mat D; 7684 PetscScalar *dvalues; 7685 7686 PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D)); 7687 PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE)); 7688 PetscCall(MatSeqDenseInvert(D)); 7689 PetscCall(MatDenseGetArray(D, &dvalues)); 7690 PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES)); 7691 PetscCall(MatDestroy(&D)); 7692 } 7693 PetscCall(MatDestroySubMatrices(edata->n, &edata->mat)); 7694 PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY)); 7695 PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY)); 7696 PetscFunctionReturn(PETSC_SUCCESS); 7697 } 7698 7699 /*@ 7700 MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size 7701 7702 Logically Collective 7703 7704 Input Parameters: 7705 + mat - the matrix 7706 . nblocks - the number of blocks on this process, each block can only exist on a single process 7707 - bsizes - the block sizes 7708 7709 Level: intermediate 7710 7711 Notes: 7712 Currently used by `PCVPBJACOBI` for `MATAIJ` matrices 7713 7714 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. 7715 7716 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, 7717 `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI` 7718 @*/ 7719 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes) 7720 { 7721 PetscInt i, ncnt = 0, nlocal; 7722 7723 PetscFunctionBegin; 7724 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7725 PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero"); 7726 PetscCall(MatGetLocalSize(mat, &nlocal, NULL)); 7727 for (i = 0; i < nblocks; i++) ncnt += bsizes[i]; 7728 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); 7729 PetscCall(PetscFree(mat->bsizes)); 7730 mat->nblocks = nblocks; 7731 PetscCall(PetscMalloc1(nblocks, &mat->bsizes)); 7732 PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks)); 7733 PetscFunctionReturn(PETSC_SUCCESS); 7734 } 7735 7736 /*@C 7737 MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size 7738 7739 Logically Collective; No Fortran Support 7740 7741 Input Parameter: 7742 . mat - the matrix 7743 7744 Output Parameters: 7745 + nblocks - the number of blocks on this process 7746 - bsizes - the block sizes 7747 7748 Level: intermediate 7749 7750 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()` 7751 @*/ 7752 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes) 7753 { 7754 PetscFunctionBegin; 7755 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7756 *nblocks = mat->nblocks; 7757 *bsizes = mat->bsizes; 7758 PetscFunctionReturn(PETSC_SUCCESS); 7759 } 7760 7761 /*@ 7762 MatSetBlockSizes - Sets the matrix block row and column sizes. 7763 7764 Logically Collective 7765 7766 Input Parameters: 7767 + mat - the matrix 7768 . rbs - row block size 7769 - cbs - column block size 7770 7771 Level: intermediate 7772 7773 Notes: 7774 Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix. 7775 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7776 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7777 7778 For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes 7779 are compatible with the matrix local sizes. 7780 7781 The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`. 7782 7783 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()` 7784 @*/ 7785 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs) 7786 { 7787 PetscFunctionBegin; 7788 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7789 PetscValidLogicalCollectiveInt(mat, rbs, 2); 7790 PetscValidLogicalCollectiveInt(mat, cbs, 3); 7791 PetscTryTypeMethod(mat, setblocksizes, rbs, cbs); 7792 if (mat->rmap->refcnt) { 7793 ISLocalToGlobalMapping l2g = NULL; 7794 PetscLayout nmap = NULL; 7795 7796 PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap)); 7797 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g)); 7798 PetscCall(PetscLayoutDestroy(&mat->rmap)); 7799 mat->rmap = nmap; 7800 mat->rmap->mapping = l2g; 7801 } 7802 if (mat->cmap->refcnt) { 7803 ISLocalToGlobalMapping l2g = NULL; 7804 PetscLayout nmap = NULL; 7805 7806 PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap)); 7807 if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g)); 7808 PetscCall(PetscLayoutDestroy(&mat->cmap)); 7809 mat->cmap = nmap; 7810 mat->cmap->mapping = l2g; 7811 } 7812 PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs)); 7813 PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs)); 7814 PetscFunctionReturn(PETSC_SUCCESS); 7815 } 7816 7817 /*@ 7818 MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices 7819 7820 Logically Collective 7821 7822 Input Parameters: 7823 + mat - the matrix 7824 . fromRow - matrix from which to copy row block size 7825 - fromCol - matrix from which to copy column block size (can be same as fromRow) 7826 7827 Level: developer 7828 7829 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()` 7830 @*/ 7831 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol) 7832 { 7833 PetscFunctionBegin; 7834 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7835 PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2); 7836 PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3); 7837 if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs)); 7838 if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs)); 7839 PetscFunctionReturn(PETSC_SUCCESS); 7840 } 7841 7842 /*@ 7843 MatResidual - Default routine to calculate the residual r = b - Ax 7844 7845 Collective 7846 7847 Input Parameters: 7848 + mat - the matrix 7849 . b - the right-hand-side 7850 - x - the approximate solution 7851 7852 Output Parameter: 7853 . r - location to store the residual 7854 7855 Level: developer 7856 7857 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()` 7858 @*/ 7859 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r) 7860 { 7861 PetscFunctionBegin; 7862 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7863 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 7864 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 7865 PetscValidHeaderSpecific(r, VEC_CLASSID, 4); 7866 PetscValidType(mat, 1); 7867 MatCheckPreallocated(mat, 1); 7868 PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0)); 7869 if (!mat->ops->residual) { 7870 PetscCall(MatMult(mat, x, r)); 7871 PetscCall(VecAYPX(r, -1.0, b)); 7872 } else { 7873 PetscUseTypeMethod(mat, residual, b, x, r); 7874 } 7875 PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0)); 7876 PetscFunctionReturn(PETSC_SUCCESS); 7877 } 7878 7879 /*MC 7880 MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix 7881 7882 Synopsis: 7883 MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 7884 7885 Not Collective 7886 7887 Input Parameters: 7888 + A - the matrix 7889 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7890 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7891 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7892 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7893 always used. 7894 7895 Output Parameters: 7896 + n - number of local rows in the (possibly compressed) matrix 7897 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 7898 . ja - the column indices 7899 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7900 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7901 7902 Level: developer 7903 7904 Note: 7905 Use `MatRestoreRowIJF90()` when you no longer need access to the data 7906 7907 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()` 7908 M*/ 7909 7910 /*MC 7911 MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()` 7912 7913 Synopsis: 7914 MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 7915 7916 Not Collective 7917 7918 Input Parameters: 7919 + A - the matrix 7920 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7921 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7922 inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7923 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7924 always used. 7925 . n - number of local rows in the (possibly compressed) matrix 7926 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 7927 . ja - the column indices 7928 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7929 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7930 7931 Level: developer 7932 7933 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()` 7934 M*/ 7935 7936 /*@C 7937 MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix 7938 7939 Collective 7940 7941 Input Parameters: 7942 + mat - the matrix 7943 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7944 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7945 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7946 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7947 always used. 7948 7949 Output Parameters: 7950 + n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed 7951 . 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 7952 . ja - the column indices, use `NULL` if not needed 7953 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7954 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7955 7956 Level: developer 7957 7958 Notes: 7959 You CANNOT change any of the ia[] or ja[] values. 7960 7961 Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values. 7962 7963 Fortran Notes: 7964 Use 7965 .vb 7966 PetscInt, pointer :: ia(:),ja(:) 7967 call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr) 7968 ! Access the ith and jth entries via ia(i) and ja(j) 7969 .ve 7970 `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()` 7971 7972 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()` 7973 @*/ 7974 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7975 { 7976 PetscFunctionBegin; 7977 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7978 PetscValidType(mat, 1); 7979 if (n) PetscAssertPointer(n, 5); 7980 if (ia) PetscAssertPointer(ia, 6); 7981 if (ja) PetscAssertPointer(ja, 7); 7982 if (done) PetscAssertPointer(done, 8); 7983 MatCheckPreallocated(mat, 1); 7984 if (!mat->ops->getrowij && done) *done = PETSC_FALSE; 7985 else { 7986 if (done) *done = PETSC_TRUE; 7987 PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0)); 7988 PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done); 7989 PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0)); 7990 } 7991 PetscFunctionReturn(PETSC_SUCCESS); 7992 } 7993 7994 /*@C 7995 MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices. 7996 7997 Collective 7998 7999 Input Parameters: 8000 + mat - the matrix 8001 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8002 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be 8003 symmetrized 8004 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8005 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8006 always used. 8007 . n - number of columns in the (possibly compressed) matrix 8008 . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix 8009 - ja - the row indices 8010 8011 Output Parameter: 8012 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned 8013 8014 Level: developer 8015 8016 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 8017 @*/ 8018 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8019 { 8020 PetscFunctionBegin; 8021 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8022 PetscValidType(mat, 1); 8023 PetscAssertPointer(n, 5); 8024 if (ia) PetscAssertPointer(ia, 6); 8025 if (ja) PetscAssertPointer(ja, 7); 8026 PetscAssertPointer(done, 8); 8027 MatCheckPreallocated(mat, 1); 8028 if (!mat->ops->getcolumnij) *done = PETSC_FALSE; 8029 else { 8030 *done = PETSC_TRUE; 8031 PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8032 } 8033 PetscFunctionReturn(PETSC_SUCCESS); 8034 } 8035 8036 /*@C 8037 MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`. 8038 8039 Collective 8040 8041 Input Parameters: 8042 + mat - the matrix 8043 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8044 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8045 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8046 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8047 always used. 8048 . n - size of (possibly compressed) matrix 8049 . ia - the row pointers 8050 - ja - the column indices 8051 8052 Output Parameter: 8053 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8054 8055 Level: developer 8056 8057 Note: 8058 This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental 8059 us of the array after it has been restored. If you pass `NULL`, it will 8060 not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid. 8061 8062 Fortran Notes: 8063 `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()` 8064 8065 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()` 8066 @*/ 8067 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8068 { 8069 PetscFunctionBegin; 8070 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8071 PetscValidType(mat, 1); 8072 if (ia) PetscAssertPointer(ia, 6); 8073 if (ja) PetscAssertPointer(ja, 7); 8074 if (done) PetscAssertPointer(done, 8); 8075 MatCheckPreallocated(mat, 1); 8076 8077 if (!mat->ops->restorerowij && done) *done = PETSC_FALSE; 8078 else { 8079 if (done) *done = PETSC_TRUE; 8080 PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8081 if (n) *n = 0; 8082 if (ia) *ia = NULL; 8083 if (ja) *ja = NULL; 8084 } 8085 PetscFunctionReturn(PETSC_SUCCESS); 8086 } 8087 8088 /*@C 8089 MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`. 8090 8091 Collective 8092 8093 Input Parameters: 8094 + mat - the matrix 8095 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8096 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8097 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8098 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8099 always used. 8100 8101 Output Parameters: 8102 + n - size of (possibly compressed) matrix 8103 . ia - the column pointers 8104 . ja - the row indices 8105 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8106 8107 Level: developer 8108 8109 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()` 8110 @*/ 8111 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8112 { 8113 PetscFunctionBegin; 8114 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8115 PetscValidType(mat, 1); 8116 if (ia) PetscAssertPointer(ia, 6); 8117 if (ja) PetscAssertPointer(ja, 7); 8118 PetscAssertPointer(done, 8); 8119 MatCheckPreallocated(mat, 1); 8120 8121 if (!mat->ops->restorecolumnij) *done = PETSC_FALSE; 8122 else { 8123 *done = PETSC_TRUE; 8124 PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8125 if (n) *n = 0; 8126 if (ia) *ia = NULL; 8127 if (ja) *ja = NULL; 8128 } 8129 PetscFunctionReturn(PETSC_SUCCESS); 8130 } 8131 8132 /*@C 8133 MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or 8134 `MatGetColumnIJ()`. 8135 8136 Collective 8137 8138 Input Parameters: 8139 + mat - the matrix 8140 . ncolors - maximum color value 8141 . n - number of entries in colorarray 8142 - colorarray - array indicating color for each column 8143 8144 Output Parameter: 8145 . iscoloring - coloring generated using colorarray information 8146 8147 Level: developer 8148 8149 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()` 8150 @*/ 8151 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring) 8152 { 8153 PetscFunctionBegin; 8154 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8155 PetscValidType(mat, 1); 8156 PetscAssertPointer(colorarray, 4); 8157 PetscAssertPointer(iscoloring, 5); 8158 MatCheckPreallocated(mat, 1); 8159 8160 if (!mat->ops->coloringpatch) { 8161 PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring)); 8162 } else { 8163 PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring); 8164 } 8165 PetscFunctionReturn(PETSC_SUCCESS); 8166 } 8167 8168 /*@ 8169 MatSetUnfactored - Resets a factored matrix to be treated as unfactored. 8170 8171 Logically Collective 8172 8173 Input Parameter: 8174 . mat - the factored matrix to be reset 8175 8176 Level: developer 8177 8178 Notes: 8179 This routine should be used only with factored matrices formed by in-place 8180 factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE` 8181 format). This option can save memory, for example, when solving nonlinear 8182 systems with a matrix-free Newton-Krylov method and a matrix-based, in-place 8183 ILU(0) preconditioner. 8184 8185 One can specify in-place ILU(0) factorization by calling 8186 .vb 8187 PCType(pc,PCILU); 8188 PCFactorSeUseInPlace(pc); 8189 .ve 8190 or by using the options -pc_type ilu -pc_factor_in_place 8191 8192 In-place factorization ILU(0) can also be used as a local 8193 solver for the blocks within the block Jacobi or additive Schwarz 8194 methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc 8195 for details on setting local solver options. 8196 8197 Most users should employ the `KSP` interface for linear solvers 8198 instead of working directly with matrix algebra routines such as this. 8199 See, e.g., `KSPCreate()`. 8200 8201 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()` 8202 @*/ 8203 PetscErrorCode MatSetUnfactored(Mat mat) 8204 { 8205 PetscFunctionBegin; 8206 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8207 PetscValidType(mat, 1); 8208 MatCheckPreallocated(mat, 1); 8209 mat->factortype = MAT_FACTOR_NONE; 8210 if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS); 8211 PetscUseTypeMethod(mat, setunfactored); 8212 PetscFunctionReturn(PETSC_SUCCESS); 8213 } 8214 8215 /*MC 8216 MatDenseGetArrayF90 - Accesses a matrix array from Fortran 8217 8218 Synopsis: 8219 MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8220 8221 Not Collective 8222 8223 Input Parameter: 8224 . x - matrix 8225 8226 Output Parameters: 8227 + xx_v - the Fortran pointer to the array 8228 - ierr - error code 8229 8230 Example of Usage: 8231 .vb 8232 PetscScalar, pointer xx_v(:,:) 8233 .... 8234 call MatDenseGetArrayF90(x,xx_v,ierr) 8235 a = xx_v(3) 8236 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8237 .ve 8238 8239 Level: advanced 8240 8241 .seealso: [](ch_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()` 8242 M*/ 8243 8244 /*MC 8245 MatDenseRestoreArrayF90 - Restores a matrix array that has been 8246 accessed with `MatDenseGetArrayF90()`. 8247 8248 Synopsis: 8249 MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8250 8251 Not Collective 8252 8253 Input Parameters: 8254 + x - matrix 8255 - xx_v - the Fortran90 pointer to the array 8256 8257 Output Parameter: 8258 . ierr - error code 8259 8260 Example of Usage: 8261 .vb 8262 PetscScalar, pointer xx_v(:,:) 8263 .... 8264 call MatDenseGetArrayF90(x,xx_v,ierr) 8265 a = xx_v(3) 8266 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8267 .ve 8268 8269 Level: advanced 8270 8271 .seealso: [](ch_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()` 8272 M*/ 8273 8274 /*MC 8275 MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran. 8276 8277 Synopsis: 8278 MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8279 8280 Not Collective 8281 8282 Input Parameter: 8283 . x - matrix 8284 8285 Output Parameters: 8286 + xx_v - the Fortran pointer to the array 8287 - ierr - error code 8288 8289 Example of Usage: 8290 .vb 8291 PetscScalar, pointer xx_v(:) 8292 .... 8293 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8294 a = xx_v(3) 8295 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8296 .ve 8297 8298 Level: advanced 8299 8300 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()` 8301 M*/ 8302 8303 /*MC 8304 MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been 8305 accessed with `MatSeqAIJGetArrayF90()`. 8306 8307 Synopsis: 8308 MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8309 8310 Not Collective 8311 8312 Input Parameters: 8313 + x - matrix 8314 - xx_v - the Fortran90 pointer to the array 8315 8316 Output Parameter: 8317 . ierr - error code 8318 8319 Example of Usage: 8320 .vb 8321 PetscScalar, pointer xx_v(:) 8322 .... 8323 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8324 a = xx_v(3) 8325 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8326 .ve 8327 8328 Level: advanced 8329 8330 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()` 8331 M*/ 8332 8333 /*@ 8334 MatCreateSubMatrix - Gets a single submatrix on the same number of processors 8335 as the original matrix. 8336 8337 Collective 8338 8339 Input Parameters: 8340 + mat - the original matrix 8341 . isrow - parallel `IS` containing the rows this processor should obtain 8342 . 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. 8343 - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 8344 8345 Output Parameter: 8346 . newmat - the new submatrix, of the same type as the original matrix 8347 8348 Level: advanced 8349 8350 Notes: 8351 The submatrix will be able to be multiplied with vectors using the same layout as `iscol`. 8352 8353 Some matrix types place restrictions on the row and column indices, such 8354 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; 8355 for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row. 8356 8357 The index sets may not have duplicate entries. 8358 8359 The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`, 8360 the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls 8361 to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX` 8362 will reuse the matrix generated the first time. You should call `MatDestroy()` on `newmat` when 8363 you are finished using it. 8364 8365 The communicator of the newly obtained matrix is ALWAYS the same as the communicator of 8366 the input matrix. 8367 8368 If `iscol` is `NULL` then all columns are obtained (not supported in Fortran). 8369 8370 Example usage: 8371 Consider the following 8x8 matrix with 34 non-zero values, that is 8372 assembled across 3 processors. Let's assume that proc0 owns 3 rows, 8373 proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 8374 as follows 8375 .vb 8376 1 2 0 | 0 3 0 | 0 4 8377 Proc0 0 5 6 | 7 0 0 | 8 0 8378 9 0 10 | 11 0 0 | 12 0 8379 ------------------------------------- 8380 13 0 14 | 15 16 17 | 0 0 8381 Proc1 0 18 0 | 19 20 21 | 0 0 8382 0 0 0 | 22 23 0 | 24 0 8383 ------------------------------------- 8384 Proc2 25 26 27 | 0 0 28 | 29 0 8385 30 0 0 | 31 32 33 | 0 34 8386 .ve 8387 8388 Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6]. The resulting submatrix is 8389 8390 .vb 8391 2 0 | 0 3 0 | 0 8392 Proc0 5 6 | 7 0 0 | 8 8393 ------------------------------- 8394 Proc1 18 0 | 19 20 21 | 0 8395 ------------------------------- 8396 Proc2 26 27 | 0 0 28 | 29 8397 0 0 | 31 32 33 | 0 8398 .ve 8399 8400 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()` 8401 @*/ 8402 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat) 8403 { 8404 PetscMPIInt size; 8405 Mat *local; 8406 IS iscoltmp; 8407 PetscBool flg; 8408 8409 PetscFunctionBegin; 8410 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8411 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 8412 if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 8413 PetscAssertPointer(newmat, 5); 8414 if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5); 8415 PetscValidType(mat, 1); 8416 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8417 PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX"); 8418 8419 MatCheckPreallocated(mat, 1); 8420 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8421 8422 if (!iscol || isrow == iscol) { 8423 PetscBool stride; 8424 PetscMPIInt grabentirematrix = 0, grab; 8425 PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride)); 8426 if (stride) { 8427 PetscInt first, step, n, rstart, rend; 8428 PetscCall(ISStrideGetInfo(isrow, &first, &step)); 8429 if (step == 1) { 8430 PetscCall(MatGetOwnershipRange(mat, &rstart, &rend)); 8431 if (rstart == first) { 8432 PetscCall(ISGetLocalSize(isrow, &n)); 8433 if (n == rend - rstart) grabentirematrix = 1; 8434 } 8435 } 8436 } 8437 PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat))); 8438 if (grab) { 8439 PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n")); 8440 if (cll == MAT_INITIAL_MATRIX) { 8441 *newmat = mat; 8442 PetscCall(PetscObjectReference((PetscObject)mat)); 8443 } 8444 PetscFunctionReturn(PETSC_SUCCESS); 8445 } 8446 } 8447 8448 if (!iscol) { 8449 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp)); 8450 } else { 8451 iscoltmp = iscol; 8452 } 8453 8454 /* if original matrix is on just one processor then use submatrix generated */ 8455 if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) { 8456 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat)); 8457 goto setproperties; 8458 } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) { 8459 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local)); 8460 *newmat = *local; 8461 PetscCall(PetscFree(local)); 8462 goto setproperties; 8463 } else if (!mat->ops->createsubmatrix) { 8464 /* Create a new matrix type that implements the operation using the full matrix */ 8465 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8466 switch (cll) { 8467 case MAT_INITIAL_MATRIX: 8468 PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat)); 8469 break; 8470 case MAT_REUSE_MATRIX: 8471 PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp)); 8472 break; 8473 default: 8474 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX"); 8475 } 8476 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8477 goto setproperties; 8478 } 8479 8480 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8481 PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat); 8482 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8483 8484 setproperties: 8485 PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg)); 8486 if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat)); 8487 if (!iscol) PetscCall(ISDestroy(&iscoltmp)); 8488 if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat)); 8489 PetscFunctionReturn(PETSC_SUCCESS); 8490 } 8491 8492 /*@ 8493 MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix 8494 8495 Not Collective 8496 8497 Input Parameters: 8498 + A - the matrix we wish to propagate options from 8499 - B - the matrix we wish to propagate options to 8500 8501 Level: beginner 8502 8503 Note: 8504 Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL` 8505 8506 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 8507 @*/ 8508 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B) 8509 { 8510 PetscFunctionBegin; 8511 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8512 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 8513 B->symmetry_eternal = A->symmetry_eternal; 8514 B->structural_symmetry_eternal = A->structural_symmetry_eternal; 8515 B->symmetric = A->symmetric; 8516 B->structurally_symmetric = A->structurally_symmetric; 8517 B->spd = A->spd; 8518 B->hermitian = A->hermitian; 8519 PetscFunctionReturn(PETSC_SUCCESS); 8520 } 8521 8522 /*@ 8523 MatStashSetInitialSize - sets the sizes of the matrix stash, that is 8524 used during the assembly process to store values that belong to 8525 other processors. 8526 8527 Not Collective 8528 8529 Input Parameters: 8530 + mat - the matrix 8531 . size - the initial size of the stash. 8532 - bsize - the initial size of the block-stash(if used). 8533 8534 Options Database Keys: 8535 + -matstash_initial_size <size> or <size0,size1,...sizep-1> - set initial size 8536 - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1> - set initial block size 8537 8538 Level: intermediate 8539 8540 Notes: 8541 The block-stash is used for values set with `MatSetValuesBlocked()` while 8542 the stash is used for values set with `MatSetValues()` 8543 8544 Run with the option -info and look for output of the form 8545 MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs. 8546 to determine the appropriate value, MM, to use for size and 8547 MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs. 8548 to determine the value, BMM to use for bsize 8549 8550 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()` 8551 @*/ 8552 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize) 8553 { 8554 PetscFunctionBegin; 8555 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8556 PetscValidType(mat, 1); 8557 PetscCall(MatStashSetInitialSize_Private(&mat->stash, size)); 8558 PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize)); 8559 PetscFunctionReturn(PETSC_SUCCESS); 8560 } 8561 8562 /*@ 8563 MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of 8564 the matrix 8565 8566 Neighbor-wise Collective 8567 8568 Input Parameters: 8569 + A - the matrix 8570 . x - the vector to be multiplied by the interpolation operator 8571 - y - the vector to be added to the result 8572 8573 Output Parameter: 8574 . w - the resulting vector 8575 8576 Level: intermediate 8577 8578 Notes: 8579 `w` may be the same vector as `y`. 8580 8581 This allows one to use either the restriction or interpolation (its transpose) 8582 matrix to do the interpolation 8583 8584 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8585 @*/ 8586 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w) 8587 { 8588 PetscInt M, N, Ny; 8589 8590 PetscFunctionBegin; 8591 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8592 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8593 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8594 PetscValidHeaderSpecific(w, VEC_CLASSID, 4); 8595 PetscCall(MatGetSize(A, &M, &N)); 8596 PetscCall(VecGetSize(y, &Ny)); 8597 if (M == Ny) { 8598 PetscCall(MatMultAdd(A, x, y, w)); 8599 } else { 8600 PetscCall(MatMultTransposeAdd(A, x, y, w)); 8601 } 8602 PetscFunctionReturn(PETSC_SUCCESS); 8603 } 8604 8605 /*@ 8606 MatInterpolate - y = A*x or A'*x depending on the shape of 8607 the matrix 8608 8609 Neighbor-wise Collective 8610 8611 Input Parameters: 8612 + A - the matrix 8613 - x - the vector to be interpolated 8614 8615 Output Parameter: 8616 . y - the resulting vector 8617 8618 Level: intermediate 8619 8620 Note: 8621 This allows one to use either the restriction or interpolation (its transpose) 8622 matrix to do the interpolation 8623 8624 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8625 @*/ 8626 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y) 8627 { 8628 PetscInt M, N, Ny; 8629 8630 PetscFunctionBegin; 8631 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8632 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8633 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8634 PetscCall(MatGetSize(A, &M, &N)); 8635 PetscCall(VecGetSize(y, &Ny)); 8636 if (M == Ny) { 8637 PetscCall(MatMult(A, x, y)); 8638 } else { 8639 PetscCall(MatMultTranspose(A, x, y)); 8640 } 8641 PetscFunctionReturn(PETSC_SUCCESS); 8642 } 8643 8644 /*@ 8645 MatRestrict - y = A*x or A'*x 8646 8647 Neighbor-wise Collective 8648 8649 Input Parameters: 8650 + A - the matrix 8651 - x - the vector to be restricted 8652 8653 Output Parameter: 8654 . y - the resulting vector 8655 8656 Level: intermediate 8657 8658 Note: 8659 This allows one to use either the restriction or interpolation (its transpose) 8660 matrix to do the restriction 8661 8662 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG` 8663 @*/ 8664 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y) 8665 { 8666 PetscInt M, N, Ny; 8667 8668 PetscFunctionBegin; 8669 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8670 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8671 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8672 PetscCall(MatGetSize(A, &M, &N)); 8673 PetscCall(VecGetSize(y, &Ny)); 8674 if (M == Ny) { 8675 PetscCall(MatMult(A, x, y)); 8676 } else { 8677 PetscCall(MatMultTranspose(A, x, y)); 8678 } 8679 PetscFunctionReturn(PETSC_SUCCESS); 8680 } 8681 8682 /*@ 8683 MatMatInterpolateAdd - Y = W + A*X or W + A'*X 8684 8685 Neighbor-wise Collective 8686 8687 Input Parameters: 8688 + A - the matrix 8689 . x - the input dense matrix to be multiplied 8690 - w - the input dense matrix to be added to the result 8691 8692 Output Parameter: 8693 . y - the output dense matrix 8694 8695 Level: intermediate 8696 8697 Note: 8698 This allows one to use either the restriction or interpolation (its transpose) 8699 matrix to do the interpolation. y matrix can be reused if already created with the proper sizes, 8700 otherwise it will be recreated. y must be initialized to `NULL` if not supplied. 8701 8702 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG` 8703 @*/ 8704 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y) 8705 { 8706 PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0; 8707 PetscBool trans = PETSC_TRUE; 8708 MatReuse reuse = MAT_INITIAL_MATRIX; 8709 8710 PetscFunctionBegin; 8711 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8712 PetscValidHeaderSpecific(x, MAT_CLASSID, 2); 8713 PetscValidType(x, 2); 8714 if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3); 8715 if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4); 8716 PetscCall(MatGetSize(A, &M, &N)); 8717 PetscCall(MatGetSize(x, &Mx, &Nx)); 8718 if (N == Mx) trans = PETSC_FALSE; 8719 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); 8720 Mo = trans ? N : M; 8721 if (*y) { 8722 PetscCall(MatGetSize(*y, &My, &Ny)); 8723 if (Mo == My && Nx == Ny) { 8724 reuse = MAT_REUSE_MATRIX; 8725 } else { 8726 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); 8727 PetscCall(MatDestroy(y)); 8728 } 8729 } 8730 8731 if (w && *y == w) { /* this is to minimize changes in PCMG */ 8732 PetscBool flg; 8733 8734 PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w)); 8735 if (w) { 8736 PetscInt My, Ny, Mw, Nw; 8737 8738 PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg)); 8739 PetscCall(MatGetSize(*y, &My, &Ny)); 8740 PetscCall(MatGetSize(w, &Mw, &Nw)); 8741 if (!flg || My != Mw || Ny != Nw) w = NULL; 8742 } 8743 if (!w) { 8744 PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w)); 8745 PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w)); 8746 PetscCall(PetscObjectDereference((PetscObject)w)); 8747 } else { 8748 PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN)); 8749 } 8750 } 8751 if (!trans) { 8752 PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8753 } else { 8754 PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8755 } 8756 if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN)); 8757 PetscFunctionReturn(PETSC_SUCCESS); 8758 } 8759 8760 /*@ 8761 MatMatInterpolate - Y = A*X or A'*X 8762 8763 Neighbor-wise Collective 8764 8765 Input Parameters: 8766 + A - the matrix 8767 - x - the input dense matrix 8768 8769 Output Parameter: 8770 . y - the output dense matrix 8771 8772 Level: intermediate 8773 8774 Note: 8775 This allows one to use either the restriction or interpolation (its transpose) 8776 matrix to do the interpolation. y matrix can be reused if already created with the proper sizes, 8777 otherwise it will be recreated. y must be initialized to `NULL` if not supplied. 8778 8779 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG` 8780 @*/ 8781 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y) 8782 { 8783 PetscFunctionBegin; 8784 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8785 PetscFunctionReturn(PETSC_SUCCESS); 8786 } 8787 8788 /*@ 8789 MatMatRestrict - Y = A*X or A'*X 8790 8791 Neighbor-wise Collective 8792 8793 Input Parameters: 8794 + A - the matrix 8795 - x - the input dense matrix 8796 8797 Output Parameter: 8798 . y - the output dense matrix 8799 8800 Level: intermediate 8801 8802 Note: 8803 This allows one to use either the restriction or interpolation (its transpose) 8804 matrix to do the restriction. y matrix can be reused if already created with the proper sizes, 8805 otherwise it will be recreated. y must be initialized to `NULL` if not supplied. 8806 8807 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG` 8808 @*/ 8809 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y) 8810 { 8811 PetscFunctionBegin; 8812 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8813 PetscFunctionReturn(PETSC_SUCCESS); 8814 } 8815 8816 /*@ 8817 MatGetNullSpace - retrieves the null space of a matrix. 8818 8819 Logically Collective 8820 8821 Input Parameters: 8822 + mat - the matrix 8823 - nullsp - the null space object 8824 8825 Level: developer 8826 8827 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace` 8828 @*/ 8829 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp) 8830 { 8831 PetscFunctionBegin; 8832 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8833 PetscAssertPointer(nullsp, 2); 8834 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp; 8835 PetscFunctionReturn(PETSC_SUCCESS); 8836 } 8837 8838 /*@ 8839 MatSetNullSpace - attaches a null space to a matrix. 8840 8841 Logically Collective 8842 8843 Input Parameters: 8844 + mat - the matrix 8845 - nullsp - the null space object 8846 8847 Level: advanced 8848 8849 Notes: 8850 This null space is used by the `KSP` linear solvers to solve singular systems. 8851 8852 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` 8853 8854 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 to 8855 to zero but the linear system will still be solved in a least squares sense. 8856 8857 The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that 8858 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). 8859 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 8860 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 8861 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). 8862 This \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix. 8863 8864 If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called 8865 `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this 8866 routine also automatically calls `MatSetTransposeNullSpace()`. 8867 8868 The user should call `MatNullSpaceDestroy()`. 8869 8870 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, 8871 `KSPSetPCSide()` 8872 @*/ 8873 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp) 8874 { 8875 PetscFunctionBegin; 8876 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8877 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8878 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8879 PetscCall(MatNullSpaceDestroy(&mat->nullsp)); 8880 mat->nullsp = nullsp; 8881 if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp)); 8882 PetscFunctionReturn(PETSC_SUCCESS); 8883 } 8884 8885 /*@ 8886 MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix. 8887 8888 Logically Collective 8889 8890 Input Parameters: 8891 + mat - the matrix 8892 - nullsp - the null space object 8893 8894 Level: developer 8895 8896 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()` 8897 @*/ 8898 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp) 8899 { 8900 PetscFunctionBegin; 8901 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8902 PetscValidType(mat, 1); 8903 PetscAssertPointer(nullsp, 2); 8904 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp; 8905 PetscFunctionReturn(PETSC_SUCCESS); 8906 } 8907 8908 /*@ 8909 MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix 8910 8911 Logically Collective 8912 8913 Input Parameters: 8914 + mat - the matrix 8915 - nullsp - the null space object 8916 8917 Level: advanced 8918 8919 Notes: 8920 This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning. 8921 8922 See `MatSetNullSpace()` 8923 8924 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()` 8925 @*/ 8926 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp) 8927 { 8928 PetscFunctionBegin; 8929 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8930 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8931 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8932 PetscCall(MatNullSpaceDestroy(&mat->transnullsp)); 8933 mat->transnullsp = nullsp; 8934 PetscFunctionReturn(PETSC_SUCCESS); 8935 } 8936 8937 /*@ 8938 MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions 8939 This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix. 8940 8941 Logically Collective 8942 8943 Input Parameters: 8944 + mat - the matrix 8945 - nullsp - the null space object 8946 8947 Level: advanced 8948 8949 Notes: 8950 Overwrites any previous near null space that may have been attached 8951 8952 You can remove the null space by calling this routine with an nullsp of `NULL` 8953 8954 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()` 8955 @*/ 8956 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp) 8957 { 8958 PetscFunctionBegin; 8959 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8960 PetscValidType(mat, 1); 8961 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8962 MatCheckPreallocated(mat, 1); 8963 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8964 PetscCall(MatNullSpaceDestroy(&mat->nearnullsp)); 8965 mat->nearnullsp = nullsp; 8966 PetscFunctionReturn(PETSC_SUCCESS); 8967 } 8968 8969 /*@ 8970 MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()` 8971 8972 Not Collective 8973 8974 Input Parameter: 8975 . mat - the matrix 8976 8977 Output Parameter: 8978 . nullsp - the null space object, `NULL` if not set 8979 8980 Level: advanced 8981 8982 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()` 8983 @*/ 8984 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp) 8985 { 8986 PetscFunctionBegin; 8987 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8988 PetscValidType(mat, 1); 8989 PetscAssertPointer(nullsp, 2); 8990 MatCheckPreallocated(mat, 1); 8991 *nullsp = mat->nearnullsp; 8992 PetscFunctionReturn(PETSC_SUCCESS); 8993 } 8994 8995 /*@C 8996 MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix. 8997 8998 Collective 8999 9000 Input Parameters: 9001 + mat - the matrix 9002 . row - row/column permutation 9003 - info - information on desired factorization process 9004 9005 Level: developer 9006 9007 Notes: 9008 Probably really in-place only when level of fill is zero, otherwise allocates 9009 new space to store factored matrix and deletes previous memory. 9010 9011 Most users should employ the `KSP` interface for linear solvers 9012 instead of working directly with matrix algebra routines such as this. 9013 See, e.g., `KSPCreate()`. 9014 9015 Developer Notes: 9016 The Fortran interface is not autogenerated as the 9017 interface definition cannot be generated correctly [due to `MatFactorInfo`] 9018 9019 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 9020 @*/ 9021 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info) 9022 { 9023 PetscFunctionBegin; 9024 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9025 PetscValidType(mat, 1); 9026 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 9027 PetscAssertPointer(info, 3); 9028 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 9029 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 9030 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 9031 MatCheckPreallocated(mat, 1); 9032 PetscUseTypeMethod(mat, iccfactor, row, info); 9033 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9034 PetscFunctionReturn(PETSC_SUCCESS); 9035 } 9036 9037 /*@ 9038 MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the 9039 ghosted ones. 9040 9041 Not Collective 9042 9043 Input Parameters: 9044 + mat - the matrix 9045 - diag - the diagonal values, including ghost ones 9046 9047 Level: developer 9048 9049 Notes: 9050 Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices 9051 9052 This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()` 9053 9054 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 9055 @*/ 9056 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag) 9057 { 9058 PetscMPIInt size; 9059 9060 PetscFunctionBegin; 9061 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9062 PetscValidHeaderSpecific(diag, VEC_CLASSID, 2); 9063 PetscValidType(mat, 1); 9064 9065 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled"); 9066 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 9067 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 9068 if (size == 1) { 9069 PetscInt n, m; 9070 PetscCall(VecGetSize(diag, &n)); 9071 PetscCall(MatGetSize(mat, NULL, &m)); 9072 PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions"); 9073 PetscCall(MatDiagonalScale(mat, NULL, diag)); 9074 } else { 9075 PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag)); 9076 } 9077 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 9078 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9079 PetscFunctionReturn(PETSC_SUCCESS); 9080 } 9081 9082 /*@ 9083 MatGetInertia - Gets the inertia from a factored matrix 9084 9085 Collective 9086 9087 Input Parameter: 9088 . mat - the matrix 9089 9090 Output Parameters: 9091 + nneg - number of negative eigenvalues 9092 . nzero - number of zero eigenvalues 9093 - npos - number of positive eigenvalues 9094 9095 Level: advanced 9096 9097 Note: 9098 Matrix must have been factored by `MatCholeskyFactor()` 9099 9100 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()` 9101 @*/ 9102 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos) 9103 { 9104 PetscFunctionBegin; 9105 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9106 PetscValidType(mat, 1); 9107 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9108 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled"); 9109 PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos); 9110 PetscFunctionReturn(PETSC_SUCCESS); 9111 } 9112 9113 /*@C 9114 MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors 9115 9116 Neighbor-wise Collective 9117 9118 Input Parameters: 9119 + mat - the factored matrix obtained with `MatGetFactor()` 9120 - b - the right-hand-side vectors 9121 9122 Output Parameter: 9123 . x - the result vectors 9124 9125 Level: developer 9126 9127 Note: 9128 The vectors `b` and `x` cannot be the same. I.e., one cannot 9129 call `MatSolves`(A,x,x). 9130 9131 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()` 9132 @*/ 9133 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x) 9134 { 9135 PetscFunctionBegin; 9136 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9137 PetscValidType(mat, 1); 9138 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 9139 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9140 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 9141 9142 MatCheckPreallocated(mat, 1); 9143 PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0)); 9144 PetscUseTypeMethod(mat, solves, b, x); 9145 PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0)); 9146 PetscFunctionReturn(PETSC_SUCCESS); 9147 } 9148 9149 /*@ 9150 MatIsSymmetric - Test whether a matrix is symmetric 9151 9152 Collective 9153 9154 Input Parameters: 9155 + A - the matrix to test 9156 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose) 9157 9158 Output Parameter: 9159 . flg - the result 9160 9161 Level: intermediate 9162 9163 Notes: 9164 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9165 9166 If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()` 9167 9168 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9169 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9170 9171 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`, 9172 `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL` 9173 @*/ 9174 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg) 9175 { 9176 PetscFunctionBegin; 9177 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9178 PetscAssertPointer(flg, 3); 9179 9180 if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE; 9181 else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE; 9182 else { 9183 PetscUseTypeMethod(A, issymmetric, tol, flg); 9184 if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg)); 9185 } 9186 PetscFunctionReturn(PETSC_SUCCESS); 9187 } 9188 9189 /*@ 9190 MatIsHermitian - Test whether a matrix is Hermitian 9191 9192 Collective 9193 9194 Input Parameters: 9195 + A - the matrix to test 9196 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian) 9197 9198 Output Parameter: 9199 . flg - the result 9200 9201 Level: intermediate 9202 9203 Notes: 9204 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9205 9206 If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()` 9207 9208 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9209 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`) 9210 9211 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, 9212 `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL` 9213 @*/ 9214 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg) 9215 { 9216 PetscFunctionBegin; 9217 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9218 PetscAssertPointer(flg, 3); 9219 9220 if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE; 9221 else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE; 9222 else { 9223 PetscUseTypeMethod(A, ishermitian, tol, flg); 9224 if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg)); 9225 } 9226 PetscFunctionReturn(PETSC_SUCCESS); 9227 } 9228 9229 /*@ 9230 MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state 9231 9232 Not Collective 9233 9234 Input Parameter: 9235 . A - the matrix to check 9236 9237 Output Parameters: 9238 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid) 9239 - flg - the result (only valid if set is `PETSC_TRUE`) 9240 9241 Level: advanced 9242 9243 Notes: 9244 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()` 9245 if you want it explicitly checked 9246 9247 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9248 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9249 9250 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9251 @*/ 9252 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9253 { 9254 PetscFunctionBegin; 9255 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9256 PetscAssertPointer(set, 2); 9257 PetscAssertPointer(flg, 3); 9258 if (A->symmetric != PETSC_BOOL3_UNKNOWN) { 9259 *set = PETSC_TRUE; 9260 *flg = PetscBool3ToBool(A->symmetric); 9261 } else { 9262 *set = PETSC_FALSE; 9263 } 9264 PetscFunctionReturn(PETSC_SUCCESS); 9265 } 9266 9267 /*@ 9268 MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state 9269 9270 Not Collective 9271 9272 Input Parameter: 9273 . A - the matrix to check 9274 9275 Output Parameters: 9276 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid) 9277 - flg - the result (only valid if set is `PETSC_TRUE`) 9278 9279 Level: advanced 9280 9281 Notes: 9282 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). 9283 9284 One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD 9285 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`) 9286 9287 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9288 @*/ 9289 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg) 9290 { 9291 PetscFunctionBegin; 9292 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9293 PetscAssertPointer(set, 2); 9294 PetscAssertPointer(flg, 3); 9295 if (A->spd != PETSC_BOOL3_UNKNOWN) { 9296 *set = PETSC_TRUE; 9297 *flg = PetscBool3ToBool(A->spd); 9298 } else { 9299 *set = PETSC_FALSE; 9300 } 9301 PetscFunctionReturn(PETSC_SUCCESS); 9302 } 9303 9304 /*@ 9305 MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state 9306 9307 Not Collective 9308 9309 Input Parameter: 9310 . A - the matrix to check 9311 9312 Output Parameters: 9313 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid) 9314 - flg - the result (only valid if set is `PETSC_TRUE`) 9315 9316 Level: advanced 9317 9318 Notes: 9319 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()` 9320 if you want it explicitly checked 9321 9322 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9323 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9324 9325 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()` 9326 @*/ 9327 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg) 9328 { 9329 PetscFunctionBegin; 9330 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9331 PetscAssertPointer(set, 2); 9332 PetscAssertPointer(flg, 3); 9333 if (A->hermitian != PETSC_BOOL3_UNKNOWN) { 9334 *set = PETSC_TRUE; 9335 *flg = PetscBool3ToBool(A->hermitian); 9336 } else { 9337 *set = PETSC_FALSE; 9338 } 9339 PetscFunctionReturn(PETSC_SUCCESS); 9340 } 9341 9342 /*@ 9343 MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric 9344 9345 Collective 9346 9347 Input Parameter: 9348 . A - the matrix to test 9349 9350 Output Parameter: 9351 . flg - the result 9352 9353 Level: intermediate 9354 9355 Notes: 9356 If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()` 9357 9358 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 9359 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9360 9361 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()` 9362 @*/ 9363 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg) 9364 { 9365 PetscFunctionBegin; 9366 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9367 PetscAssertPointer(flg, 2); 9368 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9369 *flg = PetscBool3ToBool(A->structurally_symmetric); 9370 } else { 9371 PetscUseTypeMethod(A, isstructurallysymmetric, flg); 9372 PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg)); 9373 } 9374 PetscFunctionReturn(PETSC_SUCCESS); 9375 } 9376 9377 /*@ 9378 MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state 9379 9380 Not Collective 9381 9382 Input Parameter: 9383 . A - the matrix to check 9384 9385 Output Parameters: 9386 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid) 9387 - flg - the result (only valid if set is PETSC_TRUE) 9388 9389 Level: advanced 9390 9391 Notes: 9392 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 9393 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9394 9395 Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation) 9396 9397 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9398 @*/ 9399 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9400 { 9401 PetscFunctionBegin; 9402 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9403 PetscAssertPointer(set, 2); 9404 PetscAssertPointer(flg, 3); 9405 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9406 *set = PETSC_TRUE; 9407 *flg = PetscBool3ToBool(A->structurally_symmetric); 9408 } else { 9409 *set = PETSC_FALSE; 9410 } 9411 PetscFunctionReturn(PETSC_SUCCESS); 9412 } 9413 9414 /*@ 9415 MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need 9416 to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process 9417 9418 Not Collective 9419 9420 Input Parameter: 9421 . mat - the matrix 9422 9423 Output Parameters: 9424 + nstash - the size of the stash 9425 . reallocs - the number of additional mallocs incurred. 9426 . bnstash - the size of the block stash 9427 - breallocs - the number of additional mallocs incurred.in the block stash 9428 9429 Level: advanced 9430 9431 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()` 9432 @*/ 9433 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs) 9434 { 9435 PetscFunctionBegin; 9436 PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs)); 9437 PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs)); 9438 PetscFunctionReturn(PETSC_SUCCESS); 9439 } 9440 9441 /*@C 9442 MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same 9443 parallel layout, `PetscLayout` for rows and columns 9444 9445 Collective 9446 9447 Input Parameter: 9448 . mat - the matrix 9449 9450 Output Parameters: 9451 + right - (optional) vector that the matrix can be multiplied against 9452 - left - (optional) vector that the matrix vector product can be stored in 9453 9454 Level: advanced 9455 9456 Notes: 9457 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()`. 9458 9459 These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed 9460 9461 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()` 9462 @*/ 9463 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left) 9464 { 9465 PetscFunctionBegin; 9466 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9467 PetscValidType(mat, 1); 9468 if (mat->ops->getvecs) { 9469 PetscUseTypeMethod(mat, getvecs, right, left); 9470 } else { 9471 if (right) { 9472 PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup"); 9473 PetscCall(VecCreateWithLayout_Private(mat->cmap, right)); 9474 PetscCall(VecSetType(*right, mat->defaultvectype)); 9475 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9476 if (mat->boundtocpu && mat->bindingpropagates) { 9477 PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE)); 9478 PetscCall(VecBindToCPU(*right, PETSC_TRUE)); 9479 } 9480 #endif 9481 } 9482 if (left) { 9483 PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup"); 9484 PetscCall(VecCreateWithLayout_Private(mat->rmap, left)); 9485 PetscCall(VecSetType(*left, mat->defaultvectype)); 9486 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9487 if (mat->boundtocpu && mat->bindingpropagates) { 9488 PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE)); 9489 PetscCall(VecBindToCPU(*left, PETSC_TRUE)); 9490 } 9491 #endif 9492 } 9493 } 9494 PetscFunctionReturn(PETSC_SUCCESS); 9495 } 9496 9497 /*@C 9498 MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure 9499 with default values. 9500 9501 Not Collective 9502 9503 Input Parameter: 9504 . info - the `MatFactorInfo` data structure 9505 9506 Level: developer 9507 9508 Notes: 9509 The solvers are generally used through the `KSP` and `PC` objects, for example 9510 `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC` 9511 9512 Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed 9513 9514 Developer Notes: 9515 The Fortran interface is not autogenerated as the 9516 interface definition cannot be generated correctly [due to `MatFactorInfo`] 9517 9518 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo` 9519 @*/ 9520 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info) 9521 { 9522 PetscFunctionBegin; 9523 PetscCall(PetscMemzero(info, sizeof(MatFactorInfo))); 9524 PetscFunctionReturn(PETSC_SUCCESS); 9525 } 9526 9527 /*@ 9528 MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed 9529 9530 Collective 9531 9532 Input Parameters: 9533 + mat - the factored matrix 9534 - is - the index set defining the Schur indices (0-based) 9535 9536 Level: advanced 9537 9538 Notes: 9539 Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system. 9540 9541 You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call. 9542 9543 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9544 9545 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`, 9546 `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9547 @*/ 9548 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is) 9549 { 9550 PetscErrorCode (*f)(Mat, IS); 9551 9552 PetscFunctionBegin; 9553 PetscValidType(mat, 1); 9554 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9555 PetscValidType(is, 2); 9556 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 9557 PetscCheckSameComm(mat, 1, is, 2); 9558 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 9559 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f)); 9560 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO"); 9561 PetscCall(MatDestroy(&mat->schur)); 9562 PetscCall((*f)(mat, is)); 9563 PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created"); 9564 PetscFunctionReturn(PETSC_SUCCESS); 9565 } 9566 9567 /*@ 9568 MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step 9569 9570 Logically Collective 9571 9572 Input Parameters: 9573 + F - the factored matrix obtained by calling `MatGetFactor()` 9574 . S - location where to return the Schur complement, can be `NULL` 9575 - status - the status of the Schur complement matrix, can be `NULL` 9576 9577 Level: advanced 9578 9579 Notes: 9580 You must call `MatFactorSetSchurIS()` before calling this routine. 9581 9582 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9583 9584 The routine provides a copy of the Schur matrix stored within the solver data structures. 9585 The caller must destroy the object when it is no longer needed. 9586 If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse. 9587 9588 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) 9589 9590 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9591 9592 Developer Notes: 9593 The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc 9594 matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix. 9595 9596 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9597 @*/ 9598 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9599 { 9600 PetscFunctionBegin; 9601 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9602 if (S) PetscAssertPointer(S, 2); 9603 if (status) PetscAssertPointer(status, 3); 9604 if (S) { 9605 PetscErrorCode (*f)(Mat, Mat *); 9606 9607 PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f)); 9608 if (f) { 9609 PetscCall((*f)(F, S)); 9610 } else { 9611 PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S)); 9612 } 9613 } 9614 if (status) *status = F->schur_status; 9615 PetscFunctionReturn(PETSC_SUCCESS); 9616 } 9617 9618 /*@ 9619 MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix 9620 9621 Logically Collective 9622 9623 Input Parameters: 9624 + F - the factored matrix obtained by calling `MatGetFactor()` 9625 . S - location where to return the Schur complement, can be `NULL` 9626 - status - the status of the Schur complement matrix, can be `NULL` 9627 9628 Level: advanced 9629 9630 Notes: 9631 You must call `MatFactorSetSchurIS()` before calling this routine. 9632 9633 Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS` 9634 9635 The routine returns a the Schur Complement stored within the data structures of the solver. 9636 9637 If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement. 9638 9639 The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed. 9640 9641 Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix 9642 9643 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9644 9645 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9646 @*/ 9647 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9648 { 9649 PetscFunctionBegin; 9650 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9651 if (S) { 9652 PetscAssertPointer(S, 2); 9653 *S = F->schur; 9654 } 9655 if (status) { 9656 PetscAssertPointer(status, 3); 9657 *status = F->schur_status; 9658 } 9659 PetscFunctionReturn(PETSC_SUCCESS); 9660 } 9661 9662 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F) 9663 { 9664 Mat S = F->schur; 9665 9666 PetscFunctionBegin; 9667 switch (F->schur_status) { 9668 case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through 9669 case MAT_FACTOR_SCHUR_INVERTED: 9670 if (S) { 9671 S->ops->solve = NULL; 9672 S->ops->matsolve = NULL; 9673 S->ops->solvetranspose = NULL; 9674 S->ops->matsolvetranspose = NULL; 9675 S->ops->solveadd = NULL; 9676 S->ops->solvetransposeadd = NULL; 9677 S->factortype = MAT_FACTOR_NONE; 9678 PetscCall(PetscFree(S->solvertype)); 9679 } 9680 case MAT_FACTOR_SCHUR_FACTORED: // fall-through 9681 break; 9682 default: 9683 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9684 } 9685 PetscFunctionReturn(PETSC_SUCCESS); 9686 } 9687 9688 /*@ 9689 MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()` 9690 9691 Logically Collective 9692 9693 Input Parameters: 9694 + F - the factored matrix obtained by calling `MatGetFactor()` 9695 . S - location where the Schur complement is stored 9696 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`) 9697 9698 Level: advanced 9699 9700 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9701 @*/ 9702 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status) 9703 { 9704 PetscFunctionBegin; 9705 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9706 if (S) { 9707 PetscValidHeaderSpecific(*S, MAT_CLASSID, 2); 9708 *S = NULL; 9709 } 9710 F->schur_status = status; 9711 PetscCall(MatFactorUpdateSchurStatus_Private(F)); 9712 PetscFunctionReturn(PETSC_SUCCESS); 9713 } 9714 9715 /*@ 9716 MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step 9717 9718 Logically Collective 9719 9720 Input Parameters: 9721 + F - the factored matrix obtained by calling `MatGetFactor()` 9722 . rhs - location where the right hand side of the Schur complement system is stored 9723 - sol - location where the solution of the Schur complement system has to be returned 9724 9725 Level: advanced 9726 9727 Notes: 9728 The sizes of the vectors should match the size of the Schur complement 9729 9730 Must be called after `MatFactorSetSchurIS()` 9731 9732 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()` 9733 @*/ 9734 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol) 9735 { 9736 PetscFunctionBegin; 9737 PetscValidType(F, 1); 9738 PetscValidType(rhs, 2); 9739 PetscValidType(sol, 3); 9740 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9741 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9742 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9743 PetscCheckSameComm(F, 1, rhs, 2); 9744 PetscCheckSameComm(F, 1, sol, 3); 9745 PetscCall(MatFactorFactorizeSchurComplement(F)); 9746 switch (F->schur_status) { 9747 case MAT_FACTOR_SCHUR_FACTORED: 9748 PetscCall(MatSolveTranspose(F->schur, rhs, sol)); 9749 break; 9750 case MAT_FACTOR_SCHUR_INVERTED: 9751 PetscCall(MatMultTranspose(F->schur, rhs, sol)); 9752 break; 9753 default: 9754 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9755 } 9756 PetscFunctionReturn(PETSC_SUCCESS); 9757 } 9758 9759 /*@ 9760 MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step 9761 9762 Logically Collective 9763 9764 Input Parameters: 9765 + F - the factored matrix obtained by calling `MatGetFactor()` 9766 . rhs - location where the right hand side of the Schur complement system is stored 9767 - sol - location where the solution of the Schur complement system has to be returned 9768 9769 Level: advanced 9770 9771 Notes: 9772 The sizes of the vectors should match the size of the Schur complement 9773 9774 Must be called after `MatFactorSetSchurIS()` 9775 9776 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()` 9777 @*/ 9778 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol) 9779 { 9780 PetscFunctionBegin; 9781 PetscValidType(F, 1); 9782 PetscValidType(rhs, 2); 9783 PetscValidType(sol, 3); 9784 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9785 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9786 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9787 PetscCheckSameComm(F, 1, rhs, 2); 9788 PetscCheckSameComm(F, 1, sol, 3); 9789 PetscCall(MatFactorFactorizeSchurComplement(F)); 9790 switch (F->schur_status) { 9791 case MAT_FACTOR_SCHUR_FACTORED: 9792 PetscCall(MatSolve(F->schur, rhs, sol)); 9793 break; 9794 case MAT_FACTOR_SCHUR_INVERTED: 9795 PetscCall(MatMult(F->schur, rhs, sol)); 9796 break; 9797 default: 9798 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9799 } 9800 PetscFunctionReturn(PETSC_SUCCESS); 9801 } 9802 9803 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat); 9804 #if PetscDefined(HAVE_CUDA) 9805 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat); 9806 #endif 9807 9808 /* Schur status updated in the interface */ 9809 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F) 9810 { 9811 Mat S = F->schur; 9812 9813 PetscFunctionBegin; 9814 if (S) { 9815 PetscMPIInt size; 9816 PetscBool isdense, isdensecuda; 9817 9818 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size)); 9819 PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented"); 9820 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense)); 9821 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda)); 9822 PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name); 9823 PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0)); 9824 if (isdense) { 9825 PetscCall(MatSeqDenseInvertFactors_Private(S)); 9826 } else if (isdensecuda) { 9827 #if defined(PETSC_HAVE_CUDA) 9828 PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S)); 9829 #endif 9830 } 9831 // HIP?????????????? 9832 PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0)); 9833 } 9834 PetscFunctionReturn(PETSC_SUCCESS); 9835 } 9836 9837 /*@ 9838 MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step 9839 9840 Logically Collective 9841 9842 Input Parameter: 9843 . F - the factored matrix obtained by calling `MatGetFactor()` 9844 9845 Level: advanced 9846 9847 Notes: 9848 Must be called after `MatFactorSetSchurIS()`. 9849 9850 Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it. 9851 9852 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()` 9853 @*/ 9854 PetscErrorCode MatFactorInvertSchurComplement(Mat F) 9855 { 9856 PetscFunctionBegin; 9857 PetscValidType(F, 1); 9858 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9859 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS); 9860 PetscCall(MatFactorFactorizeSchurComplement(F)); 9861 PetscCall(MatFactorInvertSchurComplement_Private(F)); 9862 F->schur_status = MAT_FACTOR_SCHUR_INVERTED; 9863 PetscFunctionReturn(PETSC_SUCCESS); 9864 } 9865 9866 /*@ 9867 MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step 9868 9869 Logically Collective 9870 9871 Input Parameter: 9872 . F - the factored matrix obtained by calling `MatGetFactor()` 9873 9874 Level: advanced 9875 9876 Note: 9877 Must be called after `MatFactorSetSchurIS()` 9878 9879 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()` 9880 @*/ 9881 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F) 9882 { 9883 MatFactorInfo info; 9884 9885 PetscFunctionBegin; 9886 PetscValidType(F, 1); 9887 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9888 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS); 9889 PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0)); 9890 PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo))); 9891 if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */ 9892 PetscCall(MatCholeskyFactor(F->schur, NULL, &info)); 9893 } else { 9894 PetscCall(MatLUFactor(F->schur, NULL, NULL, &info)); 9895 } 9896 PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0)); 9897 F->schur_status = MAT_FACTOR_SCHUR_FACTORED; 9898 PetscFunctionReturn(PETSC_SUCCESS); 9899 } 9900 9901 /*@ 9902 MatPtAP - Creates the matrix product C = P^T * A * P 9903 9904 Neighbor-wise Collective 9905 9906 Input Parameters: 9907 + A - the matrix 9908 . P - the projection matrix 9909 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9910 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate 9911 if the result is a dense matrix this is irrelevant 9912 9913 Output Parameter: 9914 . C - the product matrix 9915 9916 Level: intermediate 9917 9918 Notes: 9919 C will be created and must be destroyed by the user with `MatDestroy()`. 9920 9921 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9922 9923 Developer Notes: 9924 For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`. 9925 9926 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()` 9927 @*/ 9928 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C) 9929 { 9930 PetscFunctionBegin; 9931 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 9932 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9933 9934 if (scall == MAT_INITIAL_MATRIX) { 9935 PetscCall(MatProductCreate(A, P, NULL, C)); 9936 PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP)); 9937 PetscCall(MatProductSetAlgorithm(*C, "default")); 9938 PetscCall(MatProductSetFill(*C, fill)); 9939 9940 (*C)->product->api_user = PETSC_TRUE; 9941 PetscCall(MatProductSetFromOptions(*C)); 9942 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); 9943 PetscCall(MatProductSymbolic(*C)); 9944 } else { /* scall == MAT_REUSE_MATRIX */ 9945 PetscCall(MatProductReplaceMats(A, P, NULL, *C)); 9946 } 9947 9948 PetscCall(MatProductNumeric(*C)); 9949 (*C)->symmetric = A->symmetric; 9950 (*C)->spd = A->spd; 9951 PetscFunctionReturn(PETSC_SUCCESS); 9952 } 9953 9954 /*@ 9955 MatRARt - Creates the matrix product C = R * A * R^T 9956 9957 Neighbor-wise Collective 9958 9959 Input Parameters: 9960 + A - the matrix 9961 . R - the projection matrix 9962 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9963 - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate 9964 if the result is a dense matrix this is irrelevant 9965 9966 Output Parameter: 9967 . C - the product matrix 9968 9969 Level: intermediate 9970 9971 Notes: 9972 C will be created and must be destroyed by the user with `MatDestroy()`. 9973 9974 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9975 9976 This routine is currently only implemented for pairs of `MATAIJ` matrices and classes 9977 which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes, 9978 parallel MatRARt is implemented via explicit transpose of R, which could be very expensive. 9979 We recommend using MatPtAP(). 9980 9981 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()` 9982 @*/ 9983 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C) 9984 { 9985 PetscFunctionBegin; 9986 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 9987 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9988 9989 if (scall == MAT_INITIAL_MATRIX) { 9990 PetscCall(MatProductCreate(A, R, NULL, C)); 9991 PetscCall(MatProductSetType(*C, MATPRODUCT_RARt)); 9992 PetscCall(MatProductSetAlgorithm(*C, "default")); 9993 PetscCall(MatProductSetFill(*C, fill)); 9994 9995 (*C)->product->api_user = PETSC_TRUE; 9996 PetscCall(MatProductSetFromOptions(*C)); 9997 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); 9998 PetscCall(MatProductSymbolic(*C)); 9999 } else { /* scall == MAT_REUSE_MATRIX */ 10000 PetscCall(MatProductReplaceMats(A, R, NULL, *C)); 10001 } 10002 10003 PetscCall(MatProductNumeric(*C)); 10004 if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10005 PetscFunctionReturn(PETSC_SUCCESS); 10006 } 10007 10008 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C) 10009 { 10010 PetscFunctionBegin; 10011 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10012 10013 if (scall == MAT_INITIAL_MATRIX) { 10014 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype])); 10015 PetscCall(MatProductCreate(A, B, NULL, C)); 10016 PetscCall(MatProductSetType(*C, ptype)); 10017 PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT)); 10018 PetscCall(MatProductSetFill(*C, fill)); 10019 10020 (*C)->product->api_user = PETSC_TRUE; 10021 PetscCall(MatProductSetFromOptions(*C)); 10022 PetscCall(MatProductSymbolic(*C)); 10023 } else { /* scall == MAT_REUSE_MATRIX */ 10024 Mat_Product *product = (*C)->product; 10025 PetscBool isdense; 10026 10027 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, "")); 10028 if (isdense && product && product->type != ptype) { 10029 PetscCall(MatProductClear(*C)); 10030 product = NULL; 10031 } 10032 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype])); 10033 if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */ 10034 PetscCheck(isdense, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first"); 10035 PetscCall(MatProductCreate_Private(A, B, NULL, *C)); 10036 product = (*C)->product; 10037 product->fill = fill; 10038 product->api_user = PETSC_TRUE; 10039 product->clear = PETSC_TRUE; 10040 10041 PetscCall(MatProductSetType(*C, ptype)); 10042 PetscCall(MatProductSetFromOptions(*C)); 10043 PetscCheck((*C)->ops->productsymbolic, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "MatProduct %s not supported for %s and %s", MatProductTypes[ptype], ((PetscObject)A)->type_name, ((PetscObject)B)->type_name); 10044 PetscCall(MatProductSymbolic(*C)); 10045 } else { /* user may change input matrices A or B when REUSE */ 10046 PetscCall(MatProductReplaceMats(A, B, NULL, *C)); 10047 } 10048 } 10049 PetscCall(MatProductNumeric(*C)); 10050 PetscFunctionReturn(PETSC_SUCCESS); 10051 } 10052 10053 /*@ 10054 MatMatMult - Performs matrix-matrix multiplication C=A*B. 10055 10056 Neighbor-wise Collective 10057 10058 Input Parameters: 10059 + A - the left matrix 10060 . B - the right matrix 10061 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10062 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate 10063 if the result is a dense matrix this is irrelevant 10064 10065 Output Parameter: 10066 . C - the product matrix 10067 10068 Notes: 10069 Unless scall is `MAT_REUSE_MATRIX` C will be created. 10070 10071 `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 10072 call to this function with `MAT_INITIAL_MATRIX`. 10073 10074 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed. 10075 10076 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`, 10077 rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse. 10078 10079 Example of Usage: 10080 .vb 10081 MatProductCreate(A,B,NULL,&C); 10082 MatProductSetType(C,MATPRODUCT_AB); 10083 MatProductSymbolic(C); 10084 MatProductNumeric(C); // compute C=A * B 10085 MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1 10086 MatProductNumeric(C); 10087 MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1 10088 MatProductNumeric(C); 10089 .ve 10090 10091 Level: intermediate 10092 10093 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()` 10094 @*/ 10095 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10096 { 10097 PetscFunctionBegin; 10098 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C)); 10099 PetscFunctionReturn(PETSC_SUCCESS); 10100 } 10101 10102 /*@ 10103 MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T. 10104 10105 Neighbor-wise Collective 10106 10107 Input Parameters: 10108 + A - the left matrix 10109 . B - the right matrix 10110 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10111 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 10112 10113 Output Parameter: 10114 . C - the product matrix 10115 10116 Level: intermediate 10117 10118 Notes: 10119 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10120 10121 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call 10122 10123 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10124 actually needed. 10125 10126 This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class, 10127 and for pairs of `MATMPIDENSE` matrices. 10128 10129 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt` 10130 10131 Options Database Keys: 10132 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the 10133 first redundantly copies the transposed B matrix on each process and requires O(log P) communication complexity; 10134 the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity. 10135 10136 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType` 10137 @*/ 10138 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10139 { 10140 PetscFunctionBegin; 10141 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C)); 10142 if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10143 PetscFunctionReturn(PETSC_SUCCESS); 10144 } 10145 10146 /*@ 10147 MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B. 10148 10149 Neighbor-wise Collective 10150 10151 Input Parameters: 10152 + A - the left matrix 10153 . B - the right matrix 10154 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10155 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 10156 10157 Output Parameter: 10158 . C - the product matrix 10159 10160 Level: intermediate 10161 10162 Notes: 10163 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10164 10165 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call. 10166 10167 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB` 10168 10169 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10170 actually needed. 10171 10172 This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes 10173 which inherit from `MATSEQAIJ`. C will be of the same type as the input matrices. 10174 10175 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()` 10176 @*/ 10177 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10178 { 10179 PetscFunctionBegin; 10180 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C)); 10181 PetscFunctionReturn(PETSC_SUCCESS); 10182 } 10183 10184 /*@ 10185 MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C. 10186 10187 Neighbor-wise Collective 10188 10189 Input Parameters: 10190 + A - the left matrix 10191 . B - the middle matrix 10192 . C - the right matrix 10193 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10194 - fill - expected fill as ratio of nnz(D)/(nnz(A) + nnz(B)+nnz(C)), use `PETSC_DEFAULT` if you do not have a good estimate 10195 if the result is a dense matrix this is irrelevant 10196 10197 Output Parameter: 10198 . D - the product matrix 10199 10200 Level: intermediate 10201 10202 Notes: 10203 Unless scall is `MAT_REUSE_MATRIX` D will be created. 10204 10205 `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call 10206 10207 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC` 10208 10209 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10210 actually needed. 10211 10212 If you have many matrices with the same non-zero structure to multiply, you 10213 should use `MAT_REUSE_MATRIX` in all calls but the first 10214 10215 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()` 10216 @*/ 10217 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D) 10218 { 10219 PetscFunctionBegin; 10220 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6); 10221 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10222 10223 if (scall == MAT_INITIAL_MATRIX) { 10224 PetscCall(MatProductCreate(A, B, C, D)); 10225 PetscCall(MatProductSetType(*D, MATPRODUCT_ABC)); 10226 PetscCall(MatProductSetAlgorithm(*D, "default")); 10227 PetscCall(MatProductSetFill(*D, fill)); 10228 10229 (*D)->product->api_user = PETSC_TRUE; 10230 PetscCall(MatProductSetFromOptions(*D)); 10231 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, 10232 ((PetscObject)C)->type_name); 10233 PetscCall(MatProductSymbolic(*D)); 10234 } else { /* user may change input matrices when REUSE */ 10235 PetscCall(MatProductReplaceMats(A, B, C, *D)); 10236 } 10237 PetscCall(MatProductNumeric(*D)); 10238 PetscFunctionReturn(PETSC_SUCCESS); 10239 } 10240 10241 /*@ 10242 MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators. 10243 10244 Collective 10245 10246 Input Parameters: 10247 + mat - the matrix 10248 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices) 10249 . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used) 10250 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10251 10252 Output Parameter: 10253 . matredundant - redundant matrix 10254 10255 Level: advanced 10256 10257 Notes: 10258 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 10259 original matrix has not changed from that last call to MatCreateRedundantMatrix(). 10260 10261 This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before 10262 calling it. 10263 10264 `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be. 10265 10266 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm` 10267 @*/ 10268 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant) 10269 { 10270 MPI_Comm comm; 10271 PetscMPIInt size; 10272 PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs; 10273 Mat_Redundant *redund = NULL; 10274 PetscSubcomm psubcomm = NULL; 10275 MPI_Comm subcomm_in = subcomm; 10276 Mat *matseq; 10277 IS isrow, iscol; 10278 PetscBool newsubcomm = PETSC_FALSE; 10279 10280 PetscFunctionBegin; 10281 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10282 if (nsubcomm && reuse == MAT_REUSE_MATRIX) { 10283 PetscAssertPointer(*matredundant, 5); 10284 PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5); 10285 } 10286 10287 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10288 if (size == 1 || nsubcomm == 1) { 10289 if (reuse == MAT_INITIAL_MATRIX) { 10290 PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant)); 10291 } else { 10292 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"); 10293 PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN)); 10294 } 10295 PetscFunctionReturn(PETSC_SUCCESS); 10296 } 10297 10298 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10299 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10300 MatCheckPreallocated(mat, 1); 10301 10302 PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0)); 10303 if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */ 10304 /* create psubcomm, then get subcomm */ 10305 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10306 PetscCallMPI(MPI_Comm_size(comm, &size)); 10307 PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size); 10308 10309 PetscCall(PetscSubcommCreate(comm, &psubcomm)); 10310 PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm)); 10311 PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS)); 10312 PetscCall(PetscSubcommSetFromOptions(psubcomm)); 10313 PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL)); 10314 newsubcomm = PETSC_TRUE; 10315 PetscCall(PetscSubcommDestroy(&psubcomm)); 10316 } 10317 10318 /* get isrow, iscol and a local sequential matrix matseq[0] */ 10319 if (reuse == MAT_INITIAL_MATRIX) { 10320 mloc_sub = PETSC_DECIDE; 10321 nloc_sub = PETSC_DECIDE; 10322 if (bs < 1) { 10323 PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M)); 10324 PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N)); 10325 } else { 10326 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M)); 10327 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N)); 10328 } 10329 PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm)); 10330 rstart = rend - mloc_sub; 10331 PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow)); 10332 PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol)); 10333 PetscCall(ISSetIdentity(iscol)); 10334 } else { /* reuse == MAT_REUSE_MATRIX */ 10335 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"); 10336 /* retrieve subcomm */ 10337 PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm)); 10338 redund = (*matredundant)->redundant; 10339 isrow = redund->isrow; 10340 iscol = redund->iscol; 10341 matseq = redund->matseq; 10342 } 10343 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq)); 10344 10345 /* get matredundant over subcomm */ 10346 if (reuse == MAT_INITIAL_MATRIX) { 10347 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant)); 10348 10349 /* create a supporting struct and attach it to C for reuse */ 10350 PetscCall(PetscNew(&redund)); 10351 (*matredundant)->redundant = redund; 10352 redund->isrow = isrow; 10353 redund->iscol = iscol; 10354 redund->matseq = matseq; 10355 if (newsubcomm) { 10356 redund->subcomm = subcomm; 10357 } else { 10358 redund->subcomm = MPI_COMM_NULL; 10359 } 10360 } else { 10361 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant)); 10362 } 10363 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 10364 if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) { 10365 PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE)); 10366 PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE)); 10367 } 10368 #endif 10369 PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0)); 10370 PetscFunctionReturn(PETSC_SUCCESS); 10371 } 10372 10373 /*@C 10374 MatGetMultiProcBlock - Create multiple 'parallel submatrices' from 10375 a given `Mat`. Each submatrix can span multiple procs. 10376 10377 Collective 10378 10379 Input Parameters: 10380 + mat - the matrix 10381 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))` 10382 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10383 10384 Output Parameter: 10385 . subMat - parallel sub-matrices each spanning a given `subcomm` 10386 10387 Level: advanced 10388 10389 Notes: 10390 The submatrix partition across processors is dictated by `subComm` a 10391 communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm` 10392 is not restricted to be grouped with consecutive original ranks. 10393 10394 Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices 10395 map directly to the layout of the original matrix [wrt the local 10396 row,col partitioning]. So the original 'DiagonalMat' naturally maps 10397 into the 'DiagonalMat' of the `subMat`, hence it is used directly from 10398 the `subMat`. However the offDiagMat looses some columns - and this is 10399 reconstructed with `MatSetValues()` 10400 10401 This is used by `PCBJACOBI` when a single block spans multiple MPI processes. 10402 10403 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI` 10404 @*/ 10405 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) 10406 { 10407 PetscMPIInt commsize, subCommSize; 10408 10409 PetscFunctionBegin; 10410 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize)); 10411 PetscCallMPI(MPI_Comm_size(subComm, &subCommSize)); 10412 PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize); 10413 10414 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"); 10415 PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10416 PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat); 10417 PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10418 PetscFunctionReturn(PETSC_SUCCESS); 10419 } 10420 10421 /*@ 10422 MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering 10423 10424 Not Collective 10425 10426 Input Parameters: 10427 + mat - matrix to extract local submatrix from 10428 . isrow - local row indices for submatrix 10429 - iscol - local column indices for submatrix 10430 10431 Output Parameter: 10432 . submat - the submatrix 10433 10434 Level: intermediate 10435 10436 Notes: 10437 `submat` should be disposed of with `MatRestoreLocalSubMatrix()`. 10438 10439 Depending on the format of `mat`, the returned submat may not implement `MatMult()`. Its communicator may be 10440 the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of `mat`'s. 10441 10442 `submat` always implements `MatSetValuesLocal()`. If `isrow` and `iscol` have the same block size, then 10443 `MatSetValuesBlockedLocal()` will also be implemented. 10444 10445 `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`. 10446 Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided. 10447 10448 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()` 10449 @*/ 10450 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10451 { 10452 PetscFunctionBegin; 10453 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10454 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10455 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10456 PetscCheckSameComm(isrow, 2, iscol, 3); 10457 PetscAssertPointer(submat, 4); 10458 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call"); 10459 10460 if (mat->ops->getlocalsubmatrix) { 10461 PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat); 10462 } else { 10463 PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat)); 10464 } 10465 PetscFunctionReturn(PETSC_SUCCESS); 10466 } 10467 10468 /*@ 10469 MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()` 10470 10471 Not Collective 10472 10473 Input Parameters: 10474 + mat - matrix to extract local submatrix from 10475 . isrow - local row indices for submatrix 10476 . iscol - local column indices for submatrix 10477 - submat - the submatrix 10478 10479 Level: intermediate 10480 10481 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()` 10482 @*/ 10483 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10484 { 10485 PetscFunctionBegin; 10486 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10487 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10488 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10489 PetscCheckSameComm(isrow, 2, iscol, 3); 10490 PetscAssertPointer(submat, 4); 10491 if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4); 10492 10493 if (mat->ops->restorelocalsubmatrix) { 10494 PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat); 10495 } else { 10496 PetscCall(MatDestroy(submat)); 10497 } 10498 *submat = NULL; 10499 PetscFunctionReturn(PETSC_SUCCESS); 10500 } 10501 10502 /*@ 10503 MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix 10504 10505 Collective 10506 10507 Input Parameter: 10508 . mat - the matrix 10509 10510 Output Parameter: 10511 . is - if any rows have zero diagonals this contains the list of them 10512 10513 Level: developer 10514 10515 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10516 @*/ 10517 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is) 10518 { 10519 PetscFunctionBegin; 10520 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10521 PetscValidType(mat, 1); 10522 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10523 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10524 10525 if (!mat->ops->findzerodiagonals) { 10526 Vec diag; 10527 const PetscScalar *a; 10528 PetscInt *rows; 10529 PetscInt rStart, rEnd, r, nrow = 0; 10530 10531 PetscCall(MatCreateVecs(mat, &diag, NULL)); 10532 PetscCall(MatGetDiagonal(mat, diag)); 10533 PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd)); 10534 PetscCall(VecGetArrayRead(diag, &a)); 10535 for (r = 0; r < rEnd - rStart; ++r) 10536 if (a[r] == 0.0) ++nrow; 10537 PetscCall(PetscMalloc1(nrow, &rows)); 10538 nrow = 0; 10539 for (r = 0; r < rEnd - rStart; ++r) 10540 if (a[r] == 0.0) rows[nrow++] = r + rStart; 10541 PetscCall(VecRestoreArrayRead(diag, &a)); 10542 PetscCall(VecDestroy(&diag)); 10543 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is)); 10544 } else { 10545 PetscUseTypeMethod(mat, findzerodiagonals, is); 10546 } 10547 PetscFunctionReturn(PETSC_SUCCESS); 10548 } 10549 10550 /*@ 10551 MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size) 10552 10553 Collective 10554 10555 Input Parameter: 10556 . mat - the matrix 10557 10558 Output Parameter: 10559 . is - contains the list of rows with off block diagonal entries 10560 10561 Level: developer 10562 10563 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10564 @*/ 10565 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is) 10566 { 10567 PetscFunctionBegin; 10568 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10569 PetscValidType(mat, 1); 10570 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10571 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10572 10573 PetscUseTypeMethod(mat, findoffblockdiagonalentries, is); 10574 PetscFunctionReturn(PETSC_SUCCESS); 10575 } 10576 10577 /*@C 10578 MatInvertBlockDiagonal - Inverts the block diagonal entries. 10579 10580 Collective; No Fortran Support 10581 10582 Input Parameter: 10583 . mat - the matrix 10584 10585 Output Parameter: 10586 . values - the block inverses in column major order (FORTRAN-like) 10587 10588 Level: advanced 10589 10590 Notes: 10591 The size of the blocks is determined by the block size of the matrix. 10592 10593 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10594 10595 The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size 10596 10597 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()` 10598 @*/ 10599 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values) 10600 { 10601 PetscFunctionBegin; 10602 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10603 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10604 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10605 PetscUseTypeMethod(mat, invertblockdiagonal, values); 10606 PetscFunctionReturn(PETSC_SUCCESS); 10607 } 10608 10609 /*@C 10610 MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries. 10611 10612 Collective; No Fortran Support 10613 10614 Input Parameters: 10615 + mat - the matrix 10616 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()` 10617 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()` 10618 10619 Output Parameter: 10620 . values - the block inverses in column major order (FORTRAN-like) 10621 10622 Level: advanced 10623 10624 Notes: 10625 Use `MatInvertBlockDiagonal()` if all blocks have the same size 10626 10627 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10628 10629 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()` 10630 @*/ 10631 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values) 10632 { 10633 PetscFunctionBegin; 10634 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10635 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10636 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10637 PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values); 10638 PetscFunctionReturn(PETSC_SUCCESS); 10639 } 10640 10641 /*@ 10642 MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A 10643 10644 Collective 10645 10646 Input Parameters: 10647 + A - the matrix 10648 - C - matrix with inverted block diagonal of `A`. This matrix should be created and may have its type set. 10649 10650 Level: advanced 10651 10652 Note: 10653 The blocksize of the matrix is used to determine the blocks on the diagonal of `C` 10654 10655 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()` 10656 @*/ 10657 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C) 10658 { 10659 const PetscScalar *vals; 10660 PetscInt *dnnz; 10661 PetscInt m, rstart, rend, bs, i, j; 10662 10663 PetscFunctionBegin; 10664 PetscCall(MatInvertBlockDiagonal(A, &vals)); 10665 PetscCall(MatGetBlockSize(A, &bs)); 10666 PetscCall(MatGetLocalSize(A, &m, NULL)); 10667 PetscCall(MatSetLayouts(C, A->rmap, A->cmap)); 10668 PetscCall(PetscMalloc1(m / bs, &dnnz)); 10669 for (j = 0; j < m / bs; j++) dnnz[j] = 1; 10670 PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL)); 10671 PetscCall(PetscFree(dnnz)); 10672 PetscCall(MatGetOwnershipRange(C, &rstart, &rend)); 10673 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE)); 10674 for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES)); 10675 PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 10676 PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 10677 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE)); 10678 PetscFunctionReturn(PETSC_SUCCESS); 10679 } 10680 10681 /*@C 10682 MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created 10683 via `MatTransposeColoringCreate()`. 10684 10685 Collective 10686 10687 Input Parameter: 10688 . c - coloring context 10689 10690 Level: intermediate 10691 10692 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()` 10693 @*/ 10694 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c) 10695 { 10696 MatTransposeColoring matcolor = *c; 10697 10698 PetscFunctionBegin; 10699 if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS); 10700 if (--((PetscObject)matcolor)->refct > 0) { 10701 matcolor = NULL; 10702 PetscFunctionReturn(PETSC_SUCCESS); 10703 } 10704 10705 PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow)); 10706 PetscCall(PetscFree(matcolor->rows)); 10707 PetscCall(PetscFree(matcolor->den2sp)); 10708 PetscCall(PetscFree(matcolor->colorforcol)); 10709 PetscCall(PetscFree(matcolor->columns)); 10710 if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart)); 10711 PetscCall(PetscHeaderDestroy(c)); 10712 PetscFunctionReturn(PETSC_SUCCESS); 10713 } 10714 10715 /*@C 10716 MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which 10717 a `MatTransposeColoring` context has been created, computes a dense B^T by applying 10718 `MatTransposeColoring` to sparse B. 10719 10720 Collective 10721 10722 Input Parameters: 10723 + coloring - coloring context created with `MatTransposeColoringCreate()` 10724 - B - sparse matrix 10725 10726 Output Parameter: 10727 . Btdense - dense matrix B^T 10728 10729 Level: developer 10730 10731 Note: 10732 These are used internally for some implementations of `MatRARt()` 10733 10734 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()` 10735 @*/ 10736 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense) 10737 { 10738 PetscFunctionBegin; 10739 PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10740 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 10741 PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3); 10742 10743 PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense)); 10744 PetscFunctionReturn(PETSC_SUCCESS); 10745 } 10746 10747 /*@C 10748 MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which 10749 a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense 10750 in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix 10751 `Csp` from `Cden`. 10752 10753 Collective 10754 10755 Input Parameters: 10756 + matcoloring - coloring context created with `MatTransposeColoringCreate()` 10757 - Cden - matrix product of a sparse matrix and a dense matrix Btdense 10758 10759 Output Parameter: 10760 . Csp - sparse matrix 10761 10762 Level: developer 10763 10764 Note: 10765 These are used internally for some implementations of `MatRARt()` 10766 10767 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()` 10768 @*/ 10769 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp) 10770 { 10771 PetscFunctionBegin; 10772 PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10773 PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2); 10774 PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3); 10775 10776 PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp)); 10777 PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY)); 10778 PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY)); 10779 PetscFunctionReturn(PETSC_SUCCESS); 10780 } 10781 10782 /*@C 10783 MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T. 10784 10785 Collective 10786 10787 Input Parameters: 10788 + mat - the matrix product C 10789 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()` 10790 10791 Output Parameter: 10792 . color - the new coloring context 10793 10794 Level: intermediate 10795 10796 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`, 10797 `MatTransColoringApplyDenToSp()` 10798 @*/ 10799 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color) 10800 { 10801 MatTransposeColoring c; 10802 MPI_Comm comm; 10803 10804 PetscFunctionBegin; 10805 PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10806 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10807 PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL)); 10808 10809 c->ctype = iscoloring->ctype; 10810 PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c); 10811 10812 *color = c; 10813 PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10814 PetscFunctionReturn(PETSC_SUCCESS); 10815 } 10816 10817 /*@ 10818 MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the 10819 matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the 10820 same, otherwise it will be larger 10821 10822 Not Collective 10823 10824 Input Parameter: 10825 . mat - the matrix 10826 10827 Output Parameter: 10828 . state - the current state 10829 10830 Level: intermediate 10831 10832 Notes: 10833 You can only compare states from two different calls to the SAME matrix, you cannot compare calls between 10834 different matrices 10835 10836 Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix 10837 10838 Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers. 10839 10840 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()` 10841 @*/ 10842 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state) 10843 { 10844 PetscFunctionBegin; 10845 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10846 *state = mat->nonzerostate; 10847 PetscFunctionReturn(PETSC_SUCCESS); 10848 } 10849 10850 /*@ 10851 MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential 10852 matrices from each processor 10853 10854 Collective 10855 10856 Input Parameters: 10857 + comm - the communicators the parallel matrix will live on 10858 . seqmat - the input sequential matrices 10859 . n - number of local columns (or `PETSC_DECIDE`) 10860 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10861 10862 Output Parameter: 10863 . mpimat - the parallel matrix generated 10864 10865 Level: developer 10866 10867 Note: 10868 The number of columns of the matrix in EACH processor MUST be the same. 10869 10870 .seealso: [](ch_matrices), `Mat` 10871 @*/ 10872 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat) 10873 { 10874 PetscMPIInt size; 10875 10876 PetscFunctionBegin; 10877 PetscCallMPI(MPI_Comm_size(comm, &size)); 10878 if (size == 1) { 10879 if (reuse == MAT_INITIAL_MATRIX) { 10880 PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat)); 10881 } else { 10882 PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN)); 10883 } 10884 PetscFunctionReturn(PETSC_SUCCESS); 10885 } 10886 10887 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"); 10888 10889 PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0)); 10890 PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat)); 10891 PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0)); 10892 PetscFunctionReturn(PETSC_SUCCESS); 10893 } 10894 10895 /*@ 10896 MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI ranks' ownership ranges. 10897 10898 Collective 10899 10900 Input Parameters: 10901 + A - the matrix to create subdomains from 10902 - N - requested number of subdomains 10903 10904 Output Parameters: 10905 + n - number of subdomains resulting on this MPI process 10906 - iss - `IS` list with indices of subdomains on this MPI process 10907 10908 Level: advanced 10909 10910 Note: 10911 The number of subdomains must be smaller than the communicator size 10912 10913 .seealso: [](ch_matrices), `Mat`, `IS` 10914 @*/ 10915 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[]) 10916 { 10917 MPI_Comm comm, subcomm; 10918 PetscMPIInt size, rank, color; 10919 PetscInt rstart, rend, k; 10920 10921 PetscFunctionBegin; 10922 PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 10923 PetscCallMPI(MPI_Comm_size(comm, &size)); 10924 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 10925 PetscCheck(N >= 1 && N < (PetscInt)size, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "number of subdomains must be > 0 and < %d, got N = %" PetscInt_FMT, size, N); 10926 *n = 1; 10927 k = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */ 10928 color = rank / k; 10929 PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm)); 10930 PetscCall(PetscMalloc1(1, iss)); 10931 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 10932 PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0])); 10933 PetscCallMPI(MPI_Comm_free(&subcomm)); 10934 PetscFunctionReturn(PETSC_SUCCESS); 10935 } 10936 10937 /*@ 10938 MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection. 10939 10940 If the interpolation and restriction operators are the same, uses `MatPtAP()`. 10941 If they are not the same, uses `MatMatMatMult()`. 10942 10943 Once the coarse grid problem is constructed, correct for interpolation operators 10944 that are not of full rank, which can legitimately happen in the case of non-nested 10945 geometric multigrid. 10946 10947 Input Parameters: 10948 + restrct - restriction operator 10949 . dA - fine grid matrix 10950 . interpolate - interpolation operator 10951 . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10952 - fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate 10953 10954 Output Parameter: 10955 . A - the Galerkin coarse matrix 10956 10957 Options Database Key: 10958 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used 10959 10960 Level: developer 10961 10962 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()` 10963 @*/ 10964 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A) 10965 { 10966 IS zerorows; 10967 Vec diag; 10968 10969 PetscFunctionBegin; 10970 PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10971 /* Construct the coarse grid matrix */ 10972 if (interpolate == restrct) { 10973 PetscCall(MatPtAP(dA, interpolate, reuse, fill, A)); 10974 } else { 10975 PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A)); 10976 } 10977 10978 /* If the interpolation matrix is not of full rank, A will have zero rows. 10979 This can legitimately happen in the case of non-nested geometric multigrid. 10980 In that event, we set the rows of the matrix to the rows of the identity, 10981 ignoring the equations (as the RHS will also be zero). */ 10982 10983 PetscCall(MatFindZeroRows(*A, &zerorows)); 10984 10985 if (zerorows != NULL) { /* if there are any zero rows */ 10986 PetscCall(MatCreateVecs(*A, &diag, NULL)); 10987 PetscCall(MatGetDiagonal(*A, diag)); 10988 PetscCall(VecISSet(diag, zerorows, 1.0)); 10989 PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES)); 10990 PetscCall(VecDestroy(&diag)); 10991 PetscCall(ISDestroy(&zerorows)); 10992 } 10993 PetscFunctionReturn(PETSC_SUCCESS); 10994 } 10995 10996 /*@C 10997 MatSetOperation - Allows user to set a matrix operation for any matrix type 10998 10999 Logically Collective 11000 11001 Input Parameters: 11002 + mat - the matrix 11003 . op - the name of the operation 11004 - f - the function that provides the operation 11005 11006 Level: developer 11007 11008 Example Usage: 11009 .vb 11010 extern PetscErrorCode usermult(Mat, Vec, Vec); 11011 11012 PetscCall(MatCreateXXX(comm, ..., &A)); 11013 PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFunction)usermult)); 11014 .ve 11015 11016 Notes: 11017 See the file `include/petscmat.h` for a complete list of matrix 11018 operations, which all have the form MATOP_<OPERATION>, where 11019 <OPERATION> is the name (in all capital letters) of the 11020 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11021 11022 All user-provided functions (except for `MATOP_DESTROY`) should have the same calling 11023 sequence as the usual matrix interface routines, since they 11024 are intended to be accessed via the usual matrix interface 11025 routines, e.g., 11026 .vb 11027 MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec) 11028 .ve 11029 11030 In particular each function MUST return `PETSC_SUCCESS` on success and 11031 nonzero on failure. 11032 11033 This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type. 11034 11035 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()` 11036 @*/ 11037 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void)) 11038 { 11039 PetscFunctionBegin; 11040 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11041 if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view; 11042 (((void (**)(void))mat->ops)[op]) = f; 11043 PetscFunctionReturn(PETSC_SUCCESS); 11044 } 11045 11046 /*@C 11047 MatGetOperation - Gets a matrix operation for any matrix type. 11048 11049 Not Collective 11050 11051 Input Parameters: 11052 + mat - the matrix 11053 - op - the name of the operation 11054 11055 Output Parameter: 11056 . f - the function that provides the operation 11057 11058 Level: developer 11059 11060 Example Usage: 11061 .vb 11062 PetscErrorCode (*usermult)(Mat, Vec, Vec); 11063 11064 MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult); 11065 .ve 11066 11067 Notes: 11068 See the file include/petscmat.h for a complete list of matrix 11069 operations, which all have the form MATOP_<OPERATION>, where 11070 <OPERATION> is the name (in all capital letters) of the 11071 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11072 11073 This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type. 11074 11075 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()` 11076 @*/ 11077 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void)) 11078 { 11079 PetscFunctionBegin; 11080 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11081 *f = (((void (**)(void))mat->ops)[op]); 11082 PetscFunctionReturn(PETSC_SUCCESS); 11083 } 11084 11085 /*@ 11086 MatHasOperation - Determines whether the given matrix supports the particular operation. 11087 11088 Not Collective 11089 11090 Input Parameters: 11091 + mat - the matrix 11092 - op - the operation, for example, `MATOP_GET_DIAGONAL` 11093 11094 Output Parameter: 11095 . has - either `PETSC_TRUE` or `PETSC_FALSE` 11096 11097 Level: advanced 11098 11099 Note: 11100 See `MatSetOperation()` for additional discussion on naming convention and usage of `op`. 11101 11102 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()` 11103 @*/ 11104 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has) 11105 { 11106 PetscFunctionBegin; 11107 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11108 PetscAssertPointer(has, 3); 11109 if (mat->ops->hasoperation) { 11110 PetscUseTypeMethod(mat, hasoperation, op, has); 11111 } else { 11112 if (((void **)mat->ops)[op]) *has = PETSC_TRUE; 11113 else { 11114 *has = PETSC_FALSE; 11115 if (op == MATOP_CREATE_SUBMATRIX) { 11116 PetscMPIInt size; 11117 11118 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 11119 if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has)); 11120 } 11121 } 11122 } 11123 PetscFunctionReturn(PETSC_SUCCESS); 11124 } 11125 11126 /*@ 11127 MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent 11128 11129 Collective 11130 11131 Input Parameter: 11132 . mat - the matrix 11133 11134 Output Parameter: 11135 . cong - either `PETSC_TRUE` or `PETSC_FALSE` 11136 11137 Level: beginner 11138 11139 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout` 11140 @*/ 11141 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong) 11142 { 11143 PetscFunctionBegin; 11144 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11145 PetscValidType(mat, 1); 11146 PetscAssertPointer(cong, 2); 11147 if (!mat->rmap || !mat->cmap) { 11148 *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE; 11149 PetscFunctionReturn(PETSC_SUCCESS); 11150 } 11151 if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */ 11152 PetscCall(PetscLayoutSetUp(mat->rmap)); 11153 PetscCall(PetscLayoutSetUp(mat->cmap)); 11154 PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong)); 11155 if (*cong) mat->congruentlayouts = 1; 11156 else mat->congruentlayouts = 0; 11157 } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE; 11158 PetscFunctionReturn(PETSC_SUCCESS); 11159 } 11160 11161 PetscErrorCode MatSetInf(Mat A) 11162 { 11163 PetscFunctionBegin; 11164 PetscUseTypeMethod(A, setinf); 11165 PetscFunctionReturn(PETSC_SUCCESS); 11166 } 11167 11168 /*@C 11169 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 11170 and possibly removes small values from the graph structure. 11171 11172 Collective 11173 11174 Input Parameters: 11175 + A - the matrix 11176 . sym - `PETSC_TRUE` indicates that the graph should be symmetrized 11177 . scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry 11178 . filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value 11179 . num_idx - size of 'index' array 11180 - index - array of block indices to use for graph strength of connection weight 11181 11182 Output Parameter: 11183 . graph - the resulting graph 11184 11185 Level: advanced 11186 11187 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG` 11188 @*/ 11189 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, PetscInt num_idx, PetscInt index[], Mat *graph) 11190 { 11191 PetscFunctionBegin; 11192 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11193 PetscValidType(A, 1); 11194 PetscValidLogicalCollectiveBool(A, scale, 3); 11195 PetscAssertPointer(graph, 7); 11196 PetscUseTypeMethod(A, creategraph, sym, scale, filter, num_idx, index, graph); 11197 PetscFunctionReturn(PETSC_SUCCESS); 11198 } 11199 11200 /*@ 11201 MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place, 11202 meaning the same memory is used for the matrix, and no new memory is allocated. 11203 11204 Collective 11205 11206 Input Parameters: 11207 + A - the matrix 11208 - 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 11209 11210 Level: intermediate 11211 11212 Developer Notes: 11213 The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end 11214 of the arrays in the data structure are unneeded. 11215 11216 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatFilter()` 11217 @*/ 11218 PetscErrorCode MatEliminateZeros(Mat A, PetscBool keep) 11219 { 11220 PetscFunctionBegin; 11221 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11222 PetscUseTypeMethod(A, eliminatezeros, keep); 11223 PetscFunctionReturn(PETSC_SUCCESS); 11224 } 11225