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()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, 129 `MAT_FACTOR_NUMERIC_ZEROPIVOT` 130 @*/ 131 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row) 132 { 133 PetscFunctionBegin; 134 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 135 PetscValidRealPointer(pivot, 2); 136 PetscValidIntPointer(row, 3); 137 *pivot = mat->factorerror_zeropivot_value; 138 *row = mat->factorerror_zeropivot_row; 139 PetscFunctionReturn(PETSC_SUCCESS); 140 } 141 142 /*@ 143 MatFactorGetError - gets the error code from a factorization 144 145 Logically Collective 146 147 Input Parameter: 148 . mat - the factored matrix 149 150 Output Parameter: 151 . err - the error code 152 153 Level: advanced 154 155 Note: 156 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 157 158 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, 159 `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, `MatFactorError` 160 @*/ 161 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err) 162 { 163 PetscFunctionBegin; 164 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 165 PetscValidPointer(err, 2); 166 *err = mat->factorerrortype; 167 PetscFunctionReturn(PETSC_SUCCESS); 168 } 169 170 /*@ 171 MatFactorClearError - clears the error code in a factorization 172 173 Logically Collective 174 175 Input Parameter: 176 . mat - the factored matrix 177 178 Level: developer 179 180 Note: 181 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 182 183 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`, 184 `MatGetErrorCode()`, `MatFactorError` 185 @*/ 186 PetscErrorCode MatFactorClearError(Mat mat) 187 { 188 PetscFunctionBegin; 189 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 190 mat->factorerrortype = MAT_FACTOR_NOERROR; 191 mat->factorerror_zeropivot_value = 0.0; 192 mat->factorerror_zeropivot_row = 0; 193 PetscFunctionReturn(PETSC_SUCCESS); 194 } 195 196 PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero) 197 { 198 Vec r, l; 199 const PetscScalar *al; 200 PetscInt i, nz, gnz, N, n; 201 202 PetscFunctionBegin; 203 PetscCall(MatCreateVecs(mat, &r, &l)); 204 if (!cols) { /* nonzero rows */ 205 PetscCall(MatGetSize(mat, &N, NULL)); 206 PetscCall(MatGetLocalSize(mat, &n, NULL)); 207 PetscCall(VecSet(l, 0.0)); 208 PetscCall(VecSetRandom(r, NULL)); 209 PetscCall(MatMult(mat, r, l)); 210 PetscCall(VecGetArrayRead(l, &al)); 211 } else { /* nonzero columns */ 212 PetscCall(MatGetSize(mat, NULL, &N)); 213 PetscCall(MatGetLocalSize(mat, NULL, &n)); 214 PetscCall(VecSet(r, 0.0)); 215 PetscCall(VecSetRandom(l, NULL)); 216 PetscCall(MatMultTranspose(mat, l, r)); 217 PetscCall(VecGetArrayRead(r, &al)); 218 } 219 if (tol <= 0.0) { 220 for (i = 0, nz = 0; i < n; i++) 221 if (al[i] != 0.0) nz++; 222 } else { 223 for (i = 0, nz = 0; i < n; i++) 224 if (PetscAbsScalar(al[i]) > tol) nz++; 225 } 226 PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 227 if (gnz != N) { 228 PetscInt *nzr; 229 PetscCall(PetscMalloc1(nz, &nzr)); 230 if (nz) { 231 if (tol < 0) { 232 for (i = 0, nz = 0; i < n; i++) 233 if (al[i] != 0.0) nzr[nz++] = i; 234 } else { 235 for (i = 0, nz = 0; i < n; i++) 236 if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i; 237 } 238 } 239 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero)); 240 } else *nonzero = NULL; 241 if (!cols) { /* nonzero rows */ 242 PetscCall(VecRestoreArrayRead(l, &al)); 243 } else { 244 PetscCall(VecRestoreArrayRead(r, &al)); 245 } 246 PetscCall(VecDestroy(&l)); 247 PetscCall(VecDestroy(&r)); 248 PetscFunctionReturn(PETSC_SUCCESS); 249 } 250 251 /*@ 252 MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix 253 254 Input Parameter: 255 . mat - the matrix 256 257 Output Parameter: 258 . keptrows - the rows that are not completely zero 259 260 Level: intermediate 261 262 Note: 263 `keptrows` is set to `NULL` if all rows are nonzero. 264 265 .seealso: [](ch_matrices), `Mat`, `MatFindZeroRows()` 266 @*/ 267 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows) 268 { 269 PetscFunctionBegin; 270 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 271 PetscValidType(mat, 1); 272 PetscValidPointer(keptrows, 2); 273 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 274 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 275 if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows); 276 else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows)); 277 PetscFunctionReturn(PETSC_SUCCESS); 278 } 279 280 /*@ 281 MatFindZeroRows - Locate all rows that are completely zero in the matrix 282 283 Input Parameter: 284 . mat - the matrix 285 286 Output Parameter: 287 . zerorows - the rows that are completely zero 288 289 Level: intermediate 290 291 Note: 292 `zerorows` is set to `NULL` if no rows are zero. 293 294 .seealso: [](ch_matrices), `Mat`, `MatFindNonzeroRows()` 295 @*/ 296 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows) 297 { 298 IS keptrows; 299 PetscInt m, n; 300 301 PetscFunctionBegin; 302 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 303 PetscValidType(mat, 1); 304 PetscValidPointer(zerorows, 2); 305 PetscCall(MatFindNonzeroRows(mat, &keptrows)); 306 /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows. 307 In keeping with this convention, we set zerorows to NULL if there are no zero 308 rows. */ 309 if (keptrows == NULL) { 310 *zerorows = NULL; 311 } else { 312 PetscCall(MatGetOwnershipRange(mat, &m, &n)); 313 PetscCall(ISComplement(keptrows, m, n, zerorows)); 314 PetscCall(ISDestroy(&keptrows)); 315 } 316 PetscFunctionReturn(PETSC_SUCCESS); 317 } 318 319 /*@ 320 MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling 321 322 Not Collective 323 324 Input Parameter: 325 . A - the matrix 326 327 Output Parameter: 328 . a - the diagonal part (which is a SEQUENTIAL matrix) 329 330 Level: advanced 331 332 Notes: 333 See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix. 334 335 Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation. 336 337 .seealso: [](ch_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ` 338 @*/ 339 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a) 340 { 341 PetscFunctionBegin; 342 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 343 PetscValidType(A, 1); 344 PetscValidPointer(a, 2); 345 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 346 if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a); 347 else { 348 PetscMPIInt size; 349 350 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 351 PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name); 352 *a = A; 353 } 354 PetscFunctionReturn(PETSC_SUCCESS); 355 } 356 357 /*@ 358 MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries. 359 360 Collective 361 362 Input Parameter: 363 . mat - the matrix 364 365 Output Parameter: 366 . trace - the sum of the diagonal entries 367 368 Level: advanced 369 370 .seealso: [](ch_matrices), `Mat` 371 @*/ 372 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace) 373 { 374 Vec diag; 375 376 PetscFunctionBegin; 377 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 378 PetscValidScalarPointer(trace, 2); 379 PetscCall(MatCreateVecs(mat, &diag, NULL)); 380 PetscCall(MatGetDiagonal(mat, diag)); 381 PetscCall(VecSum(diag, trace)); 382 PetscCall(VecDestroy(&diag)); 383 PetscFunctionReturn(PETSC_SUCCESS); 384 } 385 386 /*@ 387 MatRealPart - Zeros out the imaginary part of the matrix 388 389 Logically Collective 390 391 Input Parameter: 392 . mat - the matrix 393 394 Level: advanced 395 396 .seealso: [](ch_matrices), `Mat`, `MatImaginaryPart()` 397 @*/ 398 PetscErrorCode MatRealPart(Mat mat) 399 { 400 PetscFunctionBegin; 401 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 402 PetscValidType(mat, 1); 403 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 404 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 405 MatCheckPreallocated(mat, 1); 406 PetscUseTypeMethod(mat, realpart); 407 PetscFunctionReturn(PETSC_SUCCESS); 408 } 409 410 /*@C 411 MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix 412 413 Collective 414 415 Input Parameter: 416 . mat - the matrix 417 418 Output Parameters: 419 + nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each block) 420 - ghosts - the global indices of the ghost points 421 422 Level: advanced 423 424 Note: 425 `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()` 426 427 .seealso: [](ch_matrices), `Mat`, `VecCreateGhost()` 428 @*/ 429 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[]) 430 { 431 PetscFunctionBegin; 432 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 433 PetscValidType(mat, 1); 434 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 435 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 436 if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts); 437 else { 438 if (nghosts) *nghosts = 0; 439 if (ghosts) *ghosts = NULL; 440 } 441 PetscFunctionReturn(PETSC_SUCCESS); 442 } 443 444 /*@ 445 MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part 446 447 Logically Collective 448 449 Input Parameter: 450 . mat - the matrix 451 452 Level: advanced 453 454 .seealso: [](ch_matrices), `Mat`, `MatRealPart()` 455 @*/ 456 PetscErrorCode MatImaginaryPart(Mat mat) 457 { 458 PetscFunctionBegin; 459 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 460 PetscValidType(mat, 1); 461 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 462 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 463 MatCheckPreallocated(mat, 1); 464 PetscUseTypeMethod(mat, imaginarypart); 465 PetscFunctionReturn(PETSC_SUCCESS); 466 } 467 468 /*@ 469 MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices) 470 471 Not Collective 472 473 Input Parameter: 474 . mat - the matrix 475 476 Output Parameters: 477 + missing - is any diagonal missing 478 - dd - first diagonal entry that is missing (optional) on this process 479 480 Level: advanced 481 482 .seealso: [](ch_matrices), `Mat` 483 @*/ 484 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd) 485 { 486 PetscFunctionBegin; 487 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 488 PetscValidType(mat, 1); 489 PetscValidBoolPointer(missing, 2); 490 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name); 491 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 492 PetscUseTypeMethod(mat, missingdiagonal, missing, dd); 493 PetscFunctionReturn(PETSC_SUCCESS); 494 } 495 496 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 497 /*@C 498 MatGetRow - Gets a row of a matrix. You MUST call `MatRestoreRow()` 499 for each row that you get to ensure that your application does 500 not bleed memory. 501 502 Not Collective 503 504 Input Parameters: 505 + mat - the matrix 506 - row - the row to get 507 508 Output Parameters: 509 + ncols - if not `NULL`, the number of nonzeros in the row 510 . cols - if not `NULL`, the column numbers 511 - vals - if not `NULL`, the values 512 513 Level: advanced 514 515 Notes: 516 This routine is provided for people who need to have direct access 517 to the structure of a matrix. We hope that we provide enough 518 high-level matrix routines that few users will need it. 519 520 `MatGetRow()` always returns 0-based column indices, regardless of 521 whether the internal representation is 0-based (default) or 1-based. 522 523 For better efficiency, set cols and/or vals to `NULL` if you do 524 not wish to extract these quantities. 525 526 The user can only examine the values extracted with `MatGetRow()`; 527 the values cannot be altered. To change the matrix entries, one 528 must use `MatSetValues()`. 529 530 You can only have one call to `MatGetRow()` outstanding for a particular 531 matrix at a time, per processor. `MatGetRow()` can only obtain rows 532 associated with the given processor, it cannot get rows from the 533 other processors; for that we suggest using `MatCreateSubMatrices()`, then 534 MatGetRow() on the submatrix. The row index passed to `MatGetRow()` 535 is in the global number of rows. 536 537 Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix. 538 539 Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly. 540 541 Fortran Notes: 542 The calling sequence is 543 .vb 544 MatGetRow(matrix,row,ncols,cols,values,ierr) 545 Mat matrix (input) 546 integer row (input) 547 integer ncols (output) 548 integer cols(maxcols) (output) 549 double precision (or double complex) values(maxcols) output 550 .ve 551 where maxcols >= maximum nonzeros in any row of the matrix. 552 553 Caution: 554 Do not try to change the contents of the output arrays (`cols` and `vals`). 555 In some cases, this may corrupt the matrix. 556 557 .seealso: [](ch_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()` 558 @*/ 559 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 560 { 561 PetscInt incols; 562 563 PetscFunctionBegin; 564 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 565 PetscValidType(mat, 1); 566 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 567 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 568 MatCheckPreallocated(mat, 1); 569 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); 570 PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0)); 571 PetscUseTypeMethod(mat, getrow, row, &incols, (PetscInt **)cols, (PetscScalar **)vals); 572 if (ncols) *ncols = incols; 573 PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0)); 574 PetscFunctionReturn(PETSC_SUCCESS); 575 } 576 577 /*@ 578 MatConjugate - replaces the matrix values with their complex conjugates 579 580 Logically Collective 581 582 Input Parameter: 583 . mat - the matrix 584 585 Level: advanced 586 587 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()` 588 @*/ 589 PetscErrorCode MatConjugate(Mat mat) 590 { 591 PetscFunctionBegin; 592 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 593 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 594 if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) { 595 PetscUseTypeMethod(mat, conjugate); 596 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 597 } 598 PetscFunctionReturn(PETSC_SUCCESS); 599 } 600 601 /*@C 602 MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`. 603 604 Not Collective 605 606 Input Parameters: 607 + mat - the matrix 608 . row - the row to get 609 . ncols - the number of nonzeros 610 . cols - the columns of the nonzeros 611 - vals - if nonzero the column values 612 613 Level: advanced 614 615 Notes: 616 This routine should be called after you have finished examining the entries. 617 618 This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental 619 us of the array after it has been restored. If you pass `NULL`, it will 620 not zero the pointers. Use of `cols` or `vals` after `MatRestoreRow()` is invalid. 621 622 Fortran Notes: 623 The calling sequence is 624 .vb 625 MatRestoreRow(matrix,row,ncols,cols,values,ierr) 626 Mat matrix (input) 627 integer row (input) 628 integer ncols (output) 629 integer cols(maxcols) (output) 630 double precision (or double complex) values(maxcols) output 631 .ve 632 Where maxcols >= maximum nonzeros in any row of the matrix. 633 634 In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()` 635 before another call to `MatGetRow()` can be made. 636 637 .seealso: [](ch_matrices), `Mat`, `MatGetRow()` 638 @*/ 639 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 640 { 641 PetscFunctionBegin; 642 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 643 if (ncols) PetscValidIntPointer(ncols, 3); 644 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 645 if (!mat->ops->restorerow) PetscFunctionReturn(PETSC_SUCCESS); 646 PetscUseTypeMethod(mat, restorerow, row, ncols, (PetscInt **)cols, (PetscScalar **)vals); 647 if (ncols) *ncols = 0; 648 if (cols) *cols = NULL; 649 if (vals) *vals = NULL; 650 PetscFunctionReturn(PETSC_SUCCESS); 651 } 652 653 /*@ 654 MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 655 You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag. 656 657 Not Collective 658 659 Input Parameter: 660 . mat - the matrix 661 662 Level: advanced 663 664 Note: 665 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. 666 667 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()` 668 @*/ 669 PetscErrorCode MatGetRowUpperTriangular(Mat mat) 670 { 671 PetscFunctionBegin; 672 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 673 PetscValidType(mat, 1); 674 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 675 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 676 MatCheckPreallocated(mat, 1); 677 if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS); 678 PetscUseTypeMethod(mat, getrowuppertriangular); 679 PetscFunctionReturn(PETSC_SUCCESS); 680 } 681 682 /*@ 683 MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 684 685 Not Collective 686 687 Input Parameter: 688 . mat - the matrix 689 690 Level: advanced 691 692 Note: 693 This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`. 694 695 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()` 696 @*/ 697 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat) 698 { 699 PetscFunctionBegin; 700 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 701 PetscValidType(mat, 1); 702 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 703 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 704 MatCheckPreallocated(mat, 1); 705 if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS); 706 PetscUseTypeMethod(mat, restorerowuppertriangular); 707 PetscFunctionReturn(PETSC_SUCCESS); 708 } 709 710 /*@C 711 MatSetOptionsPrefix - Sets the prefix used for searching for all 712 `Mat` options in the database. 713 714 Logically Collective 715 716 Input Parameters: 717 + A - the matrix 718 - prefix - the prefix to prepend to all option names 719 720 Level: advanced 721 722 Notes: 723 A hyphen (-) must NOT be given at the beginning of the prefix name. 724 The first character of all runtime options is AUTOMATICALLY the hyphen. 725 726 This is NOT used for options for the factorization of the matrix. Normally the 727 prefix is automatically passed in from the PC calling the factorization. To set 728 it directly use `MatSetOptionsPrefixFactor()` 729 730 .seealso: [](ch_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()` 731 @*/ 732 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[]) 733 { 734 PetscFunctionBegin; 735 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 736 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix)); 737 PetscFunctionReturn(PETSC_SUCCESS); 738 } 739 740 /*@C 741 MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for 742 for matrices created with `MatGetFactor()` 743 744 Logically Collective 745 746 Input Parameters: 747 + A - the matrix 748 - prefix - the prefix to prepend to all option names for the factored matrix 749 750 Level: developer 751 752 Notes: 753 A hyphen (-) must NOT be given at the beginning of the prefix name. 754 The first character of all runtime options is AUTOMATICALLY the hyphen. 755 756 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 757 it directly when not using `KSP`/`PC` use `MatSetOptionsPrefixFactor()` 758 759 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()` 760 @*/ 761 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[]) 762 { 763 PetscFunctionBegin; 764 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 765 if (prefix) { 766 PetscValidCharPointer(prefix, 2); 767 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 768 if (prefix != A->factorprefix) { 769 PetscCall(PetscFree(A->factorprefix)); 770 PetscCall(PetscStrallocpy(prefix, &A->factorprefix)); 771 } 772 } else PetscCall(PetscFree(A->factorprefix)); 773 PetscFunctionReturn(PETSC_SUCCESS); 774 } 775 776 /*@C 777 MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for 778 for matrices created with `MatGetFactor()` 779 780 Logically Collective 781 782 Input Parameters: 783 + A - the matrix 784 - prefix - the prefix to prepend to all option names for the factored matrix 785 786 Level: developer 787 788 Notes: 789 A hyphen (-) must NOT be given at the beginning of the prefix name. 790 The first character of all runtime options is AUTOMATICALLY the hyphen. 791 792 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 793 it directly when not using `KSP`/`PC` use `MatAppendOptionsPrefixFactor()` 794 795 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`, 796 `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`, 797 `MatSetOptionsPrefix()` 798 @*/ 799 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[]) 800 { 801 size_t len1, len2, new_len; 802 803 PetscFunctionBegin; 804 PetscValidHeader(A, 1); 805 if (!prefix) PetscFunctionReturn(PETSC_SUCCESS); 806 if (!A->factorprefix) { 807 PetscCall(MatSetOptionsPrefixFactor(A, prefix)); 808 PetscFunctionReturn(PETSC_SUCCESS); 809 } 810 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 811 812 PetscCall(PetscStrlen(A->factorprefix, &len1)); 813 PetscCall(PetscStrlen(prefix, &len2)); 814 new_len = len1 + len2 + 1; 815 PetscCall(PetscRealloc(new_len * sizeof(*(A->factorprefix)), &A->factorprefix)); 816 PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1)); 817 PetscFunctionReturn(PETSC_SUCCESS); 818 } 819 820 /*@C 821 MatAppendOptionsPrefix - Appends to the prefix used for searching for all 822 matrix options in the database. 823 824 Logically Collective 825 826 Input Parameters: 827 + A - the matrix 828 - prefix - the prefix to prepend to all option names 829 830 Level: advanced 831 832 Note: 833 A hyphen (-) must NOT be given at the beginning of the prefix name. 834 The first character of all runtime options is AUTOMATICALLY the hyphen. 835 836 .seealso: [](ch_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()` 837 @*/ 838 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[]) 839 { 840 PetscFunctionBegin; 841 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 842 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix)); 843 PetscFunctionReturn(PETSC_SUCCESS); 844 } 845 846 /*@C 847 MatGetOptionsPrefix - Gets the prefix used for searching for all 848 matrix options in the database. 849 850 Not Collective 851 852 Input Parameter: 853 . A - the matrix 854 855 Output Parameter: 856 . prefix - pointer to the prefix string used 857 858 Level: advanced 859 860 Fortran Notes: 861 The user should pass in a string `prefix` of 862 sufficient length to hold the prefix. 863 864 .seealso: [](ch_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()` 865 @*/ 866 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[]) 867 { 868 PetscFunctionBegin; 869 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 870 PetscValidPointer(prefix, 2); 871 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix)); 872 PetscFunctionReturn(PETSC_SUCCESS); 873 } 874 875 /*@ 876 MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by users. 877 878 Collective 879 880 Input Parameter: 881 . A - the matrix 882 883 Level: beginner 884 885 Notes: 886 The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`. 887 888 Users can reset the preallocation to access the original memory. 889 890 Currently only supported for `MATAIJ` matrices. 891 892 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()` 893 @*/ 894 PetscErrorCode MatResetPreallocation(Mat A) 895 { 896 PetscFunctionBegin; 897 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 898 PetscValidType(A, 1); 899 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()"); 900 if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS); 901 PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A)); 902 PetscFunctionReturn(PETSC_SUCCESS); 903 } 904 905 /*@ 906 MatSetUp - Sets up the internal matrix data structures for later use. 907 908 Collective 909 910 Input Parameter: 911 . A - the matrix 912 913 Level: intermediate 914 915 Notes: 916 If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of 917 setting values in the matrix. 918 919 If a suitable preallocation routine is used, this function does not need to be called. 920 921 This routine is called internally by other matrix functions when needed so rarely needs to be called by users 922 923 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()` 924 @*/ 925 PetscErrorCode MatSetUp(Mat A) 926 { 927 PetscFunctionBegin; 928 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 929 if (!((PetscObject)A)->type_name) { 930 PetscMPIInt size; 931 932 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 933 PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ)); 934 } 935 if (!A->preallocated) PetscTryTypeMethod(A, setup); 936 PetscCall(PetscLayoutSetUp(A->rmap)); 937 PetscCall(PetscLayoutSetUp(A->cmap)); 938 A->preallocated = PETSC_TRUE; 939 PetscFunctionReturn(PETSC_SUCCESS); 940 } 941 942 #if defined(PETSC_HAVE_SAWS) 943 #include <petscviewersaws.h> 944 #endif 945 946 /* 947 If threadsafety is on extraneous matrices may be printed 948 949 This flag cannot be stored in the matrix because the original matrix in MatView() may assemble a new matrix which is passed into MatViewFromOptions() 950 */ 951 #if !defined(PETSC_HAVE_THREADSAFETY) 952 static PetscInt insidematview = 0; 953 #endif 954 955 /*@C 956 MatViewFromOptions - View properties of the matrix based on options set in the options database 957 958 Collective 959 960 Input Parameters: 961 + A - the matrix 962 . obj - optional additional object that provides the options prefix to use 963 - name - command line option 964 965 Options Database Key: 966 . -mat_view [viewertype]:... - the viewer and its options 967 968 Level: intermediate 969 970 Notes: 971 .vb 972 If no value is provided ascii:stdout is used 973 ascii[:[filename][:[format][:append]]] defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab, 974 for example ascii::ascii_info prints just the information about the object not all details 975 unless :append is given filename opens in write mode, overwriting what was already there 976 binary[:[filename][:[format][:append]]] defaults to the file binaryoutput 977 draw[:drawtype[:filename]] for example, draw:tikz, draw:tikz:figure.tex or draw:x 978 socket[:port] defaults to the standard output port 979 saws[:communicatorname] publishes object to the Scientific Application Webserver (SAWs) 980 .ve 981 982 .seealso: [](ch_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()` 983 @*/ 984 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[]) 985 { 986 PetscFunctionBegin; 987 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 988 #if !defined(PETSC_HAVE_THREADSAFETY) 989 if (insidematview) PetscFunctionReturn(PETSC_SUCCESS); 990 #endif 991 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 992 PetscFunctionReturn(PETSC_SUCCESS); 993 } 994 995 /*@C 996 MatView - display information about a matrix in a variety ways 997 998 Collective 999 1000 Input Parameters: 1001 + mat - the matrix 1002 - viewer - visualization context 1003 1004 Options Database Keys: 1005 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 1006 . -mat_view ::ascii_info_detail - Prints more detailed info 1007 . -mat_view - Prints matrix in ASCII format 1008 . -mat_view ::ascii_matlab - Prints matrix in Matlab format 1009 . -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 1010 . -display <name> - Sets display name (default is host) 1011 . -draw_pause <sec> - Sets number of seconds to pause after display 1012 . -mat_view socket - Sends matrix to socket, can be accessed from Matlab (see Users-Manual: ch_matlab for details) 1013 . -viewer_socket_machine <machine> - - 1014 . -viewer_socket_port <port> - - 1015 . -mat_view binary - save matrix to file in binary format 1016 - -viewer_binary_filename <name> - - 1017 1018 Level: beginner 1019 1020 Notes: 1021 The available visualization contexts include 1022 + `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices 1023 . `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD` 1024 . `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm 1025 - `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure 1026 1027 The user can open alternative visualization contexts with 1028 + `PetscViewerASCIIOpen()` - Outputs matrix to a specified file 1029 . `PetscViewerBinaryOpen()` - Outputs matrix in binary to a 1030 specified file; corresponding input uses `MatLoad()` 1031 . `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to 1032 an X window display 1033 - `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer. 1034 Currently only the `MATSEQDENSE` and `MATAIJ` 1035 matrix types support the Socket viewer. 1036 1037 The user can call `PetscViewerPushFormat()` to specify the output 1038 format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`, 1039 `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`). Available formats include 1040 + `PETSC_VIEWER_DEFAULT` - default, prints matrix contents 1041 . `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in Matlab format 1042 . `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros 1043 . `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse 1044 format common among all matrix types 1045 . `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific 1046 format (which is in many cases the same as the default) 1047 . `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix 1048 size and structure (not the matrix entries) 1049 - `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about 1050 the matrix structure 1051 1052 The ASCII viewers are only recommended for small matrices on at most a moderate number of processes, 1053 the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format. 1054 1055 In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer). 1056 1057 See the manual page for `MatLoad()` for the exact format of the binary file when the binary 1058 viewer is used. 1059 1060 See share/petsc/matlab/PetscBinaryRead.m for a Matlab code that can read in the binary file when the binary 1061 viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python. 1062 1063 One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure, 1064 and then use the following mouse functions. 1065 .vb 1066 left mouse: zoom in 1067 middle mouse: zoom out 1068 right mouse: continue with the simulation 1069 .ve 1070 1071 .seealso: [](ch_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`, 1072 `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()` 1073 @*/ 1074 PetscErrorCode MatView(Mat mat, PetscViewer viewer) 1075 { 1076 PetscInt rows, cols, rbs, cbs; 1077 PetscBool isascii, isstring, issaws; 1078 PetscViewerFormat format; 1079 PetscMPIInt size; 1080 1081 PetscFunctionBegin; 1082 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1083 PetscValidType(mat, 1); 1084 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer)); 1085 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1086 PetscCheckSameComm(mat, 1, viewer, 2); 1087 1088 PetscCall(PetscViewerGetFormat(viewer, &format)); 1089 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 1090 if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS); 1091 1092 #if !defined(PETSC_HAVE_THREADSAFETY) 1093 insidematview++; 1094 #endif 1095 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 1096 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 1097 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws)); 1098 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"); 1099 1100 PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0)); 1101 if (isascii) { 1102 if (!mat->preallocated) { 1103 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n")); 1104 #if !defined(PETSC_HAVE_THREADSAFETY) 1105 insidematview--; 1106 #endif 1107 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1108 PetscFunctionReturn(PETSC_SUCCESS); 1109 } 1110 if (!mat->assembled) { 1111 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n")); 1112 #if !defined(PETSC_HAVE_THREADSAFETY) 1113 insidematview--; 1114 #endif 1115 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1116 PetscFunctionReturn(PETSC_SUCCESS); 1117 } 1118 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer)); 1119 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1120 MatNullSpace nullsp, transnullsp; 1121 1122 PetscCall(PetscViewerASCIIPushTab(viewer)); 1123 PetscCall(MatGetSize(mat, &rows, &cols)); 1124 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1125 if (rbs != 1 || cbs != 1) { 1126 if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs)); 1127 else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs)); 1128 } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols)); 1129 if (mat->factortype) { 1130 MatSolverType solver; 1131 PetscCall(MatFactorGetSolverType(mat, &solver)); 1132 PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver)); 1133 } 1134 if (mat->ops->getinfo) { 1135 MatInfo info; 1136 PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info)); 1137 PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated)); 1138 if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs)); 1139 } 1140 PetscCall(MatGetNullSpace(mat, &nullsp)); 1141 PetscCall(MatGetTransposeNullSpace(mat, &transnullsp)); 1142 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached null space\n")); 1143 if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached transposed null space\n")); 1144 PetscCall(MatGetNearNullSpace(mat, &nullsp)); 1145 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached near null space\n")); 1146 PetscCall(PetscViewerASCIIPushTab(viewer)); 1147 PetscCall(MatProductView(mat, viewer)); 1148 PetscCall(PetscViewerASCIIPopTab(viewer)); 1149 } 1150 } else if (issaws) { 1151 #if defined(PETSC_HAVE_SAWS) 1152 PetscMPIInt rank; 1153 1154 PetscCall(PetscObjectName((PetscObject)mat)); 1155 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 1156 if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer)); 1157 #endif 1158 } else if (isstring) { 1159 const char *type; 1160 PetscCall(MatGetType(mat, &type)); 1161 PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type)); 1162 PetscTryTypeMethod(mat, view, viewer); 1163 } 1164 if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) { 1165 PetscCall(PetscViewerASCIIPushTab(viewer)); 1166 PetscUseTypeMethod(mat, viewnative, viewer); 1167 PetscCall(PetscViewerASCIIPopTab(viewer)); 1168 } else if (mat->ops->view) { 1169 PetscCall(PetscViewerASCIIPushTab(viewer)); 1170 PetscUseTypeMethod(mat, view, viewer); 1171 PetscCall(PetscViewerASCIIPopTab(viewer)); 1172 } 1173 if (isascii) { 1174 PetscCall(PetscViewerGetFormat(viewer, &format)); 1175 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer)); 1176 } 1177 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1178 #if !defined(PETSC_HAVE_THREADSAFETY) 1179 insidematview--; 1180 #endif 1181 PetscFunctionReturn(PETSC_SUCCESS); 1182 } 1183 1184 #if defined(PETSC_USE_DEBUG) 1185 #include <../src/sys/totalview/tv_data_display.h> 1186 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat) 1187 { 1188 TV_add_row("Local rows", "int", &mat->rmap->n); 1189 TV_add_row("Local columns", "int", &mat->cmap->n); 1190 TV_add_row("Global rows", "int", &mat->rmap->N); 1191 TV_add_row("Global columns", "int", &mat->cmap->N); 1192 TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name); 1193 return TV_format_OK; 1194 } 1195 #endif 1196 1197 /*@C 1198 MatLoad - Loads a matrix that has been stored in binary/HDF5 format 1199 with `MatView()`. The matrix format is determined from the options database. 1200 Generates a parallel MPI matrix if the communicator has more than one 1201 processor. The default matrix type is `MATAIJ`. 1202 1203 Collective 1204 1205 Input Parameters: 1206 + mat - the newly loaded matrix, this needs to have been created with `MatCreate()` 1207 or some related function before a call to `MatLoad()` 1208 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer 1209 1210 Options Database Keys: 1211 Used with block matrix formats (`MATSEQBAIJ`, ...) to specify 1212 block size 1213 . -matload_block_size <bs> - set block size 1214 1215 Level: beginner 1216 1217 Notes: 1218 If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the 1219 `Mat` before calling this routine if you wish to set it from the options database. 1220 1221 `MatLoad()` automatically loads into the options database any options 1222 given in the file filename.info where filename is the name of the file 1223 that was passed to the `PetscViewerBinaryOpen()`. The options in the info 1224 file will be ignored if you use the -viewer_binary_skip_info option. 1225 1226 If the type or size of mat is not set before a call to `MatLoad()`, PETSc 1227 sets the default matrix type AIJ and sets the local and global sizes. 1228 If type and/or size is already set, then the same are used. 1229 1230 In parallel, each processor can load a subset of rows (or the 1231 entire matrix). This routine is especially useful when a large 1232 matrix is stored on disk and only part of it is desired on each 1233 processor. For example, a parallel solver may access only some of 1234 the rows from each processor. The algorithm used here reads 1235 relatively small blocks of data rather than reading the entire 1236 matrix and then subsetting it. 1237 1238 Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`. 1239 Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`, 1240 or the sequence like 1241 .vb 1242 `PetscViewer` v; 1243 `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v); 1244 `PetscViewerSetType`(v,`PETSCVIEWERBINARY`); 1245 `PetscViewerSetFromOptions`(v); 1246 `PetscViewerFileSetMode`(v,`FILE_MODE_READ`); 1247 `PetscViewerFileSetName`(v,"datafile"); 1248 .ve 1249 The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option 1250 $ -viewer_type {binary, hdf5} 1251 1252 See the example src/ksp/ksp/tutorials/ex27.c with the first approach, 1253 and src/mat/tutorials/ex10.c with the second approach. 1254 1255 In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks 1256 is read onto MPI rank 0 and then shipped to its destination MPI rank, one after another. 1257 Multiple objects, both matrices and vectors, can be stored within the same file. 1258 Their `PetscObject` name is ignored; they are loaded in the order of their storage. 1259 1260 Most users should not need to know the details of the binary storage 1261 format, since `MatLoad()` and `MatView()` completely hide these details. 1262 But for anyone who is interested, the standard binary matrix storage 1263 format is 1264 1265 .vb 1266 PetscInt MAT_FILE_CLASSID 1267 PetscInt number of rows 1268 PetscInt number of columns 1269 PetscInt total number of nonzeros 1270 PetscInt *number nonzeros in each row 1271 PetscInt *column indices of all nonzeros (starting index is zero) 1272 PetscScalar *values of all nonzeros 1273 .ve 1274 If PETSc was not configured with `--with-64-bit-indices` then only `MATMPIAIJ` matrices with more than `PETSC_INT_MAX` non-zeros can be 1275 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 1276 case will not fit in a (32-bit) `PetscInt` the value `PETSC_INT_MAX` is used for the header entry `total number of nonzeros`. 1277 1278 PETSc automatically does the byte swapping for 1279 machines that store the bytes reversed. Thus if you write your own binary 1280 read/write routines you have to swap the bytes; see `PetscBinaryRead()` 1281 and `PetscBinaryWrite()` to see how this may be done. 1282 1283 In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used. 1284 Each processor's chunk is loaded independently by its owning MPI process. 1285 Multiple objects, both matrices and vectors, can be stored within the same file. 1286 They are looked up by their PetscObject name. 1287 1288 As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use 1289 by default the same structure and naming of the AIJ arrays and column count 1290 within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g. 1291 $ save example.mat A b -v7.3 1292 can be directly read by this routine (see Reference 1 for details). 1293 1294 Depending on your MATLAB version, this format might be a default, 1295 otherwise you can set it as default in Preferences. 1296 1297 Unless -nocompression flag is used to save the file in MATLAB, 1298 PETSc must be configured with ZLIB package. 1299 1300 See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c 1301 1302 This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5` 1303 1304 Corresponding `MatView()` is not yet implemented. 1305 1306 The loaded matrix is actually a transpose of the original one in MATLAB, 1307 unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above). 1308 With this format, matrix is automatically transposed by PETSc, 1309 unless the matrix is marked as SPD or symmetric 1310 (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`). 1311 1312 References: 1313 . * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version 1314 1315 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()` 1316 @*/ 1317 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer) 1318 { 1319 PetscBool flg; 1320 1321 PetscFunctionBegin; 1322 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1323 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1324 1325 if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ)); 1326 1327 flg = PETSC_FALSE; 1328 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL)); 1329 if (flg) { 1330 PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE)); 1331 PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE)); 1332 } 1333 flg = PETSC_FALSE; 1334 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL)); 1335 if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE)); 1336 1337 PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0)); 1338 PetscUseTypeMethod(mat, load, viewer); 1339 PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0)); 1340 PetscFunctionReturn(PETSC_SUCCESS); 1341 } 1342 1343 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant) 1344 { 1345 Mat_Redundant *redund = *redundant; 1346 1347 PetscFunctionBegin; 1348 if (redund) { 1349 if (redund->matseq) { /* via MatCreateSubMatrices() */ 1350 PetscCall(ISDestroy(&redund->isrow)); 1351 PetscCall(ISDestroy(&redund->iscol)); 1352 PetscCall(MatDestroySubMatrices(1, &redund->matseq)); 1353 } else { 1354 PetscCall(PetscFree2(redund->send_rank, redund->recv_rank)); 1355 PetscCall(PetscFree(redund->sbuf_j)); 1356 PetscCall(PetscFree(redund->sbuf_a)); 1357 for (PetscInt i = 0; i < redund->nrecvs; i++) { 1358 PetscCall(PetscFree(redund->rbuf_j[i])); 1359 PetscCall(PetscFree(redund->rbuf_a[i])); 1360 } 1361 PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a)); 1362 } 1363 1364 if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm)); 1365 PetscCall(PetscFree(redund)); 1366 } 1367 PetscFunctionReturn(PETSC_SUCCESS); 1368 } 1369 1370 /*@C 1371 MatDestroy - Frees space taken by a matrix. 1372 1373 Collective 1374 1375 Input Parameter: 1376 . A - the matrix 1377 1378 Level: beginner 1379 1380 Developer Notes: 1381 Some special arrays of matrices are not destroyed in this routine but instead by the routines called by 1382 `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines. 1383 `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes 1384 if changes are needed here. 1385 1386 .seealso: [](ch_matrices), `Mat`, `MatCreate()` 1387 @*/ 1388 PetscErrorCode MatDestroy(Mat *A) 1389 { 1390 PetscFunctionBegin; 1391 if (!*A) PetscFunctionReturn(PETSC_SUCCESS); 1392 PetscValidHeaderSpecific(*A, MAT_CLASSID, 1); 1393 if (--((PetscObject)(*A))->refct > 0) { 1394 *A = NULL; 1395 PetscFunctionReturn(PETSC_SUCCESS); 1396 } 1397 1398 /* if memory was published with SAWs then destroy it */ 1399 PetscCall(PetscObjectSAWsViewOff((PetscObject)*A)); 1400 PetscTryTypeMethod((*A), destroy); 1401 1402 PetscCall(PetscFree((*A)->factorprefix)); 1403 PetscCall(PetscFree((*A)->defaultvectype)); 1404 PetscCall(PetscFree((*A)->defaultrandtype)); 1405 PetscCall(PetscFree((*A)->bsizes)); 1406 PetscCall(PetscFree((*A)->solvertype)); 1407 for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i])); 1408 if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL; 1409 PetscCall(MatDestroy_Redundant(&(*A)->redundant)); 1410 PetscCall(MatProductClear(*A)); 1411 PetscCall(MatNullSpaceDestroy(&(*A)->nullsp)); 1412 PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp)); 1413 PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp)); 1414 PetscCall(MatDestroy(&(*A)->schur)); 1415 PetscCall(PetscLayoutDestroy(&(*A)->rmap)); 1416 PetscCall(PetscLayoutDestroy(&(*A)->cmap)); 1417 PetscCall(PetscHeaderDestroy(A)); 1418 PetscFunctionReturn(PETSC_SUCCESS); 1419 } 1420 1421 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1422 /*@C 1423 MatSetValues - Inserts or adds a block of values into a matrix. 1424 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1425 MUST be called after all calls to `MatSetValues()` have been completed. 1426 1427 Not Collective 1428 1429 Input Parameters: 1430 + mat - the matrix 1431 . v - a logically two-dimensional array of values 1432 . m - the number of rows 1433 . idxm - the global indices of the rows 1434 . n - the number of columns 1435 . idxn - the global indices of the columns 1436 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1437 1438 Level: beginner 1439 1440 Notes: 1441 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1442 1443 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1444 options cannot be mixed without intervening calls to the assembly 1445 routines. 1446 1447 `MatSetValues()` uses 0-based row and column numbers in Fortran 1448 as well as in C. 1449 1450 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1451 simply ignored. This allows easily inserting element stiffness matrices 1452 with homogeneous Dirichlet boundary conditions that you don't want represented 1453 in the matrix. 1454 1455 Efficiency Alert: 1456 The routine `MatSetValuesBlocked()` may offer much better efficiency 1457 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1458 1459 Developer Notes: 1460 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1461 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1462 1463 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1464 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1465 @*/ 1466 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1467 { 1468 PetscFunctionBeginHot; 1469 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1470 PetscValidType(mat, 1); 1471 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1472 PetscValidIntPointer(idxm, 3); 1473 PetscValidIntPointer(idxn, 5); 1474 MatCheckPreallocated(mat, 1); 1475 1476 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1477 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1478 1479 if (PetscDefined(USE_DEBUG)) { 1480 PetscInt i, j; 1481 1482 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1483 for (i = 0; i < m; i++) { 1484 for (j = 0; j < n; j++) { 1485 if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j])) 1486 #if defined(PETSC_USE_COMPLEX) 1487 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]); 1488 #else 1489 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]); 1490 #endif 1491 } 1492 } 1493 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); 1494 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); 1495 } 1496 1497 if (mat->assembled) { 1498 mat->was_assembled = PETSC_TRUE; 1499 mat->assembled = PETSC_FALSE; 1500 } 1501 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1502 PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv); 1503 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1504 PetscFunctionReturn(PETSC_SUCCESS); 1505 } 1506 1507 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1508 /*@C 1509 MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns 1510 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1511 MUST be called after all calls to `MatSetValues()` have been completed. 1512 1513 Not Collective 1514 1515 Input Parameters: 1516 + mat - the matrix 1517 . v - a logically two-dimensional array of values 1518 . ism - the rows to provide 1519 . isn - the columns to provide 1520 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1521 1522 Level: beginner 1523 1524 Notes: 1525 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1526 1527 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1528 options cannot be mixed without intervening calls to the assembly 1529 routines. 1530 1531 `MatSetValues()` uses 0-based row and column numbers in Fortran 1532 as well as in C. 1533 1534 Negative indices may be passed in `ism` and `isn`, these rows and columns are 1535 simply ignored. This allows easily inserting element stiffness matrices 1536 with homogeneous Dirichlet boundary conditions that you don't want represented 1537 in the matrix. 1538 1539 Efficiency Alert: 1540 The routine `MatSetValuesBlocked()` may offer much better efficiency 1541 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1542 1543 This is currently not optimized for any particular `ISType` 1544 1545 Developer Notes: 1546 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1547 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1548 1549 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1550 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1551 @*/ 1552 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv) 1553 { 1554 PetscInt m, n; 1555 const PetscInt *rows, *cols; 1556 1557 PetscFunctionBeginHot; 1558 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1559 PetscCall(ISGetIndices(ism, &rows)); 1560 PetscCall(ISGetIndices(isn, &cols)); 1561 PetscCall(ISGetLocalSize(ism, &m)); 1562 PetscCall(ISGetLocalSize(isn, &n)); 1563 PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv)); 1564 PetscCall(ISRestoreIndices(ism, &rows)); 1565 PetscCall(ISRestoreIndices(isn, &cols)); 1566 PetscFunctionReturn(PETSC_SUCCESS); 1567 } 1568 1569 /*@ 1570 MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1571 values into a matrix 1572 1573 Not Collective 1574 1575 Input Parameters: 1576 + mat - the matrix 1577 . row - the (block) row to set 1578 - v - a logically two-dimensional array of values 1579 1580 Level: intermediate 1581 1582 Notes: 1583 The values, `v`, are column-oriented (for the block version) and sorted 1584 1585 All the nonzeros in the row must be provided 1586 1587 The matrix must have previously had its column indices set, likely by having been assembled. 1588 1589 The row must belong to this process 1590 1591 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1592 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()` 1593 @*/ 1594 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[]) 1595 { 1596 PetscInt globalrow; 1597 1598 PetscFunctionBegin; 1599 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1600 PetscValidType(mat, 1); 1601 PetscValidScalarPointer(v, 3); 1602 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow)); 1603 PetscCall(MatSetValuesRow(mat, globalrow, v)); 1604 PetscFunctionReturn(PETSC_SUCCESS); 1605 } 1606 1607 /*@ 1608 MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1609 values into a matrix 1610 1611 Not Collective 1612 1613 Input Parameters: 1614 + mat - the matrix 1615 . row - the (block) row to set 1616 - 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 1617 1618 Level: advanced 1619 1620 Notes: 1621 The values, `v`, are column-oriented for the block version. 1622 1623 All the nonzeros in the row must be provided 1624 1625 THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used. 1626 1627 The row must belong to this process 1628 1629 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1630 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1631 @*/ 1632 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[]) 1633 { 1634 PetscFunctionBeginHot; 1635 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1636 PetscValidType(mat, 1); 1637 MatCheckPreallocated(mat, 1); 1638 PetscValidScalarPointer(v, 3); 1639 PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values"); 1640 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1641 mat->insertmode = INSERT_VALUES; 1642 1643 if (mat->assembled) { 1644 mat->was_assembled = PETSC_TRUE; 1645 mat->assembled = PETSC_FALSE; 1646 } 1647 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1648 PetscUseTypeMethod(mat, setvaluesrow, row, v); 1649 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1650 PetscFunctionReturn(PETSC_SUCCESS); 1651 } 1652 1653 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1654 /*@ 1655 MatSetValuesStencil - Inserts or adds a block of values into a matrix. 1656 Using structured grid indexing 1657 1658 Not Collective 1659 1660 Input Parameters: 1661 + mat - the matrix 1662 . m - number of rows being entered 1663 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered 1664 . n - number of columns being entered 1665 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered 1666 . v - a logically two-dimensional array of values 1667 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values 1668 1669 Level: beginner 1670 1671 Notes: 1672 By default the values, `v`, are row-oriented. See `MatSetOption()` for other options. 1673 1674 Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1675 options cannot be mixed without intervening calls to the assembly 1676 routines. 1677 1678 The grid coordinates are across the entire grid, not just the local portion 1679 1680 `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran 1681 as well as in C. 1682 1683 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1684 1685 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1686 or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1687 1688 The columns and rows in the stencil passed in MUST be contained within the 1689 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1690 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1691 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1692 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1693 1694 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 1695 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 1696 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 1697 `DM_BOUNDARY_PERIODIC` boundary type. 1698 1699 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 1700 a single value per point) you can skip filling those indices. 1701 1702 Inspired by the structured grid interface to the HYPRE package 1703 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1704 1705 Efficiency Alert: 1706 The routine `MatSetValuesBlockedStencil()` may offer much better efficiency 1707 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1708 1709 Fortran Notes: 1710 `idxm` and `idxn` should be declared as 1711 $ MatStencil idxm(4,m),idxn(4,n) 1712 and the values inserted using 1713 .vb 1714 idxm(MatStencil_i,1) = i 1715 idxm(MatStencil_j,1) = j 1716 idxm(MatStencil_k,1) = k 1717 idxm(MatStencil_c,1) = c 1718 etc 1719 .ve 1720 1721 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1722 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil` 1723 @*/ 1724 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1725 { 1726 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1727 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1728 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1729 1730 PetscFunctionBegin; 1731 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1732 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1733 PetscValidType(mat, 1); 1734 PetscValidPointer(idxm, 3); 1735 PetscValidPointer(idxn, 5); 1736 1737 if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 1738 jdxm = buf; 1739 jdxn = buf + m; 1740 } else { 1741 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1742 jdxm = bufm; 1743 jdxn = bufn; 1744 } 1745 for (i = 0; i < m; i++) { 1746 for (j = 0; j < 3 - sdim; j++) dxm++; 1747 tmp = *dxm++ - starts[0]; 1748 for (j = 0; j < dim - 1; j++) { 1749 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1750 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1751 } 1752 if (mat->stencil.noc) dxm++; 1753 jdxm[i] = tmp; 1754 } 1755 for (i = 0; i < n; i++) { 1756 for (j = 0; j < 3 - sdim; j++) dxn++; 1757 tmp = *dxn++ - starts[0]; 1758 for (j = 0; j < dim - 1; j++) { 1759 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1760 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1761 } 1762 if (mat->stencil.noc) dxn++; 1763 jdxn[i] = tmp; 1764 } 1765 PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv)); 1766 PetscCall(PetscFree2(bufm, bufn)); 1767 PetscFunctionReturn(PETSC_SUCCESS); 1768 } 1769 1770 /*@ 1771 MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix. 1772 Using structured grid indexing 1773 1774 Not Collective 1775 1776 Input Parameters: 1777 + mat - the matrix 1778 . m - number of rows being entered 1779 . idxm - grid coordinates for matrix rows being entered 1780 . n - number of columns being entered 1781 . idxn - grid coordinates for matrix columns being entered 1782 . v - a logically two-dimensional array of values 1783 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values 1784 1785 Level: beginner 1786 1787 Notes: 1788 By default the values, `v`, are row-oriented and unsorted. 1789 See `MatSetOption()` for other options. 1790 1791 Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1792 options cannot be mixed without intervening calls to the assembly 1793 routines. 1794 1795 The grid coordinates are across the entire grid, not just the local portion 1796 1797 `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran 1798 as well as in C. 1799 1800 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1801 1802 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1803 or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1804 1805 The columns and rows in the stencil passed in MUST be contained within the 1806 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1807 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1808 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1809 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1810 1811 Negative indices may be passed in idxm and idxn, these rows and columns are 1812 simply ignored. This allows easily inserting element stiffness matrices 1813 with homogeneous Dirichlet boundary conditions that you don't want represented 1814 in the matrix. 1815 1816 Inspired by the structured grid interface to the HYPRE package 1817 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1818 1819 Fortran Notes: 1820 `idxm` and `idxn` should be declared as 1821 $ MatStencil idxm(4,m),idxn(4,n) 1822 and the values inserted using 1823 .vb 1824 idxm(MatStencil_i,1) = i 1825 idxm(MatStencil_j,1) = j 1826 idxm(MatStencil_k,1) = k 1827 etc 1828 .ve 1829 1830 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1831 `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`, 1832 `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` 1833 @*/ 1834 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1835 { 1836 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1837 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1838 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1839 1840 PetscFunctionBegin; 1841 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1842 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1843 PetscValidType(mat, 1); 1844 PetscValidPointer(idxm, 3); 1845 PetscValidPointer(idxn, 5); 1846 PetscValidScalarPointer(v, 6); 1847 1848 if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 1849 jdxm = buf; 1850 jdxn = buf + m; 1851 } else { 1852 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1853 jdxm = bufm; 1854 jdxn = bufn; 1855 } 1856 for (i = 0; i < m; i++) { 1857 for (j = 0; j < 3 - sdim; j++) dxm++; 1858 tmp = *dxm++ - starts[0]; 1859 for (j = 0; j < sdim - 1; j++) { 1860 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1861 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1862 } 1863 dxm++; 1864 jdxm[i] = tmp; 1865 } 1866 for (i = 0; i < n; i++) { 1867 for (j = 0; j < 3 - sdim; j++) dxn++; 1868 tmp = *dxn++ - starts[0]; 1869 for (j = 0; j < sdim - 1; j++) { 1870 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1871 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1872 } 1873 dxn++; 1874 jdxn[i] = tmp; 1875 } 1876 PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv)); 1877 PetscCall(PetscFree2(bufm, bufn)); 1878 PetscFunctionReturn(PETSC_SUCCESS); 1879 } 1880 1881 /*@ 1882 MatSetStencil - Sets the grid information for setting values into a matrix via 1883 `MatSetValuesStencil()` 1884 1885 Not Collective 1886 1887 Input Parameters: 1888 + mat - the matrix 1889 . dim - dimension of the grid 1, 2, or 3 1890 . dims - number of grid points in x, y, and z direction, including ghost points on your processor 1891 . starts - starting point of ghost nodes on your processor in x, y, and z direction 1892 - dof - number of degrees of freedom per node 1893 1894 Level: beginner 1895 1896 Notes: 1897 Inspired by the structured grid interface to the HYPRE package 1898 (www.llnl.gov/CASC/hyper) 1899 1900 For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the 1901 user. 1902 1903 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1904 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()` 1905 @*/ 1906 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof) 1907 { 1908 PetscFunctionBegin; 1909 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1910 PetscValidIntPointer(dims, 3); 1911 PetscValidIntPointer(starts, 4); 1912 1913 mat->stencil.dim = dim + (dof > 1); 1914 for (PetscInt i = 0; i < dim; i++) { 1915 mat->stencil.dims[i] = dims[dim - i - 1]; /* copy the values in backwards */ 1916 mat->stencil.starts[i] = starts[dim - i - 1]; 1917 } 1918 mat->stencil.dims[dim] = dof; 1919 mat->stencil.starts[dim] = 0; 1920 mat->stencil.noc = (PetscBool)(dof == 1); 1921 PetscFunctionReturn(PETSC_SUCCESS); 1922 } 1923 1924 /*@C 1925 MatSetValuesBlocked - Inserts or adds a block of values into a matrix. 1926 1927 Not Collective 1928 1929 Input Parameters: 1930 + mat - the matrix 1931 . v - a logically two-dimensional array of values 1932 . m - the number of block rows 1933 . idxm - the global block indices 1934 . n - the number of block columns 1935 . idxn - the global block indices 1936 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values 1937 1938 Level: intermediate 1939 1940 Notes: 1941 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call 1942 MatXXXXSetPreallocation() or `MatSetUp()` before using this routine. 1943 1944 The `m` and `n` count the NUMBER of blocks in the row direction and column direction, 1945 NOT the total number of rows/columns; for example, if the block size is 2 and 1946 you are passing in values for rows 2,3,4,5 then m would be 2 (not 4). 1947 The values in idxm would be 1 2; that is the first index for each block divided by 1948 the block size. 1949 1950 You must call `MatSetBlockSize()` when constructing this matrix (before 1951 preallocating it). 1952 1953 By default the values, `v`, are row-oriented, so the layout of 1954 `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options. 1955 1956 Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES` 1957 options cannot be mixed without intervening calls to the assembly 1958 routines. 1959 1960 `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran 1961 as well as in C. 1962 1963 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1964 simply ignored. This allows easily inserting element stiffness matrices 1965 with homogeneous Dirichlet boundary conditions that you don't want represented 1966 in the matrix. 1967 1968 Each time an entry is set within a sparse matrix via `MatSetValues()`, 1969 internal searching must be done to determine where to place the 1970 data in the matrix storage space. By instead inserting blocks of 1971 entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is 1972 reduced. 1973 1974 Example: 1975 .vb 1976 Suppose m=n=2 and block size(bs) = 2 The array is 1977 1978 1 2 | 3 4 1979 5 6 | 7 8 1980 - - - | - - - 1981 9 10 | 11 12 1982 13 14 | 15 16 1983 1984 v[] should be passed in like 1985 v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] 1986 1987 If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then 1988 v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16] 1989 .ve 1990 1991 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()` 1992 @*/ 1993 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1994 { 1995 PetscFunctionBeginHot; 1996 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1997 PetscValidType(mat, 1); 1998 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1999 PetscValidIntPointer(idxm, 3); 2000 PetscValidIntPointer(idxn, 5); 2001 MatCheckPreallocated(mat, 1); 2002 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2003 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2004 if (PetscDefined(USE_DEBUG)) { 2005 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2006 PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2007 } 2008 if (PetscDefined(USE_DEBUG)) { 2009 PetscInt rbs, cbs, M, N, i; 2010 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 2011 PetscCall(MatGetSize(mat, &M, &N)); 2012 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); 2013 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); 2014 } 2015 if (mat->assembled) { 2016 mat->was_assembled = PETSC_TRUE; 2017 mat->assembled = PETSC_FALSE; 2018 } 2019 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2020 if (mat->ops->setvaluesblocked) { 2021 PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv); 2022 } else { 2023 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn; 2024 PetscInt i, j, bs, cbs; 2025 2026 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 2027 if (m * bs + n * cbs <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2028 iidxm = buf; 2029 iidxn = buf + m * bs; 2030 } else { 2031 PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc)); 2032 iidxm = bufr; 2033 iidxn = bufc; 2034 } 2035 for (i = 0; i < m; i++) { 2036 for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j; 2037 } 2038 if (m != n || bs != cbs || idxm != idxn) { 2039 for (i = 0; i < n; i++) { 2040 for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j; 2041 } 2042 } else iidxn = iidxm; 2043 PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv)); 2044 PetscCall(PetscFree2(bufr, bufc)); 2045 } 2046 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2047 PetscFunctionReturn(PETSC_SUCCESS); 2048 } 2049 2050 /*@C 2051 MatGetValues - Gets a block of local values from a matrix. 2052 2053 Not Collective; can only return values that are owned by the give process 2054 2055 Input Parameters: 2056 + mat - the matrix 2057 . v - a logically two-dimensional array for storing the values 2058 . m - the number of rows 2059 . idxm - the global indices of the rows 2060 . n - the number of columns 2061 - idxn - the global indices of the columns 2062 2063 Level: advanced 2064 2065 Notes: 2066 The user must allocate space (m*n `PetscScalar`s) for the values, `v`. 2067 The values, `v`, are then returned in a row-oriented format, 2068 analogous to that used by default in `MatSetValues()`. 2069 2070 `MatGetValues()` uses 0-based row and column numbers in 2071 Fortran as well as in C. 2072 2073 `MatGetValues()` requires that the matrix has been assembled 2074 with `MatAssemblyBegin()`/`MatAssemblyEnd()`. Thus, calls to 2075 `MatSetValues()` and `MatGetValues()` CANNOT be made in succession 2076 without intermediate matrix assembly. 2077 2078 Negative row or column indices will be ignored and those locations in `v` will be 2079 left unchanged. 2080 2081 For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI process. 2082 That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable 2083 from `MatGetOwnershipRange`(mat,&rstart,&rend). 2084 2085 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()` 2086 @*/ 2087 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) 2088 { 2089 PetscFunctionBegin; 2090 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2091 PetscValidType(mat, 1); 2092 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); 2093 PetscValidIntPointer(idxm, 3); 2094 PetscValidIntPointer(idxn, 5); 2095 PetscValidScalarPointer(v, 6); 2096 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2097 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2098 MatCheckPreallocated(mat, 1); 2099 2100 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2101 PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v); 2102 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2103 PetscFunctionReturn(PETSC_SUCCESS); 2104 } 2105 2106 /*@C 2107 MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices 2108 defined previously by `MatSetLocalToGlobalMapping()` 2109 2110 Not Collective 2111 2112 Input Parameters: 2113 + mat - the matrix 2114 . nrow - number of rows 2115 . irow - the row local indices 2116 . ncol - number of columns 2117 - icol - the column local indices 2118 2119 Output Parameter: 2120 . y - a logically two-dimensional array of values 2121 2122 Level: advanced 2123 2124 Notes: 2125 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine. 2126 2127 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, 2128 are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can 2129 determine if the resulting global row associated with the local row r is owned by the requesting MPI process by applying the `ISLocalToGlobalMapping` set 2130 with `MatSetLocalToGlobalMapping()`. 2131 2132 Developer Notes: 2133 This is labelled with C so does not automatically generate Fortran stubs and interfaces 2134 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2135 2136 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2137 `MatSetValuesLocal()`, `MatGetValues()` 2138 @*/ 2139 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[]) 2140 { 2141 PetscFunctionBeginHot; 2142 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2143 PetscValidType(mat, 1); 2144 MatCheckPreallocated(mat, 1); 2145 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */ 2146 PetscValidIntPointer(irow, 3); 2147 PetscValidIntPointer(icol, 5); 2148 if (PetscDefined(USE_DEBUG)) { 2149 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2150 PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2151 } 2152 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2153 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2154 if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y); 2155 else { 2156 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm; 2157 if ((nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2158 irowm = buf; 2159 icolm = buf + nrow; 2160 } else { 2161 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2162 irowm = bufr; 2163 icolm = bufc; 2164 } 2165 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping())."); 2166 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping())."); 2167 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm)); 2168 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm)); 2169 PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y)); 2170 PetscCall(PetscFree2(bufr, bufc)); 2171 } 2172 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2173 PetscFunctionReturn(PETSC_SUCCESS); 2174 } 2175 2176 /*@ 2177 MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and 2178 the same size. Currently, this can only be called once and creates the given matrix. 2179 2180 Not Collective 2181 2182 Input Parameters: 2183 + mat - the matrix 2184 . nb - the number of blocks 2185 . bs - the number of rows (and columns) in each block 2186 . rows - a concatenation of the rows for each block 2187 - v - a concatenation of logically two-dimensional arrays of values 2188 2189 Level: advanced 2190 2191 Note: 2192 `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values 2193 2194 In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix. 2195 2196 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 2197 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()` 2198 @*/ 2199 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[]) 2200 { 2201 PetscFunctionBegin; 2202 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2203 PetscValidType(mat, 1); 2204 PetscValidIntPointer(rows, 4); 2205 PetscValidScalarPointer(v, 5); 2206 PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2207 2208 PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0)); 2209 if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v); 2210 else { 2211 for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES)); 2212 } 2213 PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0)); 2214 PetscFunctionReturn(PETSC_SUCCESS); 2215 } 2216 2217 /*@ 2218 MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by 2219 the routine `MatSetValuesLocal()` to allow users to insert matrix entries 2220 using a local (per-processor) numbering. 2221 2222 Not Collective 2223 2224 Input Parameters: 2225 + x - the matrix 2226 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()` 2227 - cmapping - column mapping 2228 2229 Level: intermediate 2230 2231 Note: 2232 If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix 2233 2234 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()` 2235 @*/ 2236 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping) 2237 { 2238 PetscFunctionBegin; 2239 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 2240 PetscValidType(x, 1); 2241 if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2); 2242 if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3); 2243 if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping); 2244 else { 2245 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping)); 2246 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping)); 2247 } 2248 PetscFunctionReturn(PETSC_SUCCESS); 2249 } 2250 2251 /*@ 2252 MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()` 2253 2254 Not Collective 2255 2256 Input Parameter: 2257 . A - the matrix 2258 2259 Output Parameters: 2260 + rmapping - row mapping 2261 - cmapping - column mapping 2262 2263 Level: advanced 2264 2265 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()` 2266 @*/ 2267 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping) 2268 { 2269 PetscFunctionBegin; 2270 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2271 PetscValidType(A, 1); 2272 if (rmapping) { 2273 PetscValidPointer(rmapping, 2); 2274 *rmapping = A->rmap->mapping; 2275 } 2276 if (cmapping) { 2277 PetscValidPointer(cmapping, 3); 2278 *cmapping = A->cmap->mapping; 2279 } 2280 PetscFunctionReturn(PETSC_SUCCESS); 2281 } 2282 2283 /*@ 2284 MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix 2285 2286 Logically Collective 2287 2288 Input Parameters: 2289 + A - the matrix 2290 . rmap - row layout 2291 - cmap - column layout 2292 2293 Level: advanced 2294 2295 Note: 2296 The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called. 2297 2298 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()` 2299 @*/ 2300 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap) 2301 { 2302 PetscFunctionBegin; 2303 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2304 PetscCall(PetscLayoutReference(rmap, &A->rmap)); 2305 PetscCall(PetscLayoutReference(cmap, &A->cmap)); 2306 PetscFunctionReturn(PETSC_SUCCESS); 2307 } 2308 2309 /*@ 2310 MatGetLayouts - Gets the `PetscLayout` objects for rows and columns 2311 2312 Not Collective 2313 2314 Input Parameter: 2315 . A - the matrix 2316 2317 Output Parameters: 2318 + rmap - row layout 2319 - cmap - column layout 2320 2321 Level: advanced 2322 2323 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()` 2324 @*/ 2325 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap) 2326 { 2327 PetscFunctionBegin; 2328 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2329 PetscValidType(A, 1); 2330 if (rmap) { 2331 PetscValidPointer(rmap, 2); 2332 *rmap = A->rmap; 2333 } 2334 if (cmap) { 2335 PetscValidPointer(cmap, 3); 2336 *cmap = A->cmap; 2337 } 2338 PetscFunctionReturn(PETSC_SUCCESS); 2339 } 2340 2341 /*@C 2342 MatSetValuesLocal - Inserts or adds values into certain locations of a matrix, 2343 using a local numbering of the nodes. 2344 2345 Not Collective 2346 2347 Input Parameters: 2348 + mat - the matrix 2349 . nrow - number of rows 2350 . irow - the row local indices 2351 . ncol - number of columns 2352 . icol - the column local indices 2353 . y - a logically two-dimensional array of values 2354 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2355 2356 Level: intermediate 2357 2358 Notes: 2359 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 2360 `MatSetUp()` before using this routine 2361 2362 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine 2363 2364 Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2365 options cannot be mixed without intervening calls to the assembly 2366 routines. 2367 2368 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2369 MUST be called after all calls to `MatSetValuesLocal()` have been completed. 2370 2371 Developer Notes: 2372 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2373 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2374 2375 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2376 `MatGetValuesLocal()` 2377 @*/ 2378 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2379 { 2380 PetscFunctionBeginHot; 2381 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2382 PetscValidType(mat, 1); 2383 MatCheckPreallocated(mat, 1); 2384 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2385 PetscValidIntPointer(irow, 3); 2386 PetscValidIntPointer(icol, 5); 2387 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2388 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2389 if (PetscDefined(USE_DEBUG)) { 2390 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2391 PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2392 } 2393 2394 if (mat->assembled) { 2395 mat->was_assembled = PETSC_TRUE; 2396 mat->assembled = PETSC_FALSE; 2397 } 2398 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2399 if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv); 2400 else { 2401 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2402 const PetscInt *irowm, *icolm; 2403 2404 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2405 bufr = buf; 2406 bufc = buf + nrow; 2407 irowm = bufr; 2408 icolm = bufc; 2409 } else { 2410 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2411 irowm = bufr; 2412 icolm = bufc; 2413 } 2414 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr)); 2415 else irowm = irow; 2416 if (mat->cmap->mapping) { 2417 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2418 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc)); 2419 } else icolm = irowm; 2420 } else icolm = icol; 2421 PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv)); 2422 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2423 } 2424 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2425 PetscFunctionReturn(PETSC_SUCCESS); 2426 } 2427 2428 /*@C 2429 MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix, 2430 using a local ordering of the nodes a block at a time. 2431 2432 Not Collective 2433 2434 Input Parameters: 2435 + mat - the matrix 2436 . nrow - number of rows 2437 . irow - the row local indices 2438 . ncol - number of columns 2439 . icol - the column local indices 2440 . y - a logically two-dimensional array of values 2441 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2442 2443 Level: intermediate 2444 2445 Notes: 2446 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 2447 `MatSetUp()` before using this routine 2448 2449 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()` 2450 before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the 2451 2452 Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2453 options cannot be mixed without intervening calls to the assembly 2454 routines. 2455 2456 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2457 MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed. 2458 2459 Developer Notes: 2460 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2461 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2462 2463 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, 2464 `MatSetValuesLocal()`, `MatSetValuesBlocked()` 2465 @*/ 2466 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2467 { 2468 PetscFunctionBeginHot; 2469 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2470 PetscValidType(mat, 1); 2471 MatCheckPreallocated(mat, 1); 2472 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2473 PetscValidIntPointer(irow, 3); 2474 PetscValidIntPointer(icol, 5); 2475 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2476 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2477 if (PetscDefined(USE_DEBUG)) { 2478 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2479 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); 2480 } 2481 2482 if (mat->assembled) { 2483 mat->was_assembled = PETSC_TRUE; 2484 mat->assembled = PETSC_FALSE; 2485 } 2486 if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */ 2487 PetscInt irbs, rbs; 2488 PetscCall(MatGetBlockSizes(mat, &rbs, NULL)); 2489 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs)); 2490 PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs); 2491 } 2492 if (PetscUnlikelyDebug(mat->cmap->mapping)) { 2493 PetscInt icbs, cbs; 2494 PetscCall(MatGetBlockSizes(mat, NULL, &cbs)); 2495 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs)); 2496 PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs); 2497 } 2498 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2499 if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv); 2500 else { 2501 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2502 const PetscInt *irowm, *icolm; 2503 2504 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2505 bufr = buf; 2506 bufc = buf + nrow; 2507 irowm = bufr; 2508 icolm = bufc; 2509 } else { 2510 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2511 irowm = bufr; 2512 icolm = bufc; 2513 } 2514 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr)); 2515 else irowm = irow; 2516 if (mat->cmap->mapping) { 2517 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2518 PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc)); 2519 } else icolm = irowm; 2520 } else icolm = icol; 2521 PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv)); 2522 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2523 } 2524 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2525 PetscFunctionReturn(PETSC_SUCCESS); 2526 } 2527 2528 /*@ 2529 MatMultDiagonalBlock - Computes the matrix-vector product, y = Dx. Where D is defined by the inode or block structure of the diagonal 2530 2531 Collective 2532 2533 Input Parameters: 2534 + mat - the matrix 2535 - x - the vector to be multiplied 2536 2537 Output Parameter: 2538 . y - the result 2539 2540 Level: developer 2541 2542 Note: 2543 The vectors `x` and `y` cannot be the same. I.e., one cannot 2544 call `MatMultDiagonalBlock`(A,y,y). 2545 2546 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2547 @*/ 2548 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y) 2549 { 2550 PetscFunctionBegin; 2551 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2552 PetscValidType(mat, 1); 2553 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2554 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2555 2556 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2557 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2558 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2559 MatCheckPreallocated(mat, 1); 2560 2561 PetscUseTypeMethod(mat, multdiagonalblock, x, y); 2562 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2563 PetscFunctionReturn(PETSC_SUCCESS); 2564 } 2565 2566 /*@ 2567 MatMult - Computes the matrix-vector product, y = Ax. 2568 2569 Neighbor-wise Collective 2570 2571 Input Parameters: 2572 + mat - the matrix 2573 - x - the vector to be multiplied 2574 2575 Output Parameter: 2576 . y - the result 2577 2578 Level: beginner 2579 2580 Note: 2581 The vectors `x` and `y` cannot be the same. I.e., one cannot 2582 call `MatMult`(A,y,y). 2583 2584 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2585 @*/ 2586 PetscErrorCode MatMult(Mat mat, Vec x, Vec y) 2587 { 2588 PetscFunctionBegin; 2589 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2590 PetscValidType(mat, 1); 2591 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2592 VecCheckAssembled(x); 2593 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2594 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2595 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2596 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2597 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); 2598 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); 2599 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); 2600 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); 2601 PetscCall(VecSetErrorIfLocked(y, 3)); 2602 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2603 MatCheckPreallocated(mat, 1); 2604 2605 PetscCall(VecLockReadPush(x)); 2606 PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0)); 2607 PetscUseTypeMethod(mat, mult, x, y); 2608 PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0)); 2609 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2610 PetscCall(VecLockReadPop(x)); 2611 PetscFunctionReturn(PETSC_SUCCESS); 2612 } 2613 2614 /*@ 2615 MatMultTranspose - Computes matrix transpose times a vector y = A^T * x. 2616 2617 Neighbor-wise Collective 2618 2619 Input Parameters: 2620 + mat - the matrix 2621 - x - the vector to be multiplied 2622 2623 Output Parameter: 2624 . y - the result 2625 2626 Level: beginner 2627 2628 Notes: 2629 The vectors `x` and `y` cannot be the same. I.e., one cannot 2630 call `MatMultTranspose`(A,y,y). 2631 2632 For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple, 2633 use `MatMultHermitianTranspose()` 2634 2635 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()` 2636 @*/ 2637 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y) 2638 { 2639 PetscErrorCode (*op)(Mat, Vec, Vec) = NULL; 2640 2641 PetscFunctionBegin; 2642 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2643 PetscValidType(mat, 1); 2644 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2645 VecCheckAssembled(x); 2646 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2647 2648 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2649 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2650 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2651 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); 2652 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); 2653 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); 2654 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); 2655 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2656 MatCheckPreallocated(mat, 1); 2657 2658 if (!mat->ops->multtranspose) { 2659 if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult; 2660 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); 2661 } else op = mat->ops->multtranspose; 2662 PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0)); 2663 PetscCall(VecLockReadPush(x)); 2664 PetscCall((*op)(mat, x, y)); 2665 PetscCall(VecLockReadPop(x)); 2666 PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0)); 2667 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2668 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2669 PetscFunctionReturn(PETSC_SUCCESS); 2670 } 2671 2672 /*@ 2673 MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector. 2674 2675 Neighbor-wise Collective 2676 2677 Input Parameters: 2678 + mat - the matrix 2679 - x - the vector to be multiplied 2680 2681 Output Parameter: 2682 . y - the result 2683 2684 Level: beginner 2685 2686 Notes: 2687 The vectors `x` and `y` cannot be the same. I.e., one cannot 2688 call `MatMultHermitianTranspose`(A,y,y). 2689 2690 Also called the conjugate transpose, complex conjugate transpose, or adjoint. 2691 2692 For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical. 2693 2694 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()` 2695 @*/ 2696 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y) 2697 { 2698 PetscFunctionBegin; 2699 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2700 PetscValidType(mat, 1); 2701 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2702 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2703 2704 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2705 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2706 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2707 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); 2708 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); 2709 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); 2710 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); 2711 MatCheckPreallocated(mat, 1); 2712 2713 PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0)); 2714 #if defined(PETSC_USE_COMPLEX) 2715 if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) { 2716 PetscCall(VecLockReadPush(x)); 2717 if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y); 2718 else PetscUseTypeMethod(mat, mult, x, y); 2719 PetscCall(VecLockReadPop(x)); 2720 } else { 2721 Vec w; 2722 PetscCall(VecDuplicate(x, &w)); 2723 PetscCall(VecCopy(x, w)); 2724 PetscCall(VecConjugate(w)); 2725 PetscCall(MatMultTranspose(mat, w, y)); 2726 PetscCall(VecDestroy(&w)); 2727 PetscCall(VecConjugate(y)); 2728 } 2729 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2730 #else 2731 PetscCall(MatMultTranspose(mat, x, y)); 2732 #endif 2733 PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0)); 2734 PetscFunctionReturn(PETSC_SUCCESS); 2735 } 2736 2737 /*@ 2738 MatMultAdd - Computes v3 = v2 + A * v1. 2739 2740 Neighbor-wise Collective 2741 2742 Input Parameters: 2743 + mat - the matrix 2744 . v1 - the vector to be multiplied by `mat` 2745 - v2 - the vector to be added to the result 2746 2747 Output Parameter: 2748 . v3 - the result 2749 2750 Level: beginner 2751 2752 Note: 2753 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2754 call `MatMultAdd`(A,v1,v2,v1). 2755 2756 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()` 2757 @*/ 2758 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2759 { 2760 PetscFunctionBegin; 2761 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2762 PetscValidType(mat, 1); 2763 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2764 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2765 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2766 2767 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2768 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2769 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); 2770 /* 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); 2771 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); */ 2772 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); 2773 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); 2774 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2775 MatCheckPreallocated(mat, 1); 2776 2777 PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3)); 2778 PetscCall(VecLockReadPush(v1)); 2779 PetscUseTypeMethod(mat, multadd, v1, v2, v3); 2780 PetscCall(VecLockReadPop(v1)); 2781 PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3)); 2782 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2783 PetscFunctionReturn(PETSC_SUCCESS); 2784 } 2785 2786 /*@ 2787 MatMultTransposeAdd - Computes v3 = v2 + A' * v1. 2788 2789 Neighbor-wise Collective 2790 2791 Input Parameters: 2792 + mat - the matrix 2793 . v1 - the vector to be multiplied by the transpose of the matrix 2794 - v2 - the vector to be added to the result 2795 2796 Output Parameter: 2797 . v3 - the result 2798 2799 Level: beginner 2800 2801 Note: 2802 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2803 call `MatMultTransposeAdd`(A,v1,v2,v1). 2804 2805 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2806 @*/ 2807 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2808 { 2809 PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd; 2810 2811 PetscFunctionBegin; 2812 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2813 PetscValidType(mat, 1); 2814 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2815 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2816 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2817 2818 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2819 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2820 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); 2821 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); 2822 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); 2823 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2824 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2825 MatCheckPreallocated(mat, 1); 2826 2827 PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2828 PetscCall(VecLockReadPush(v1)); 2829 PetscCall((*op)(mat, v1, v2, v3)); 2830 PetscCall(VecLockReadPop(v1)); 2831 PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2832 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2833 PetscFunctionReturn(PETSC_SUCCESS); 2834 } 2835 2836 /*@ 2837 MatMultHermitianTransposeAdd - Computes v3 = v2 + A^H * v1. 2838 2839 Neighbor-wise Collective 2840 2841 Input Parameters: 2842 + mat - the matrix 2843 . v1 - the vector to be multiplied by the Hermitian transpose 2844 - v2 - the vector to be added to the result 2845 2846 Output Parameter: 2847 . v3 - the result 2848 2849 Level: beginner 2850 2851 Note: 2852 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2853 call `MatMultHermitianTransposeAdd`(A,v1,v2,v1). 2854 2855 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2856 @*/ 2857 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2858 { 2859 PetscFunctionBegin; 2860 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2861 PetscValidType(mat, 1); 2862 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2863 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2864 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2865 2866 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2867 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2868 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2869 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); 2870 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); 2871 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); 2872 MatCheckPreallocated(mat, 1); 2873 2874 PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2875 PetscCall(VecLockReadPush(v1)); 2876 if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3); 2877 else { 2878 Vec w, z; 2879 PetscCall(VecDuplicate(v1, &w)); 2880 PetscCall(VecCopy(v1, w)); 2881 PetscCall(VecConjugate(w)); 2882 PetscCall(VecDuplicate(v3, &z)); 2883 PetscCall(MatMultTranspose(mat, w, z)); 2884 PetscCall(VecDestroy(&w)); 2885 PetscCall(VecConjugate(z)); 2886 if (v2 != v3) { 2887 PetscCall(VecWAXPY(v3, 1.0, v2, z)); 2888 } else { 2889 PetscCall(VecAXPY(v3, 1.0, z)); 2890 } 2891 PetscCall(VecDestroy(&z)); 2892 } 2893 PetscCall(VecLockReadPop(v1)); 2894 PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2895 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2896 PetscFunctionReturn(PETSC_SUCCESS); 2897 } 2898 2899 /*@C 2900 MatGetFactorType - gets the type of factorization it is 2901 2902 Not Collective 2903 2904 Input Parameter: 2905 . mat - the matrix 2906 2907 Output Parameter: 2908 . 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` 2909 2910 Level: intermediate 2911 2912 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2913 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2914 @*/ 2915 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t) 2916 { 2917 PetscFunctionBegin; 2918 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2919 PetscValidType(mat, 1); 2920 PetscValidPointer(t, 2); 2921 *t = mat->factortype; 2922 PetscFunctionReturn(PETSC_SUCCESS); 2923 } 2924 2925 /*@C 2926 MatSetFactorType - sets the type of factorization it is 2927 2928 Logically Collective 2929 2930 Input Parameters: 2931 + mat - the matrix 2932 - 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` 2933 2934 Level: intermediate 2935 2936 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2937 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2938 @*/ 2939 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t) 2940 { 2941 PetscFunctionBegin; 2942 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2943 PetscValidType(mat, 1); 2944 mat->factortype = t; 2945 PetscFunctionReturn(PETSC_SUCCESS); 2946 } 2947 2948 /*@C 2949 MatGetInfo - Returns information about matrix storage (number of 2950 nonzeros, memory, etc.). 2951 2952 Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag 2953 2954 Input Parameters: 2955 + mat - the matrix 2956 - 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) 2957 2958 Output Parameter: 2959 . info - matrix information context 2960 2961 Options Database Key: 2962 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT` 2963 2964 Notes: 2965 The `MatInfo` context contains a variety of matrix data, including 2966 number of nonzeros allocated and used, number of mallocs during 2967 matrix assembly, etc. Additional information for factored matrices 2968 is provided (such as the fill ratio, number of mallocs during 2969 factorization, etc.). 2970 2971 Example: 2972 See the file ${PETSC_DIR}/include/petscmat.h for a complete list of 2973 data within the MatInfo context. For example, 2974 .vb 2975 MatInfo info; 2976 Mat A; 2977 double mal, nz_a, nz_u; 2978 2979 MatGetInfo(A, MAT_LOCAL, &info); 2980 mal = info.mallocs; 2981 nz_a = info.nz_allocated; 2982 .ve 2983 2984 Fortran users should declare info as a double precision 2985 array of dimension `MAT_INFO_SIZE`, and then extract the parameters 2986 of interest. See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h 2987 a complete list of parameter names. 2988 .vb 2989 double precision info(MAT_INFO_SIZE) 2990 double precision mal, nz_a 2991 Mat A 2992 integer ierr 2993 2994 call MatGetInfo(A, MAT_LOCAL, info, ierr) 2995 mal = info(MAT_INFO_MALLOCS) 2996 nz_a = info(MAT_INFO_NZ_ALLOCATED) 2997 .ve 2998 2999 Level: intermediate 3000 3001 Developer Notes: 3002 The Fortran interface is not autogenerated as the 3003 interface definition cannot be generated correctly [due to `MatInfo` argument] 3004 3005 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()` 3006 @*/ 3007 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info) 3008 { 3009 PetscFunctionBegin; 3010 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3011 PetscValidType(mat, 1); 3012 PetscValidPointer(info, 3); 3013 MatCheckPreallocated(mat, 1); 3014 PetscUseTypeMethod(mat, getinfo, flag, info); 3015 PetscFunctionReturn(PETSC_SUCCESS); 3016 } 3017 3018 /* 3019 This is used by external packages where it is not easy to get the info from the actual 3020 matrix factorization. 3021 */ 3022 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info) 3023 { 3024 PetscFunctionBegin; 3025 PetscCall(PetscMemzero(info, sizeof(MatInfo))); 3026 PetscFunctionReturn(PETSC_SUCCESS); 3027 } 3028 3029 /*@C 3030 MatLUFactor - Performs in-place LU factorization of matrix. 3031 3032 Collective 3033 3034 Input Parameters: 3035 + mat - the matrix 3036 . row - row permutation 3037 . col - column permutation 3038 - info - options for factorization, includes 3039 .vb 3040 fill - expected fill as ratio of original fill. 3041 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3042 Run with the option -info to determine an optimal value to use 3043 .ve 3044 3045 Level: developer 3046 3047 Notes: 3048 Most users should employ the `KSP` interface for linear solvers 3049 instead of working directly with matrix algebra routines such as this. 3050 See, e.g., `KSPCreate()`. 3051 3052 This changes the state of the matrix to a factored matrix; it cannot be used 3053 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3054 3055 This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()` 3056 when not using `KSP`. 3057 3058 Developer Notes: 3059 The Fortran interface is not autogenerated as the 3060 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3061 3062 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, 3063 `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3064 @*/ 3065 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3066 { 3067 MatFactorInfo tinfo; 3068 3069 PetscFunctionBegin; 3070 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3071 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3072 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3073 if (info) PetscValidPointer(info, 4); 3074 PetscValidType(mat, 1); 3075 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3076 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3077 MatCheckPreallocated(mat, 1); 3078 if (!info) { 3079 PetscCall(MatFactorInfoInitialize(&tinfo)); 3080 info = &tinfo; 3081 } 3082 3083 PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0)); 3084 PetscUseTypeMethod(mat, lufactor, row, col, info); 3085 PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0)); 3086 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3087 PetscFunctionReturn(PETSC_SUCCESS); 3088 } 3089 3090 /*@C 3091 MatILUFactor - Performs in-place ILU factorization of matrix. 3092 3093 Collective 3094 3095 Input Parameters: 3096 + mat - the matrix 3097 . row - row permutation 3098 . col - column permutation 3099 - info - structure containing 3100 .vb 3101 levels - number of levels of fill. 3102 expected fill - as ratio of original fill. 3103 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 3104 missing diagonal entries) 3105 .ve 3106 3107 Level: developer 3108 3109 Notes: 3110 Most users should employ the `KSP` interface for linear solvers 3111 instead of working directly with matrix algebra routines such as this. 3112 See, e.g., `KSPCreate()`. 3113 3114 Probably really in-place only when level of fill is zero, otherwise allocates 3115 new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()` 3116 when not using `KSP`. 3117 3118 Developer Notes: 3119 The Fortran interface is not autogenerated as the 3120 interface definition cannot be generated correctly [due to MatFactorInfo] 3121 3122 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 3123 @*/ 3124 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3125 { 3126 PetscFunctionBegin; 3127 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3128 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3129 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3130 PetscValidPointer(info, 4); 3131 PetscValidType(mat, 1); 3132 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 3133 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3134 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3135 MatCheckPreallocated(mat, 1); 3136 3137 PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0)); 3138 PetscUseTypeMethod(mat, ilufactor, row, col, info); 3139 PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0)); 3140 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3141 PetscFunctionReturn(PETSC_SUCCESS); 3142 } 3143 3144 /*@C 3145 MatLUFactorSymbolic - Performs symbolic LU factorization of matrix. 3146 Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`. 3147 3148 Collective 3149 3150 Input Parameters: 3151 + fact - the factor matrix obtained with `MatGetFactor()` 3152 . mat - the matrix 3153 . row - the row permutation 3154 . col - the column permutation 3155 - info - options for factorization, includes 3156 .vb 3157 fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use 3158 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3159 .ve 3160 3161 Level: developer 3162 3163 Notes: 3164 See [Matrix Factorization](sec_matfactor) for additional information about factorizations 3165 3166 Most users should employ the simplified `KSP` interface for linear solvers 3167 instead of working directly with matrix algebra routines such as this. 3168 See, e.g., `KSPCreate()`. 3169 3170 Developer Notes: 3171 The Fortran interface is not autogenerated as the 3172 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3173 3174 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3175 @*/ 3176 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 3177 { 3178 MatFactorInfo tinfo; 3179 3180 PetscFunctionBegin; 3181 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3182 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3183 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 3184 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 3185 if (info) PetscValidPointer(info, 5); 3186 PetscValidType(fact, 1); 3187 PetscValidType(mat, 2); 3188 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3189 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3190 MatCheckPreallocated(mat, 2); 3191 if (!info) { 3192 PetscCall(MatFactorInfoInitialize(&tinfo)); 3193 info = &tinfo; 3194 } 3195 3196 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0)); 3197 PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info); 3198 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0)); 3199 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3200 PetscFunctionReturn(PETSC_SUCCESS); 3201 } 3202 3203 /*@C 3204 MatLUFactorNumeric - Performs numeric LU factorization of a matrix. 3205 Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`. 3206 3207 Collective 3208 3209 Input Parameters: 3210 + fact - the factor matrix obtained with `MatGetFactor()` 3211 . mat - the matrix 3212 - info - options for factorization 3213 3214 Level: developer 3215 3216 Notes: 3217 See `MatLUFactor()` for in-place factorization. See 3218 `MatCholeskyFactorNumeric()` for the symmetric, positive definite case. 3219 3220 Most users should employ the `KSP` interface for linear solvers 3221 instead of working directly with matrix algebra routines such as this. 3222 See, e.g., `KSPCreate()`. 3223 3224 Developer Notes: 3225 The Fortran interface is not autogenerated as the 3226 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3227 3228 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()` 3229 @*/ 3230 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3231 { 3232 MatFactorInfo tinfo; 3233 3234 PetscFunctionBegin; 3235 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3236 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3237 PetscValidType(fact, 1); 3238 PetscValidType(mat, 2); 3239 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3240 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, 3241 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3242 3243 MatCheckPreallocated(mat, 2); 3244 if (!info) { 3245 PetscCall(MatFactorInfoInitialize(&tinfo)); 3246 info = &tinfo; 3247 } 3248 3249 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3250 else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0)); 3251 PetscUseTypeMethod(fact, lufactornumeric, mat, info); 3252 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3253 else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0)); 3254 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3255 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3256 PetscFunctionReturn(PETSC_SUCCESS); 3257 } 3258 3259 /*@C 3260 MatCholeskyFactor - Performs in-place Cholesky factorization of a 3261 symmetric matrix. 3262 3263 Collective 3264 3265 Input Parameters: 3266 + mat - the matrix 3267 . perm - row and column permutations 3268 - info - expected fill as ratio of original fill 3269 3270 Level: developer 3271 3272 Notes: 3273 See `MatLUFactor()` for the nonsymmetric case. See also `MatGetFactor()`, 3274 `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`. 3275 3276 Most users should employ the `KSP` interface for linear solvers 3277 instead of working directly with matrix algebra routines such as this. 3278 See, e.g., `KSPCreate()`. 3279 3280 Developer Notes: 3281 The Fortran interface is not autogenerated as the 3282 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3283 3284 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()` 3285 `MatGetOrdering()` 3286 @*/ 3287 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info) 3288 { 3289 MatFactorInfo tinfo; 3290 3291 PetscFunctionBegin; 3292 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3293 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2); 3294 if (info) PetscValidPointer(info, 3); 3295 PetscValidType(mat, 1); 3296 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3297 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3298 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3299 MatCheckPreallocated(mat, 1); 3300 if (!info) { 3301 PetscCall(MatFactorInfoInitialize(&tinfo)); 3302 info = &tinfo; 3303 } 3304 3305 PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0)); 3306 PetscUseTypeMethod(mat, choleskyfactor, perm, info); 3307 PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0)); 3308 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3309 PetscFunctionReturn(PETSC_SUCCESS); 3310 } 3311 3312 /*@C 3313 MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization 3314 of a symmetric matrix. 3315 3316 Collective 3317 3318 Input Parameters: 3319 + fact - the factor matrix obtained with `MatGetFactor()` 3320 . mat - the matrix 3321 . perm - row and column permutations 3322 - info - options for factorization, includes 3323 .vb 3324 fill - expected fill as ratio of original fill. 3325 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3326 Run with the option -info to determine an optimal value to use 3327 .ve 3328 3329 Level: developer 3330 3331 Notes: 3332 See `MatLUFactorSymbolic()` for the nonsymmetric case. See also 3333 `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`. 3334 3335 Most users should employ the `KSP` interface for linear solvers 3336 instead of working directly with matrix algebra routines such as this. 3337 See, e.g., `KSPCreate()`. 3338 3339 Developer Notes: 3340 The Fortran interface is not autogenerated as the 3341 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3342 3343 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()` 3344 `MatGetOrdering()` 3345 @*/ 3346 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 3347 { 3348 MatFactorInfo tinfo; 3349 3350 PetscFunctionBegin; 3351 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3352 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3353 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 3354 if (info) PetscValidPointer(info, 4); 3355 PetscValidType(fact, 1); 3356 PetscValidType(mat, 2); 3357 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3358 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3359 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3360 MatCheckPreallocated(mat, 2); 3361 if (!info) { 3362 PetscCall(MatFactorInfoInitialize(&tinfo)); 3363 info = &tinfo; 3364 } 3365 3366 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3367 PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info); 3368 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3369 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3370 PetscFunctionReturn(PETSC_SUCCESS); 3371 } 3372 3373 /*@C 3374 MatCholeskyFactorNumeric - Performs numeric Cholesky factorization 3375 of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and 3376 `MatCholeskyFactorSymbolic()`. 3377 3378 Collective 3379 3380 Input Parameters: 3381 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored 3382 . mat - the initial matrix that is to be factored 3383 - info - options for factorization 3384 3385 Level: developer 3386 3387 Note: 3388 Most users should employ the `KSP` interface for linear solvers 3389 instead of working directly with matrix algebra routines such as this. 3390 See, e.g., `KSPCreate()`. 3391 3392 Developer Notes: 3393 The Fortran interface is not autogenerated as the 3394 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3395 3396 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()` 3397 @*/ 3398 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3399 { 3400 MatFactorInfo tinfo; 3401 3402 PetscFunctionBegin; 3403 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3404 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3405 PetscValidType(fact, 1); 3406 PetscValidType(mat, 2); 3407 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3408 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, 3409 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3410 MatCheckPreallocated(mat, 2); 3411 if (!info) { 3412 PetscCall(MatFactorInfoInitialize(&tinfo)); 3413 info = &tinfo; 3414 } 3415 3416 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3417 else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0)); 3418 PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info); 3419 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3420 else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0)); 3421 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3422 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3423 PetscFunctionReturn(PETSC_SUCCESS); 3424 } 3425 3426 /*@ 3427 MatQRFactor - Performs in-place QR factorization of matrix. 3428 3429 Collective 3430 3431 Input Parameters: 3432 + mat - the matrix 3433 . col - column permutation 3434 - info - options for factorization, includes 3435 .vb 3436 fill - expected fill as ratio of original fill. 3437 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3438 Run with the option -info to determine an optimal value to use 3439 .ve 3440 3441 Level: developer 3442 3443 Notes: 3444 Most users should employ the `KSP` interface for linear solvers 3445 instead of working directly with matrix algebra routines such as this. 3446 See, e.g., `KSPCreate()`. 3447 3448 This changes the state of the matrix to a factored matrix; it cannot be used 3449 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3450 3451 Developer Notes: 3452 The Fortran interface is not autogenerated as the 3453 interface definition cannot be generated correctly [due to MatFactorInfo] 3454 3455 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`, 3456 `MatSetUnfactored()` 3457 @*/ 3458 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info) 3459 { 3460 PetscFunctionBegin; 3461 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3462 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2); 3463 if (info) PetscValidPointer(info, 3); 3464 PetscValidType(mat, 1); 3465 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3466 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3467 MatCheckPreallocated(mat, 1); 3468 PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0)); 3469 PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info)); 3470 PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0)); 3471 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3472 PetscFunctionReturn(PETSC_SUCCESS); 3473 } 3474 3475 /*@ 3476 MatQRFactorSymbolic - Performs symbolic QR factorization of matrix. 3477 Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`. 3478 3479 Collective 3480 3481 Input Parameters: 3482 + fact - the factor matrix obtained with `MatGetFactor()` 3483 . mat - the matrix 3484 . col - column permutation 3485 - info - options for factorization, includes 3486 .vb 3487 fill - expected fill as ratio of original fill. 3488 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3489 Run with the option -info to determine an optimal value to use 3490 .ve 3491 3492 Level: developer 3493 3494 Note: 3495 Most users should employ the `KSP` interface for linear solvers 3496 instead of working directly with matrix algebra routines such as this. 3497 See, e.g., `KSPCreate()`. 3498 3499 Developer Notes: 3500 The Fortran interface is not autogenerated as the 3501 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3502 3503 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfoInitialize()` 3504 @*/ 3505 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info) 3506 { 3507 MatFactorInfo tinfo; 3508 3509 PetscFunctionBegin; 3510 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3511 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3512 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3513 if (info) PetscValidPointer(info, 4); 3514 PetscValidType(fact, 1); 3515 PetscValidType(mat, 2); 3516 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3517 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3518 MatCheckPreallocated(mat, 2); 3519 if (!info) { 3520 PetscCall(MatFactorInfoInitialize(&tinfo)); 3521 info = &tinfo; 3522 } 3523 3524 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3525 PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info)); 3526 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3527 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3528 PetscFunctionReturn(PETSC_SUCCESS); 3529 } 3530 3531 /*@ 3532 MatQRFactorNumeric - Performs numeric QR factorization of a matrix. 3533 Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`. 3534 3535 Collective 3536 3537 Input Parameters: 3538 + fact - the factor matrix obtained with `MatGetFactor()` 3539 . mat - the matrix 3540 - info - options for factorization 3541 3542 Level: developer 3543 3544 Notes: 3545 See `MatQRFactor()` for in-place factorization. 3546 3547 Most users should employ the `KSP` interface for linear solvers 3548 instead of working directly with matrix algebra routines such as this. 3549 See, e.g., `KSPCreate()`. 3550 3551 Developer Notes: 3552 The Fortran interface is not autogenerated as the 3553 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3554 3555 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()` 3556 @*/ 3557 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3558 { 3559 MatFactorInfo tinfo; 3560 3561 PetscFunctionBegin; 3562 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3563 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3564 PetscValidType(fact, 1); 3565 PetscValidType(mat, 2); 3566 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3567 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, 3568 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3569 3570 MatCheckPreallocated(mat, 2); 3571 if (!info) { 3572 PetscCall(MatFactorInfoInitialize(&tinfo)); 3573 info = &tinfo; 3574 } 3575 3576 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3577 else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0)); 3578 PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info)); 3579 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3580 else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0)); 3581 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3582 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3583 PetscFunctionReturn(PETSC_SUCCESS); 3584 } 3585 3586 /*@ 3587 MatSolve - Solves A x = b, given a factored matrix. 3588 3589 Neighbor-wise Collective 3590 3591 Input Parameters: 3592 + mat - the factored matrix 3593 - b - the right-hand-side vector 3594 3595 Output Parameter: 3596 . x - the result vector 3597 3598 Level: developer 3599 3600 Notes: 3601 The vectors `b` and `x` cannot be the same. I.e., one cannot 3602 call `MatSolve`(A,x,x). 3603 3604 Most users should employ the `KSP` interface for linear solvers 3605 instead of working directly with matrix algebra routines such as this. 3606 See, e.g., `KSPCreate()`. 3607 3608 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3609 @*/ 3610 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x) 3611 { 3612 PetscFunctionBegin; 3613 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3614 PetscValidType(mat, 1); 3615 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3616 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3617 PetscCheckSameComm(mat, 1, b, 2); 3618 PetscCheckSameComm(mat, 1, x, 3); 3619 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3620 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); 3621 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); 3622 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); 3623 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3624 MatCheckPreallocated(mat, 1); 3625 3626 PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0)); 3627 if (mat->factorerrortype) { 3628 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3629 PetscCall(VecSetInf(x)); 3630 } else PetscUseTypeMethod(mat, solve, b, x); 3631 PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0)); 3632 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3633 PetscFunctionReturn(PETSC_SUCCESS); 3634 } 3635 3636 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans) 3637 { 3638 Vec b, x; 3639 PetscInt N, i; 3640 PetscErrorCode (*f)(Mat, Vec, Vec); 3641 PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE; 3642 3643 PetscFunctionBegin; 3644 if (A->factorerrortype) { 3645 PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype)); 3646 PetscCall(MatSetInf(X)); 3647 PetscFunctionReturn(PETSC_SUCCESS); 3648 } 3649 f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose; 3650 PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 3651 PetscCall(MatBoundToCPU(A, &Abound)); 3652 if (!Abound) { 3653 PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3654 PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3655 } 3656 #if PetscDefined(HAVE_CUDA) 3657 if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B)); 3658 if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X)); 3659 #elif PetscDefined(HAVE_HIP) 3660 if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B)); 3661 if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X)); 3662 #endif 3663 PetscCall(MatGetSize(B, NULL, &N)); 3664 for (i = 0; i < N; i++) { 3665 PetscCall(MatDenseGetColumnVecRead(B, i, &b)); 3666 PetscCall(MatDenseGetColumnVecWrite(X, i, &x)); 3667 PetscCall((*f)(A, b, x)); 3668 PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x)); 3669 PetscCall(MatDenseRestoreColumnVecRead(B, i, &b)); 3670 } 3671 if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B)); 3672 if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X)); 3673 PetscFunctionReturn(PETSC_SUCCESS); 3674 } 3675 3676 /*@ 3677 MatMatSolve - Solves A X = B, given a factored matrix. 3678 3679 Neighbor-wise Collective 3680 3681 Input Parameters: 3682 + A - the factored matrix 3683 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS) 3684 3685 Output Parameter: 3686 . X - the result matrix (dense matrix) 3687 3688 Level: developer 3689 3690 Note: 3691 If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`; 3692 otherwise, `B` and `X` cannot be the same. 3693 3694 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3695 @*/ 3696 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X) 3697 { 3698 PetscFunctionBegin; 3699 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3700 PetscValidType(A, 1); 3701 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3702 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3703 PetscCheckSameComm(A, 1, B, 2); 3704 PetscCheckSameComm(A, 1, X, 3); 3705 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); 3706 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); 3707 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"); 3708 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3709 MatCheckPreallocated(A, 1); 3710 3711 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3712 if (!A->ops->matsolve) { 3713 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name)); 3714 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE)); 3715 } else PetscUseTypeMethod(A, matsolve, B, X); 3716 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3717 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3718 PetscFunctionReturn(PETSC_SUCCESS); 3719 } 3720 3721 /*@ 3722 MatMatSolveTranspose - Solves A^T X = B, given a factored matrix. 3723 3724 Neighbor-wise Collective 3725 3726 Input Parameters: 3727 + A - the factored matrix 3728 - B - the right-hand-side matrix (`MATDENSE` matrix) 3729 3730 Output Parameter: 3731 . X - the result matrix (dense matrix) 3732 3733 Level: developer 3734 3735 Note: 3736 The matrices `B` and `X` cannot be the same. I.e., one cannot 3737 call `MatMatSolveTranspose`(A,X,X). 3738 3739 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()` 3740 @*/ 3741 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X) 3742 { 3743 PetscFunctionBegin; 3744 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3745 PetscValidType(A, 1); 3746 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3747 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3748 PetscCheckSameComm(A, 1, B, 2); 3749 PetscCheckSameComm(A, 1, X, 3); 3750 PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3751 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); 3752 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); 3753 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); 3754 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"); 3755 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3756 MatCheckPreallocated(A, 1); 3757 3758 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3759 if (!A->ops->matsolvetranspose) { 3760 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name)); 3761 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE)); 3762 } else PetscUseTypeMethod(A, matsolvetranspose, B, X); 3763 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3764 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3765 PetscFunctionReturn(PETSC_SUCCESS); 3766 } 3767 3768 /*@ 3769 MatMatTransposeSolve - Solves A X = B^T, given a factored matrix. 3770 3771 Neighbor-wise Collective 3772 3773 Input Parameters: 3774 + A - the factored matrix 3775 - Bt - the transpose of right-hand-side matrix as a `MATDENSE` 3776 3777 Output Parameter: 3778 . X - the result matrix (dense matrix) 3779 3780 Level: developer 3781 3782 Note: 3783 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 3784 format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`. 3785 3786 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3787 @*/ 3788 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X) 3789 { 3790 PetscFunctionBegin; 3791 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3792 PetscValidType(A, 1); 3793 PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2); 3794 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3795 PetscCheckSameComm(A, 1, Bt, 2); 3796 PetscCheckSameComm(A, 1, X, 3); 3797 3798 PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3799 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); 3800 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); 3801 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"); 3802 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3803 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3804 MatCheckPreallocated(A, 1); 3805 3806 PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0)); 3807 PetscUseTypeMethod(A, mattransposesolve, Bt, X); 3808 PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0)); 3809 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3810 PetscFunctionReturn(PETSC_SUCCESS); 3811 } 3812 3813 /*@ 3814 MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or 3815 U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U, 3816 3817 Neighbor-wise Collective 3818 3819 Input Parameters: 3820 + mat - the factored matrix 3821 - b - the right-hand-side vector 3822 3823 Output Parameter: 3824 . x - the result vector 3825 3826 Level: developer 3827 3828 Notes: 3829 `MatSolve()` should be used for most applications, as it performs 3830 a forward solve followed by a backward solve. 3831 3832 The vectors `b` and `x` cannot be the same, i.e., one cannot 3833 call `MatForwardSolve`(A,x,x). 3834 3835 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3836 the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet. 3837 `MatForwardSolve()` solves U^T*D y = b, and 3838 `MatBackwardSolve()` solves U x = y. 3839 Thus they do not provide a symmetric preconditioner. 3840 3841 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()` 3842 @*/ 3843 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x) 3844 { 3845 PetscFunctionBegin; 3846 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3847 PetscValidType(mat, 1); 3848 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3849 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3850 PetscCheckSameComm(mat, 1, b, 2); 3851 PetscCheckSameComm(mat, 1, x, 3); 3852 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3853 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); 3854 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); 3855 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); 3856 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3857 MatCheckPreallocated(mat, 1); 3858 3859 PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0)); 3860 PetscUseTypeMethod(mat, forwardsolve, b, x); 3861 PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0)); 3862 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3863 PetscFunctionReturn(PETSC_SUCCESS); 3864 } 3865 3866 /*@ 3867 MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU. 3868 D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U, 3869 3870 Neighbor-wise Collective 3871 3872 Input Parameters: 3873 + mat - the factored matrix 3874 - b - the right-hand-side vector 3875 3876 Output Parameter: 3877 . x - the result vector 3878 3879 Level: developer 3880 3881 Notes: 3882 `MatSolve()` should be used for most applications, as it performs 3883 a forward solve followed by a backward solve. 3884 3885 The vectors `b` and `x` cannot be the same. I.e., one cannot 3886 call `MatBackwardSolve`(A,x,x). 3887 3888 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3889 the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet. 3890 `MatForwardSolve()` solves U^T*D y = b, and 3891 `MatBackwardSolve()` solves U x = y. 3892 Thus they do not provide a symmetric preconditioner. 3893 3894 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()` 3895 @*/ 3896 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x) 3897 { 3898 PetscFunctionBegin; 3899 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3900 PetscValidType(mat, 1); 3901 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3902 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3903 PetscCheckSameComm(mat, 1, b, 2); 3904 PetscCheckSameComm(mat, 1, x, 3); 3905 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3906 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); 3907 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); 3908 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); 3909 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3910 MatCheckPreallocated(mat, 1); 3911 3912 PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0)); 3913 PetscUseTypeMethod(mat, backwardsolve, b, x); 3914 PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0)); 3915 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3916 PetscFunctionReturn(PETSC_SUCCESS); 3917 } 3918 3919 /*@ 3920 MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix. 3921 3922 Neighbor-wise Collective 3923 3924 Input Parameters: 3925 + mat - the factored matrix 3926 . b - the right-hand-side vector 3927 - y - the vector to be added to 3928 3929 Output Parameter: 3930 . x - the result vector 3931 3932 Level: developer 3933 3934 Note: 3935 The vectors `b` and `x` cannot be the same. I.e., one cannot 3936 call `MatSolveAdd`(A,x,y,x). 3937 3938 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3939 @*/ 3940 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x) 3941 { 3942 PetscScalar one = 1.0; 3943 Vec tmp; 3944 3945 PetscFunctionBegin; 3946 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3947 PetscValidType(mat, 1); 3948 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 3949 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3950 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 3951 PetscCheckSameComm(mat, 1, b, 2); 3952 PetscCheckSameComm(mat, 1, y, 3); 3953 PetscCheckSameComm(mat, 1, x, 4); 3954 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3955 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); 3956 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); 3957 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); 3958 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); 3959 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); 3960 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3961 MatCheckPreallocated(mat, 1); 3962 3963 PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y)); 3964 if (mat->factorerrortype) { 3965 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3966 PetscCall(VecSetInf(x)); 3967 } else if (mat->ops->solveadd) { 3968 PetscUseTypeMethod(mat, solveadd, b, y, x); 3969 } else { 3970 /* do the solve then the add manually */ 3971 if (x != y) { 3972 PetscCall(MatSolve(mat, b, x)); 3973 PetscCall(VecAXPY(x, one, y)); 3974 } else { 3975 PetscCall(VecDuplicate(x, &tmp)); 3976 PetscCall(VecCopy(x, tmp)); 3977 PetscCall(MatSolve(mat, b, x)); 3978 PetscCall(VecAXPY(x, one, tmp)); 3979 PetscCall(VecDestroy(&tmp)); 3980 } 3981 } 3982 PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y)); 3983 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3984 PetscFunctionReturn(PETSC_SUCCESS); 3985 } 3986 3987 /*@ 3988 MatSolveTranspose - Solves A' x = b, given a factored matrix. 3989 3990 Neighbor-wise Collective 3991 3992 Input Parameters: 3993 + mat - the factored matrix 3994 - b - the right-hand-side vector 3995 3996 Output Parameter: 3997 . x - the result vector 3998 3999 Level: developer 4000 4001 Notes: 4002 The vectors `b` and `x` cannot be the same. I.e., one cannot 4003 call `MatSolveTranspose`(A,x,x). 4004 4005 Most users should employ the `KSP` interface for linear solvers 4006 instead of working directly with matrix algebra routines such as this. 4007 See, e.g., `KSPCreate()`. 4008 4009 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()` 4010 @*/ 4011 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x) 4012 { 4013 PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose; 4014 4015 PetscFunctionBegin; 4016 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4017 PetscValidType(mat, 1); 4018 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4019 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 4020 PetscCheckSameComm(mat, 1, b, 2); 4021 PetscCheckSameComm(mat, 1, x, 3); 4022 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4023 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); 4024 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); 4025 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4026 MatCheckPreallocated(mat, 1); 4027 PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0)); 4028 if (mat->factorerrortype) { 4029 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4030 PetscCall(VecSetInf(x)); 4031 } else { 4032 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name); 4033 PetscCall((*f)(mat, b, x)); 4034 } 4035 PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0)); 4036 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4037 PetscFunctionReturn(PETSC_SUCCESS); 4038 } 4039 4040 /*@ 4041 MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a 4042 factored matrix. 4043 4044 Neighbor-wise Collective 4045 4046 Input Parameters: 4047 + mat - the factored matrix 4048 . b - the right-hand-side vector 4049 - y - the vector to be added to 4050 4051 Output Parameter: 4052 . x - the result vector 4053 4054 Level: developer 4055 4056 Note: 4057 The vectors `b` and `x` cannot be the same. I.e., one cannot 4058 call `MatSolveTransposeAdd`(A,x,y,x). 4059 4060 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()` 4061 @*/ 4062 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x) 4063 { 4064 PetscScalar one = 1.0; 4065 Vec tmp; 4066 PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd; 4067 4068 PetscFunctionBegin; 4069 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4070 PetscValidType(mat, 1); 4071 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4072 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4073 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4074 PetscCheckSameComm(mat, 1, b, 2); 4075 PetscCheckSameComm(mat, 1, y, 3); 4076 PetscCheckSameComm(mat, 1, x, 4); 4077 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4078 PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N); 4079 PetscCheck(mat->cmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, b->map->N); 4080 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); 4081 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); 4082 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4083 MatCheckPreallocated(mat, 1); 4084 4085 PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y)); 4086 if (mat->factorerrortype) { 4087 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4088 PetscCall(VecSetInf(x)); 4089 } else if (f) { 4090 PetscCall((*f)(mat, b, y, x)); 4091 } else { 4092 /* do the solve then the add manually */ 4093 if (x != y) { 4094 PetscCall(MatSolveTranspose(mat, b, x)); 4095 PetscCall(VecAXPY(x, one, y)); 4096 } else { 4097 PetscCall(VecDuplicate(x, &tmp)); 4098 PetscCall(VecCopy(x, tmp)); 4099 PetscCall(MatSolveTranspose(mat, b, x)); 4100 PetscCall(VecAXPY(x, one, tmp)); 4101 PetscCall(VecDestroy(&tmp)); 4102 } 4103 } 4104 PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y)); 4105 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4106 PetscFunctionReturn(PETSC_SUCCESS); 4107 } 4108 4109 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 4110 /*@ 4111 MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps. 4112 4113 Neighbor-wise Collective 4114 4115 Input Parameters: 4116 + mat - the matrix 4117 . b - the right hand side 4118 . omega - the relaxation factor 4119 . flag - flag indicating the type of SOR (see below) 4120 . shift - diagonal shift 4121 . its - the number of iterations 4122 - lits - the number of local iterations 4123 4124 Output Parameter: 4125 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess) 4126 4127 SOR Flags: 4128 + `SOR_FORWARD_SWEEP` - forward SOR 4129 . `SOR_BACKWARD_SWEEP` - backward SOR 4130 . `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR) 4131 . `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR 4132 . `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR 4133 . `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR 4134 . `SOR_EISENSTAT` - SOR with Eisenstat trick 4135 . `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies 4136 upper/lower triangular part of matrix to 4137 vector (with omega) 4138 - `SOR_ZERO_INITIAL_GUESS` - zero initial guess 4139 4140 Level: developer 4141 4142 Notes: 4143 `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and 4144 `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings 4145 on each processor. 4146 4147 Application programmers will not generally use `MatSOR()` directly, 4148 but instead will employ the `KSP`/`PC` interface. 4149 4150 For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing 4151 4152 Most users should employ the `KSP` interface for linear solvers 4153 instead of working directly with matrix algebra routines such as this. 4154 See, e.g., `KSPCreate()`. 4155 4156 Vectors `x` and `b` CANNOT be the same 4157 4158 The flags are implemented as bitwise inclusive or operations. 4159 For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`) 4160 to specify a zero initial guess for SSOR. 4161 4162 Developer Notes: 4163 We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes 4164 4165 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()` 4166 @*/ 4167 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x) 4168 { 4169 PetscFunctionBegin; 4170 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4171 PetscValidType(mat, 1); 4172 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4173 PetscValidHeaderSpecific(x, VEC_CLASSID, 8); 4174 PetscCheckSameComm(mat, 1, b, 2); 4175 PetscCheckSameComm(mat, 1, x, 8); 4176 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4177 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4178 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); 4179 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); 4180 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); 4181 PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its); 4182 PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits); 4183 PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same"); 4184 4185 MatCheckPreallocated(mat, 1); 4186 PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0)); 4187 PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x); 4188 PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0)); 4189 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4190 PetscFunctionReturn(PETSC_SUCCESS); 4191 } 4192 4193 /* 4194 Default matrix copy routine. 4195 */ 4196 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str) 4197 { 4198 PetscInt i, rstart = 0, rend = 0, nz; 4199 const PetscInt *cwork; 4200 const PetscScalar *vwork; 4201 4202 PetscFunctionBegin; 4203 if (B->assembled) PetscCall(MatZeroEntries(B)); 4204 if (str == SAME_NONZERO_PATTERN) { 4205 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 4206 for (i = rstart; i < rend; i++) { 4207 PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork)); 4208 PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES)); 4209 PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork)); 4210 } 4211 } else { 4212 PetscCall(MatAYPX(B, 0.0, A, str)); 4213 } 4214 PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 4215 PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 4216 PetscFunctionReturn(PETSC_SUCCESS); 4217 } 4218 4219 /*@ 4220 MatCopy - Copies a matrix to another matrix. 4221 4222 Collective 4223 4224 Input Parameters: 4225 + A - the matrix 4226 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN` 4227 4228 Output Parameter: 4229 . B - where the copy is put 4230 4231 Level: intermediate 4232 4233 Notes: 4234 If you use `SAME_NONZERO_PATTERN` then the two matrices must have the same nonzero pattern or the routine will crash. 4235 4236 `MatCopy()` copies the matrix entries of a matrix to another existing 4237 matrix (after first zeroing the second matrix). A related routine is 4238 `MatConvert()`, which first creates a new matrix and then copies the data. 4239 4240 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()` 4241 @*/ 4242 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str) 4243 { 4244 PetscInt i; 4245 4246 PetscFunctionBegin; 4247 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 4248 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 4249 PetscValidType(A, 1); 4250 PetscValidType(B, 2); 4251 PetscCheckSameComm(A, 1, B, 2); 4252 MatCheckPreallocated(B, 2); 4253 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4254 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4255 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, 4256 A->cmap->N, B->cmap->N); 4257 MatCheckPreallocated(A, 1); 4258 if (A == B) PetscFunctionReturn(PETSC_SUCCESS); 4259 4260 PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0)); 4261 if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str); 4262 else PetscCall(MatCopy_Basic(A, B, str)); 4263 4264 B->stencil.dim = A->stencil.dim; 4265 B->stencil.noc = A->stencil.noc; 4266 for (i = 0; i <= A->stencil.dim; i++) { 4267 B->stencil.dims[i] = A->stencil.dims[i]; 4268 B->stencil.starts[i] = A->stencil.starts[i]; 4269 } 4270 4271 PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0)); 4272 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4273 PetscFunctionReturn(PETSC_SUCCESS); 4274 } 4275 4276 /*@C 4277 MatConvert - Converts a matrix to another matrix, either of the same 4278 or different type. 4279 4280 Collective 4281 4282 Input Parameters: 4283 + mat - the matrix 4284 . newtype - new matrix type. Use `MATSAME` to create a new matrix of the 4285 same type as the original matrix. 4286 - reuse - denotes if the destination matrix is to be created or reused. 4287 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 4288 `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). 4289 4290 Output Parameter: 4291 . M - pointer to place new matrix 4292 4293 Level: intermediate 4294 4295 Notes: 4296 `MatConvert()` first creates a new matrix and then copies the data from 4297 the first matrix. A related routine is `MatCopy()`, which copies the matrix 4298 entries of one matrix to another already existing matrix context. 4299 4300 Cannot be used to convert a sequential matrix to parallel or parallel to sequential, 4301 the MPI communicator of the generated matrix is always the same as the communicator 4302 of the input matrix. 4303 4304 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 4305 @*/ 4306 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M) 4307 { 4308 PetscBool sametype, issame, flg; 4309 PetscBool3 issymmetric, ishermitian; 4310 char convname[256], mtype[256]; 4311 Mat B; 4312 4313 PetscFunctionBegin; 4314 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4315 PetscValidType(mat, 1); 4316 PetscValidPointer(M, 4); 4317 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4318 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4319 MatCheckPreallocated(mat, 1); 4320 4321 PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg)); 4322 if (flg) newtype = mtype; 4323 4324 PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype)); 4325 PetscCall(PetscStrcmp(newtype, "same", &issame)); 4326 PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix"); 4327 PetscCheck(!(reuse == MAT_REUSE_MATRIX) || !(mat == *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX"); 4328 4329 if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) { 4330 PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4331 PetscFunctionReturn(PETSC_SUCCESS); 4332 } 4333 4334 /* Cache Mat options because some converters use MatHeaderReplace */ 4335 issymmetric = mat->symmetric; 4336 ishermitian = mat->hermitian; 4337 4338 if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) { 4339 PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4340 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4341 } else { 4342 PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL; 4343 const char *prefix[3] = {"seq", "mpi", ""}; 4344 PetscInt i; 4345 /* 4346 Order of precedence: 4347 0) See if newtype is a superclass of the current matrix. 4348 1) See if a specialized converter is known to the current matrix. 4349 2) See if a specialized converter is known to the desired matrix class. 4350 3) See if a good general converter is registered for the desired class 4351 (as of 6/27/03 only MATMPIADJ falls into this category). 4352 4) See if a good general converter is known for the current matrix. 4353 5) Use a really basic converter. 4354 */ 4355 4356 /* 0) See if newtype is a superclass of the current matrix. 4357 i.e mat is mpiaij and newtype is aij */ 4358 for (i = 0; i < 2; i++) { 4359 PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname))); 4360 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4361 PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg)); 4362 PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg)); 4363 if (flg) { 4364 if (reuse == MAT_INPLACE_MATRIX) { 4365 PetscCall(PetscInfo(mat, "Early return\n")); 4366 PetscFunctionReturn(PETSC_SUCCESS); 4367 } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) { 4368 PetscCall(PetscInfo(mat, "Calling MatDuplicate\n")); 4369 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4370 PetscFunctionReturn(PETSC_SUCCESS); 4371 } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) { 4372 PetscCall(PetscInfo(mat, "Calling MatCopy\n")); 4373 PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN)); 4374 PetscFunctionReturn(PETSC_SUCCESS); 4375 } 4376 } 4377 } 4378 /* 1) See if a specialized converter is known to the current matrix and the desired class */ 4379 for (i = 0; i < 3; i++) { 4380 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4381 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4382 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4383 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4384 PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname))); 4385 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4386 PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv)); 4387 PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv)); 4388 if (conv) goto foundconv; 4389 } 4390 4391 /* 2) See if a specialized converter is known to the desired matrix class. */ 4392 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B)); 4393 PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 4394 PetscCall(MatSetType(B, newtype)); 4395 for (i = 0; i < 3; i++) { 4396 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4397 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4398 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4399 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4400 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4401 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4402 PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv)); 4403 PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv)); 4404 if (conv) { 4405 PetscCall(MatDestroy(&B)); 4406 goto foundconv; 4407 } 4408 } 4409 4410 /* 3) See if a good general converter is registered for the desired class */ 4411 conv = B->ops->convertfrom; 4412 PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv)); 4413 PetscCall(MatDestroy(&B)); 4414 if (conv) goto foundconv; 4415 4416 /* 4) See if a good general converter is known for the current matrix */ 4417 if (mat->ops->convert) conv = mat->ops->convert; 4418 PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv)); 4419 if (conv) goto foundconv; 4420 4421 /* 5) Use a really basic converter. */ 4422 PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n")); 4423 conv = MatConvert_Basic; 4424 4425 foundconv: 4426 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4427 PetscCall((*conv)(mat, newtype, reuse, M)); 4428 if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) { 4429 /* the block sizes must be same if the mappings are copied over */ 4430 (*M)->rmap->bs = mat->rmap->bs; 4431 (*M)->cmap->bs = mat->cmap->bs; 4432 PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping)); 4433 PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping)); 4434 (*M)->rmap->mapping = mat->rmap->mapping; 4435 (*M)->cmap->mapping = mat->cmap->mapping; 4436 } 4437 (*M)->stencil.dim = mat->stencil.dim; 4438 (*M)->stencil.noc = mat->stencil.noc; 4439 for (i = 0; i <= mat->stencil.dim; i++) { 4440 (*M)->stencil.dims[i] = mat->stencil.dims[i]; 4441 (*M)->stencil.starts[i] = mat->stencil.starts[i]; 4442 } 4443 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4444 } 4445 PetscCall(PetscObjectStateIncrease((PetscObject)*M)); 4446 4447 /* Copy Mat options */ 4448 if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE)); 4449 else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE)); 4450 if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE)); 4451 else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE)); 4452 PetscFunctionReturn(PETSC_SUCCESS); 4453 } 4454 4455 /*@C 4456 MatFactorGetSolverType - Returns name of the package providing the factorization routines 4457 4458 Not Collective 4459 4460 Input Parameter: 4461 . mat - the matrix, must be a factored matrix 4462 4463 Output Parameter: 4464 . type - the string name of the package (do not free this string) 4465 4466 Level: intermediate 4467 4468 Fortran Notes: 4469 Pass in an empty string and the package name will be copied into it. Make sure the string is long enough. 4470 4471 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()` 4472 @*/ 4473 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type) 4474 { 4475 PetscErrorCode (*conv)(Mat, MatSolverType *); 4476 4477 PetscFunctionBegin; 4478 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4479 PetscValidType(mat, 1); 4480 PetscValidPointer(type, 2); 4481 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 4482 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv)); 4483 if (conv) PetscCall((*conv)(mat, type)); 4484 else *type = MATSOLVERPETSC; 4485 PetscFunctionReturn(PETSC_SUCCESS); 4486 } 4487 4488 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType; 4489 struct _MatSolverTypeForSpecifcType { 4490 MatType mtype; 4491 /* no entry for MAT_FACTOR_NONE */ 4492 PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *); 4493 MatSolverTypeForSpecifcType next; 4494 }; 4495 4496 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder; 4497 struct _MatSolverTypeHolder { 4498 char *name; 4499 MatSolverTypeForSpecifcType handlers; 4500 MatSolverTypeHolder next; 4501 }; 4502 4503 static MatSolverTypeHolder MatSolverTypeHolders = NULL; 4504 4505 /*@C 4506 MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type 4507 4508 Input Parameters: 4509 + package - name of the package, for example petsc or superlu 4510 . mtype - the matrix type that works with this package 4511 . ftype - the type of factorization supported by the package 4512 - createfactor - routine that will create the factored matrix ready to be used 4513 4514 Level: developer 4515 4516 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()` 4517 @*/ 4518 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *)) 4519 { 4520 MatSolverTypeHolder next = MatSolverTypeHolders, prev = NULL; 4521 PetscBool flg; 4522 MatSolverTypeForSpecifcType inext, iprev = NULL; 4523 4524 PetscFunctionBegin; 4525 PetscCall(MatInitializePackage()); 4526 if (!next) { 4527 PetscCall(PetscNew(&MatSolverTypeHolders)); 4528 PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name)); 4529 PetscCall(PetscNew(&MatSolverTypeHolders->handlers)); 4530 PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype)); 4531 MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor; 4532 PetscFunctionReturn(PETSC_SUCCESS); 4533 } 4534 while (next) { 4535 PetscCall(PetscStrcasecmp(package, next->name, &flg)); 4536 if (flg) { 4537 PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers"); 4538 inext = next->handlers; 4539 while (inext) { 4540 PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg)); 4541 if (flg) { 4542 inext->createfactor[(int)ftype - 1] = createfactor; 4543 PetscFunctionReturn(PETSC_SUCCESS); 4544 } 4545 iprev = inext; 4546 inext = inext->next; 4547 } 4548 PetscCall(PetscNew(&iprev->next)); 4549 PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype)); 4550 iprev->next->createfactor[(int)ftype - 1] = createfactor; 4551 PetscFunctionReturn(PETSC_SUCCESS); 4552 } 4553 prev = next; 4554 next = next->next; 4555 } 4556 PetscCall(PetscNew(&prev->next)); 4557 PetscCall(PetscStrallocpy(package, &prev->next->name)); 4558 PetscCall(PetscNew(&prev->next->handlers)); 4559 PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype)); 4560 prev->next->handlers->createfactor[(int)ftype - 1] = createfactor; 4561 PetscFunctionReturn(PETSC_SUCCESS); 4562 } 4563 4564 /*@C 4565 MatSolverTypeGet - Gets the function that creates the factor matrix if it exist 4566 4567 Input Parameters: 4568 + type - name of the package, for example petsc or superlu 4569 . ftype - the type of factorization supported by the type 4570 - mtype - the matrix type that works with this type 4571 4572 Output Parameters: 4573 + foundtype - `PETSC_TRUE` if the type was registered 4574 . foundmtype - `PETSC_TRUE` if the type supports the requested mtype 4575 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found 4576 4577 Level: developer 4578 4579 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()` 4580 @*/ 4581 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *)) 4582 { 4583 MatSolverTypeHolder next = MatSolverTypeHolders; 4584 PetscBool flg; 4585 MatSolverTypeForSpecifcType inext; 4586 4587 PetscFunctionBegin; 4588 if (foundtype) *foundtype = PETSC_FALSE; 4589 if (foundmtype) *foundmtype = PETSC_FALSE; 4590 if (createfactor) *createfactor = NULL; 4591 4592 if (type) { 4593 while (next) { 4594 PetscCall(PetscStrcasecmp(type, next->name, &flg)); 4595 if (flg) { 4596 if (foundtype) *foundtype = PETSC_TRUE; 4597 inext = next->handlers; 4598 while (inext) { 4599 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4600 if (flg) { 4601 if (foundmtype) *foundmtype = PETSC_TRUE; 4602 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4603 PetscFunctionReturn(PETSC_SUCCESS); 4604 } 4605 inext = inext->next; 4606 } 4607 } 4608 next = next->next; 4609 } 4610 } else { 4611 while (next) { 4612 inext = next->handlers; 4613 while (inext) { 4614 PetscCall(PetscStrcmp(mtype, inext->mtype, &flg)); 4615 if (flg && inext->createfactor[(int)ftype - 1]) { 4616 if (foundtype) *foundtype = PETSC_TRUE; 4617 if (foundmtype) *foundmtype = PETSC_TRUE; 4618 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4619 PetscFunctionReturn(PETSC_SUCCESS); 4620 } 4621 inext = inext->next; 4622 } 4623 next = next->next; 4624 } 4625 /* try with base classes inext->mtype */ 4626 next = MatSolverTypeHolders; 4627 while (next) { 4628 inext = next->handlers; 4629 while (inext) { 4630 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4631 if (flg && inext->createfactor[(int)ftype - 1]) { 4632 if (foundtype) *foundtype = PETSC_TRUE; 4633 if (foundmtype) *foundmtype = PETSC_TRUE; 4634 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4635 PetscFunctionReturn(PETSC_SUCCESS); 4636 } 4637 inext = inext->next; 4638 } 4639 next = next->next; 4640 } 4641 } 4642 PetscFunctionReturn(PETSC_SUCCESS); 4643 } 4644 4645 PetscErrorCode MatSolverTypeDestroy(void) 4646 { 4647 MatSolverTypeHolder next = MatSolverTypeHolders, prev; 4648 MatSolverTypeForSpecifcType inext, iprev; 4649 4650 PetscFunctionBegin; 4651 while (next) { 4652 PetscCall(PetscFree(next->name)); 4653 inext = next->handlers; 4654 while (inext) { 4655 PetscCall(PetscFree(inext->mtype)); 4656 iprev = inext; 4657 inext = inext->next; 4658 PetscCall(PetscFree(iprev)); 4659 } 4660 prev = next; 4661 next = next->next; 4662 PetscCall(PetscFree(prev)); 4663 } 4664 MatSolverTypeHolders = NULL; 4665 PetscFunctionReturn(PETSC_SUCCESS); 4666 } 4667 4668 /*@C 4669 MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4670 4671 Logically Collective 4672 4673 Input Parameter: 4674 . mat - the matrix 4675 4676 Output Parameter: 4677 . flg - `PETSC_TRUE` if uses the ordering 4678 4679 Level: developer 4680 4681 Note: 4682 Most internal PETSc factorizations use the ordering passed to the factorization routine but external 4683 packages do not, thus we want to skip generating the ordering when it is not needed or used. 4684 4685 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4686 @*/ 4687 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg) 4688 { 4689 PetscFunctionBegin; 4690 *flg = mat->canuseordering; 4691 PetscFunctionReturn(PETSC_SUCCESS); 4692 } 4693 4694 /*@C 4695 MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object 4696 4697 Logically Collective 4698 4699 Input Parameters: 4700 + mat - the matrix obtained with `MatGetFactor()` 4701 - ftype - the factorization type to be used 4702 4703 Output Parameter: 4704 . otype - the preferred ordering type 4705 4706 Level: developer 4707 4708 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4709 @*/ 4710 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype) 4711 { 4712 PetscFunctionBegin; 4713 *otype = mat->preferredordering[ftype]; 4714 PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering"); 4715 PetscFunctionReturn(PETSC_SUCCESS); 4716 } 4717 4718 /*@C 4719 MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic() 4720 4721 Collective 4722 4723 Input Parameters: 4724 + mat - the matrix 4725 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4726 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4727 4728 Output Parameter: 4729 . f - the factor matrix used with MatXXFactorSymbolic() calls. Can be `NULL` in some cases, see notes below. 4730 4731 Options Database Key: 4732 . -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory. 4733 One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices. 4734 4735 Level: intermediate 4736 4737 Notes: 4738 The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization 4739 types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime. 4740 4741 Users usually access the factorization solvers via `KSP` 4742 4743 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4744 such as pastix, superlu, mumps etc. 4745 4746 PETSc must have been ./configure to use the external solver, using the option --download-package 4747 4748 Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption 4749 where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set 4750 call `MatSetOptionsPrefixFactor()` on the originating matrix or `MatSetOptionsPrefix()` on the resulting factor matrix. 4751 4752 Developer Notes: 4753 This should actually be called `MatCreateFactor()` since it creates a new factor object 4754 4755 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, 4756 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4757 @*/ 4758 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f) 4759 { 4760 PetscBool foundtype, foundmtype; 4761 PetscErrorCode (*conv)(Mat, MatFactorType, Mat *); 4762 4763 PetscFunctionBegin; 4764 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4765 PetscValidType(mat, 1); 4766 4767 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4768 MatCheckPreallocated(mat, 1); 4769 4770 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv)); 4771 if (!foundtype) { 4772 if (type) { 4773 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], 4774 ((PetscObject)mat)->type_name, type); 4775 } else { 4776 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); 4777 } 4778 } 4779 PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name); 4780 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); 4781 4782 PetscCall((*conv)(mat, ftype, f)); 4783 if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix)); 4784 PetscFunctionReturn(PETSC_SUCCESS); 4785 } 4786 4787 /*@C 4788 MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type 4789 4790 Not Collective 4791 4792 Input Parameters: 4793 + mat - the matrix 4794 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4795 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4796 4797 Output Parameter: 4798 . flg - PETSC_TRUE if the factorization is available 4799 4800 Level: intermediate 4801 4802 Notes: 4803 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4804 such as pastix, superlu, mumps etc. 4805 4806 PETSc must have been ./configure to use the external solver, using the option --download-package 4807 4808 Developer Notes: 4809 This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object 4810 4811 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatSolverTypeRegister()`, 4812 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4813 @*/ 4814 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg) 4815 { 4816 PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *); 4817 4818 PetscFunctionBegin; 4819 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4820 PetscValidType(mat, 1); 4821 PetscValidBoolPointer(flg, 4); 4822 4823 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4824 MatCheckPreallocated(mat, 1); 4825 4826 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv)); 4827 *flg = gconv ? PETSC_TRUE : PETSC_FALSE; 4828 PetscFunctionReturn(PETSC_SUCCESS); 4829 } 4830 4831 /*@ 4832 MatDuplicate - Duplicates a matrix including the non-zero structure. 4833 4834 Collective 4835 4836 Input Parameters: 4837 + mat - the matrix 4838 - op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`. 4839 See the manual page for `MatDuplicateOption()` for an explanation of these options. 4840 4841 Output Parameter: 4842 . M - pointer to place new matrix 4843 4844 Level: intermediate 4845 4846 Notes: 4847 You cannot change the nonzero pattern for the parent or child matrix if you use `MAT_SHARE_NONZERO_PATTERN`. 4848 4849 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. 4850 4851 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 4852 is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated. 4853 User should not use `MatDuplicate()` to create new matrix M if M is intended to be reused as the product of matrix operation. 4854 4855 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption` 4856 @*/ 4857 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M) 4858 { 4859 Mat B; 4860 VecType vtype; 4861 PetscInt i; 4862 PetscObject dm, container_h, container_d; 4863 void (*viewf)(void); 4864 4865 PetscFunctionBegin; 4866 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4867 PetscValidType(mat, 1); 4868 PetscValidPointer(M, 3); 4869 PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix"); 4870 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4871 MatCheckPreallocated(mat, 1); 4872 4873 *M = NULL; 4874 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4875 PetscUseTypeMethod(mat, duplicate, op, M); 4876 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4877 B = *M; 4878 4879 PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf)); 4880 if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf)); 4881 PetscCall(MatGetVecType(mat, &vtype)); 4882 PetscCall(MatSetVecType(B, vtype)); 4883 4884 B->stencil.dim = mat->stencil.dim; 4885 B->stencil.noc = mat->stencil.noc; 4886 for (i = 0; i <= mat->stencil.dim; i++) { 4887 B->stencil.dims[i] = mat->stencil.dims[i]; 4888 B->stencil.starts[i] = mat->stencil.starts[i]; 4889 } 4890 4891 B->nooffproczerorows = mat->nooffproczerorows; 4892 B->nooffprocentries = mat->nooffprocentries; 4893 4894 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm)); 4895 if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm)); 4896 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h)); 4897 if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h)); 4898 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d)); 4899 if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d)); 4900 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4901 PetscFunctionReturn(PETSC_SUCCESS); 4902 } 4903 4904 /*@ 4905 MatGetDiagonal - Gets the diagonal of a matrix as a `Vec` 4906 4907 Logically Collective 4908 4909 Input Parameter: 4910 . mat - the matrix 4911 4912 Output Parameter: 4913 . v - the diagonal of the matrix 4914 4915 Level: intermediate 4916 4917 Note: 4918 If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries 4919 of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v` 4920 is larger than `ndiag`, the values of the remaining entries are unspecified. 4921 4922 Currently only correct in parallel for square matrices. 4923 4924 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()` 4925 @*/ 4926 PetscErrorCode MatGetDiagonal(Mat mat, Vec v) 4927 { 4928 PetscFunctionBegin; 4929 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4930 PetscValidType(mat, 1); 4931 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4932 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4933 MatCheckPreallocated(mat, 1); 4934 if (PetscDefined(USE_DEBUG)) { 4935 PetscInt nv, row, col, ndiag; 4936 4937 PetscCall(VecGetLocalSize(v, &nv)); 4938 PetscCall(MatGetLocalSize(mat, &row, &col)); 4939 ndiag = PetscMin(row, col); 4940 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); 4941 } 4942 4943 PetscUseTypeMethod(mat, getdiagonal, v); 4944 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4945 PetscFunctionReturn(PETSC_SUCCESS); 4946 } 4947 4948 /*@C 4949 MatGetRowMin - Gets the minimum value (of the real part) of each 4950 row of the matrix 4951 4952 Logically Collective 4953 4954 Input Parameter: 4955 . mat - the matrix 4956 4957 Output Parameters: 4958 + v - the vector for storing the maximums 4959 - idx - the indices of the column found for each row (optional) 4960 4961 Level: intermediate 4962 4963 Note: 4964 The result of this call are the same as if one converted the matrix to dense format 4965 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 4966 4967 This code is only implemented for a couple of matrix formats. 4968 4969 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, 4970 `MatGetRowMax()` 4971 @*/ 4972 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[]) 4973 { 4974 PetscFunctionBegin; 4975 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4976 PetscValidType(mat, 1); 4977 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4978 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4979 4980 if (!mat->cmap->N) { 4981 PetscCall(VecSet(v, PETSC_MAX_REAL)); 4982 if (idx) { 4983 PetscInt i, m = mat->rmap->n; 4984 for (i = 0; i < m; i++) idx[i] = -1; 4985 } 4986 } else { 4987 MatCheckPreallocated(mat, 1); 4988 } 4989 PetscUseTypeMethod(mat, getrowmin, v, idx); 4990 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4991 PetscFunctionReturn(PETSC_SUCCESS); 4992 } 4993 4994 /*@C 4995 MatGetRowMinAbs - Gets the minimum value (in absolute value) of each 4996 row of the matrix 4997 4998 Logically Collective 4999 5000 Input Parameter: 5001 . mat - the matrix 5002 5003 Output Parameters: 5004 + v - the vector for storing the minimums 5005 - idx - the indices of the column found for each row (or `NULL` if not needed) 5006 5007 Level: intermediate 5008 5009 Notes: 5010 if a row is completely empty or has only 0.0 values then the idx[] value for that 5011 row is 0 (the first column). 5012 5013 This code is only implemented for a couple of matrix formats. 5014 5015 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()` 5016 @*/ 5017 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[]) 5018 { 5019 PetscFunctionBegin; 5020 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5021 PetscValidType(mat, 1); 5022 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5023 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5024 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5025 5026 if (!mat->cmap->N) { 5027 PetscCall(VecSet(v, 0.0)); 5028 if (idx) { 5029 PetscInt i, m = mat->rmap->n; 5030 for (i = 0; i < m; i++) idx[i] = -1; 5031 } 5032 } else { 5033 MatCheckPreallocated(mat, 1); 5034 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5035 PetscUseTypeMethod(mat, getrowminabs, v, idx); 5036 } 5037 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5038 PetscFunctionReturn(PETSC_SUCCESS); 5039 } 5040 5041 /*@C 5042 MatGetRowMax - Gets the maximum value (of the real part) of each 5043 row of the matrix 5044 5045 Logically Collective 5046 5047 Input Parameter: 5048 . mat - the matrix 5049 5050 Output Parameters: 5051 + v - the vector for storing the maximums 5052 - idx - the indices of the column found for each row (optional) 5053 5054 Level: intermediate 5055 5056 Notes: 5057 The result of this call are the same as if one converted the matrix to dense format 5058 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5059 5060 This code is only implemented for a couple of matrix formats. 5061 5062 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5063 @*/ 5064 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[]) 5065 { 5066 PetscFunctionBegin; 5067 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5068 PetscValidType(mat, 1); 5069 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5070 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5071 5072 if (!mat->cmap->N) { 5073 PetscCall(VecSet(v, PETSC_MIN_REAL)); 5074 if (idx) { 5075 PetscInt i, m = mat->rmap->n; 5076 for (i = 0; i < m; i++) idx[i] = -1; 5077 } 5078 } else { 5079 MatCheckPreallocated(mat, 1); 5080 PetscUseTypeMethod(mat, getrowmax, v, idx); 5081 } 5082 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5083 PetscFunctionReturn(PETSC_SUCCESS); 5084 } 5085 5086 /*@C 5087 MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each 5088 row of the matrix 5089 5090 Logically Collective 5091 5092 Input Parameter: 5093 . mat - the matrix 5094 5095 Output Parameters: 5096 + v - the vector for storing the maximums 5097 - idx - the indices of the column found for each row (or `NULL` if not needed) 5098 5099 Level: intermediate 5100 5101 Notes: 5102 if a row is completely empty or has only 0.0 values then the idx[] value for that 5103 row is 0 (the first column). 5104 5105 This code is only implemented for a couple of matrix formats. 5106 5107 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5108 @*/ 5109 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[]) 5110 { 5111 PetscFunctionBegin; 5112 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5113 PetscValidType(mat, 1); 5114 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5115 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5116 5117 if (!mat->cmap->N) { 5118 PetscCall(VecSet(v, 0.0)); 5119 if (idx) { 5120 PetscInt i, m = mat->rmap->n; 5121 for (i = 0; i < m; i++) idx[i] = -1; 5122 } 5123 } else { 5124 MatCheckPreallocated(mat, 1); 5125 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5126 PetscUseTypeMethod(mat, getrowmaxabs, v, idx); 5127 } 5128 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5129 PetscFunctionReturn(PETSC_SUCCESS); 5130 } 5131 5132 /*@ 5133 MatGetRowSum - Gets the sum of each row of the matrix 5134 5135 Logically or Neighborhood Collective 5136 5137 Input Parameter: 5138 . mat - the matrix 5139 5140 Output Parameter: 5141 . v - the vector for storing the sum of rows 5142 5143 Level: intermediate 5144 5145 Notes: 5146 This code is slow since it is not currently specialized for different formats 5147 5148 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()` 5149 @*/ 5150 PetscErrorCode MatGetRowSum(Mat mat, Vec v) 5151 { 5152 Vec ones; 5153 5154 PetscFunctionBegin; 5155 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5156 PetscValidType(mat, 1); 5157 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5158 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5159 MatCheckPreallocated(mat, 1); 5160 PetscCall(MatCreateVecs(mat, &ones, NULL)); 5161 PetscCall(VecSet(ones, 1.)); 5162 PetscCall(MatMult(mat, ones, v)); 5163 PetscCall(VecDestroy(&ones)); 5164 PetscFunctionReturn(PETSC_SUCCESS); 5165 } 5166 5167 /*@ 5168 MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) 5169 when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B) 5170 5171 Collective 5172 5173 Input Parameter: 5174 . mat - the matrix to provide the transpose 5175 5176 Output Parameter: 5177 . 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 5178 5179 Level: advanced 5180 5181 Note: 5182 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 5183 routine allows bypassing that call. 5184 5185 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5186 @*/ 5187 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B) 5188 { 5189 PetscContainer rB = NULL; 5190 MatParentState *rb = NULL; 5191 5192 PetscFunctionBegin; 5193 PetscCall(PetscNew(&rb)); 5194 rb->id = ((PetscObject)mat)->id; 5195 rb->state = 0; 5196 PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate)); 5197 PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB)); 5198 PetscCall(PetscContainerSetPointer(rB, rb)); 5199 PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault)); 5200 PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB)); 5201 PetscCall(PetscObjectDereference((PetscObject)rB)); 5202 PetscFunctionReturn(PETSC_SUCCESS); 5203 } 5204 5205 /*@ 5206 MatTranspose - Computes an in-place or out-of-place transpose of a matrix. 5207 5208 Collective 5209 5210 Input Parameters: 5211 + mat - the matrix to transpose 5212 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5213 5214 Output Parameter: 5215 . B - the transpose 5216 5217 Level: intermediate 5218 5219 Notes: 5220 If you use `MAT_INPLACE_MATRIX` then you must pass in &mat for B 5221 5222 `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 5223 transpose, call `MatTransposeSetPrecursor`(mat,B) before calling this routine. 5224 5225 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. 5226 5227 Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed. 5228 5229 If mat is unchanged from the last call this function returns immediately without recomputing the result 5230 5231 If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()` 5232 5233 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`, 5234 `MatTransposeSymbolic()`, `MatCreateTranspose()` 5235 @*/ 5236 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B) 5237 { 5238 PetscContainer rB = NULL; 5239 MatParentState *rb = NULL; 5240 5241 PetscFunctionBegin; 5242 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5243 PetscValidType(mat, 1); 5244 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5245 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5246 PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first"); 5247 PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX"); 5248 MatCheckPreallocated(mat, 1); 5249 if (reuse == MAT_REUSE_MATRIX) { 5250 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5251 PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor()."); 5252 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5253 PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5254 if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS); 5255 } 5256 5257 PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0)); 5258 if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) { 5259 PetscUseTypeMethod(mat, transpose, reuse, B); 5260 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5261 } 5262 PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0)); 5263 5264 if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B)); 5265 if (reuse != MAT_INPLACE_MATRIX) { 5266 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5267 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5268 rb->state = ((PetscObject)mat)->state; 5269 rb->nonzerostate = mat->nonzerostate; 5270 } 5271 PetscFunctionReturn(PETSC_SUCCESS); 5272 } 5273 5274 /*@ 5275 MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix. 5276 5277 Collective 5278 5279 Input Parameter: 5280 . A - the matrix to transpose 5281 5282 Output Parameter: 5283 . 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 5284 numerical portion. 5285 5286 Level: intermediate 5287 5288 Note: 5289 This is not supported for many matrix types, use `MatTranspose()` in those cases 5290 5291 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5292 @*/ 5293 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B) 5294 { 5295 PetscFunctionBegin; 5296 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5297 PetscValidType(A, 1); 5298 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5299 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5300 PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0)); 5301 PetscUseTypeMethod(A, transposesymbolic, B); 5302 PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0)); 5303 5304 PetscCall(MatTransposeSetPrecursor(A, *B)); 5305 PetscFunctionReturn(PETSC_SUCCESS); 5306 } 5307 5308 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B) 5309 { 5310 PetscContainer rB; 5311 MatParentState *rb; 5312 5313 PetscFunctionBegin; 5314 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5315 PetscValidType(A, 1); 5316 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5317 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5318 PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB)); 5319 PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()"); 5320 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5321 PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5322 PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure"); 5323 PetscFunctionReturn(PETSC_SUCCESS); 5324 } 5325 5326 /*@ 5327 MatIsTranspose - Test whether a matrix is another one's transpose, 5328 or its own, in which case it tests symmetry. 5329 5330 Collective 5331 5332 Input Parameters: 5333 + A - the matrix to test 5334 . B - the matrix to test against, this can equal the first parameter 5335 - tol - tolerance, differences between entries smaller than this are counted as zero 5336 5337 Output Parameter: 5338 . flg - the result 5339 5340 Level: intermediate 5341 5342 Notes: 5343 Only available for `MATAIJ` matrices. 5344 5345 The sequential algorithm has a running time of the order of the number of nonzeros; the parallel 5346 test involves parallel copies of the block-offdiagonal parts of the matrix. 5347 5348 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()` 5349 @*/ 5350 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5351 { 5352 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5353 5354 PetscFunctionBegin; 5355 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5356 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5357 PetscValidBoolPointer(flg, 4); 5358 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f)); 5359 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g)); 5360 *flg = PETSC_FALSE; 5361 if (f && g) { 5362 PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test"); 5363 PetscCall((*f)(A, B, tol, flg)); 5364 } else { 5365 MatType mattype; 5366 5367 PetscCall(MatGetType(f ? B : A, &mattype)); 5368 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype); 5369 } 5370 PetscFunctionReturn(PETSC_SUCCESS); 5371 } 5372 5373 /*@ 5374 MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate. 5375 5376 Collective 5377 5378 Input Parameters: 5379 + mat - the matrix to transpose and complex conjugate 5380 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5381 5382 Output Parameter: 5383 . B - the Hermitian transpose 5384 5385 Level: intermediate 5386 5387 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse` 5388 @*/ 5389 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B) 5390 { 5391 PetscFunctionBegin; 5392 PetscCall(MatTranspose(mat, reuse, B)); 5393 #if defined(PETSC_USE_COMPLEX) 5394 PetscCall(MatConjugate(*B)); 5395 #endif 5396 PetscFunctionReturn(PETSC_SUCCESS); 5397 } 5398 5399 /*@ 5400 MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose, 5401 5402 Collective 5403 5404 Input Parameters: 5405 + A - the matrix to test 5406 . B - the matrix to test against, this can equal the first parameter 5407 - tol - tolerance, differences between entries smaller than this are counted as zero 5408 5409 Output Parameter: 5410 . flg - the result 5411 5412 Level: intermediate 5413 5414 Notes: 5415 Only available for `MATAIJ` matrices. 5416 5417 The sequential algorithm 5418 has a running time of the order of the number of nonzeros; the parallel 5419 test involves parallel copies of the block-offdiagonal parts of the matrix. 5420 5421 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()` 5422 @*/ 5423 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5424 { 5425 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5426 5427 PetscFunctionBegin; 5428 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5429 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5430 PetscValidBoolPointer(flg, 4); 5431 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f)); 5432 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g)); 5433 if (f && g) { 5434 PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test"); 5435 PetscCall((*f)(A, B, tol, flg)); 5436 } 5437 PetscFunctionReturn(PETSC_SUCCESS); 5438 } 5439 5440 /*@ 5441 MatPermute - Creates a new matrix with rows and columns permuted from the 5442 original. 5443 5444 Collective 5445 5446 Input Parameters: 5447 + mat - the matrix to permute 5448 . row - row permutation, each processor supplies only the permutation for its rows 5449 - col - column permutation, each processor supplies only the permutation for its columns 5450 5451 Output Parameter: 5452 . B - the permuted matrix 5453 5454 Level: advanced 5455 5456 Note: 5457 The index sets map from row/col of permuted matrix to row/col of original matrix. 5458 The index sets should be on the same communicator as mat and have the same local sizes. 5459 5460 Developer Notes: 5461 If you want to implement `MatPermute()` for a matrix type, and your approach doesn't 5462 exploit the fact that row and col are permutations, consider implementing the 5463 more general `MatCreateSubMatrix()` instead. 5464 5465 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()` 5466 @*/ 5467 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B) 5468 { 5469 PetscFunctionBegin; 5470 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5471 PetscValidType(mat, 1); 5472 PetscValidHeaderSpecific(row, IS_CLASSID, 2); 5473 PetscValidHeaderSpecific(col, IS_CLASSID, 3); 5474 PetscValidPointer(B, 4); 5475 PetscCheckSameComm(mat, 1, row, 2); 5476 if (row != col) PetscCheckSameComm(row, 2, col, 3); 5477 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5478 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5479 PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name); 5480 MatCheckPreallocated(mat, 1); 5481 5482 if (mat->ops->permute) { 5483 PetscUseTypeMethod(mat, permute, row, col, B); 5484 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5485 } else { 5486 PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B)); 5487 } 5488 PetscFunctionReturn(PETSC_SUCCESS); 5489 } 5490 5491 /*@ 5492 MatEqual - Compares two matrices. 5493 5494 Collective 5495 5496 Input Parameters: 5497 + A - the first matrix 5498 - B - the second matrix 5499 5500 Output Parameter: 5501 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise. 5502 5503 Level: intermediate 5504 5505 .seealso: [](ch_matrices), `Mat` 5506 @*/ 5507 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg) 5508 { 5509 PetscFunctionBegin; 5510 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5511 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5512 PetscValidType(A, 1); 5513 PetscValidType(B, 2); 5514 PetscValidBoolPointer(flg, 3); 5515 PetscCheckSameComm(A, 1, B, 2); 5516 MatCheckPreallocated(A, 1); 5517 MatCheckPreallocated(B, 2); 5518 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5519 PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5520 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, 5521 B->cmap->N); 5522 if (A->ops->equal && A->ops->equal == B->ops->equal) { 5523 PetscUseTypeMethod(A, equal, B, flg); 5524 } else { 5525 PetscCall(MatMultEqual(A, B, 10, flg)); 5526 } 5527 PetscFunctionReturn(PETSC_SUCCESS); 5528 } 5529 5530 /*@ 5531 MatDiagonalScale - Scales a matrix on the left and right by diagonal 5532 matrices that are stored as vectors. Either of the two scaling 5533 matrices can be `NULL`. 5534 5535 Collective 5536 5537 Input Parameters: 5538 + mat - the matrix to be scaled 5539 . l - the left scaling vector (or `NULL`) 5540 - r - the right scaling vector (or `NULL`) 5541 5542 Level: intermediate 5543 5544 Note: 5545 `MatDiagonalScale()` computes A = LAR, where 5546 L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector) 5547 The L scales the rows of the matrix, the R scales the columns of the matrix. 5548 5549 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()` 5550 @*/ 5551 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r) 5552 { 5553 PetscFunctionBegin; 5554 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5555 PetscValidType(mat, 1); 5556 if (l) { 5557 PetscValidHeaderSpecific(l, VEC_CLASSID, 2); 5558 PetscCheckSameComm(mat, 1, l, 2); 5559 } 5560 if (r) { 5561 PetscValidHeaderSpecific(r, VEC_CLASSID, 3); 5562 PetscCheckSameComm(mat, 1, r, 3); 5563 } 5564 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5565 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5566 MatCheckPreallocated(mat, 1); 5567 if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS); 5568 5569 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5570 PetscUseTypeMethod(mat, diagonalscale, l, r); 5571 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5572 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5573 if (l != r) mat->symmetric = PETSC_BOOL3_FALSE; 5574 PetscFunctionReturn(PETSC_SUCCESS); 5575 } 5576 5577 /*@ 5578 MatScale - Scales all elements of a matrix by a given number. 5579 5580 Logically Collective 5581 5582 Input Parameters: 5583 + mat - the matrix to be scaled 5584 - a - the scaling value 5585 5586 Level: intermediate 5587 5588 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 5589 @*/ 5590 PetscErrorCode MatScale(Mat mat, PetscScalar a) 5591 { 5592 PetscFunctionBegin; 5593 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5594 PetscValidType(mat, 1); 5595 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5596 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5597 PetscValidLogicalCollectiveScalar(mat, a, 2); 5598 MatCheckPreallocated(mat, 1); 5599 5600 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5601 if (a != (PetscScalar)1.0) { 5602 PetscUseTypeMethod(mat, scale, a); 5603 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5604 } 5605 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5606 PetscFunctionReturn(PETSC_SUCCESS); 5607 } 5608 5609 /*@ 5610 MatNorm - Calculates various norms of a matrix. 5611 5612 Collective 5613 5614 Input Parameters: 5615 + mat - the matrix 5616 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY` 5617 5618 Output Parameter: 5619 . nrm - the resulting norm 5620 5621 Level: intermediate 5622 5623 .seealso: [](ch_matrices), `Mat` 5624 @*/ 5625 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm) 5626 { 5627 PetscFunctionBegin; 5628 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5629 PetscValidType(mat, 1); 5630 PetscValidRealPointer(nrm, 3); 5631 5632 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5633 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5634 MatCheckPreallocated(mat, 1); 5635 5636 PetscUseTypeMethod(mat, norm, type, nrm); 5637 PetscFunctionReturn(PETSC_SUCCESS); 5638 } 5639 5640 /* 5641 This variable is used to prevent counting of MatAssemblyBegin() that 5642 are called from within a MatAssemblyEnd(). 5643 */ 5644 static PetscInt MatAssemblyEnd_InUse = 0; 5645 /*@ 5646 MatAssemblyBegin - Begins assembling the matrix. This routine should 5647 be called after completing all calls to `MatSetValues()`. 5648 5649 Collective 5650 5651 Input Parameters: 5652 + mat - the matrix 5653 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5654 5655 Level: beginner 5656 5657 Notes: 5658 `MatSetValues()` generally caches the values that belong to other MPI processes. The matrix is ready to 5659 use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called. 5660 5661 Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES` 5662 in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before 5663 using the matrix. 5664 5665 ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the 5666 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 5667 a global collective operation requiring all processes that share the matrix. 5668 5669 Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed 5670 out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros 5671 before `MAT_FINAL_ASSEMBLY` so the space is not compressed out. 5672 5673 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()` 5674 @*/ 5675 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type) 5676 { 5677 PetscFunctionBegin; 5678 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5679 PetscValidType(mat, 1); 5680 MatCheckPreallocated(mat, 1); 5681 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?"); 5682 if (mat->assembled) { 5683 mat->was_assembled = PETSC_TRUE; 5684 mat->assembled = PETSC_FALSE; 5685 } 5686 5687 if (!MatAssemblyEnd_InUse) { 5688 PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0)); 5689 PetscTryTypeMethod(mat, assemblybegin, type); 5690 PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0)); 5691 } else PetscTryTypeMethod(mat, assemblybegin, type); 5692 PetscFunctionReturn(PETSC_SUCCESS); 5693 } 5694 5695 /*@ 5696 MatAssembled - Indicates if a matrix has been assembled and is ready for 5697 use; for example, in matrix-vector product. 5698 5699 Not Collective 5700 5701 Input Parameter: 5702 . mat - the matrix 5703 5704 Output Parameter: 5705 . assembled - `PETSC_TRUE` or `PETSC_FALSE` 5706 5707 Level: advanced 5708 5709 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()` 5710 @*/ 5711 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled) 5712 { 5713 PetscFunctionBegin; 5714 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5715 PetscValidBoolPointer(assembled, 2); 5716 *assembled = mat->assembled; 5717 PetscFunctionReturn(PETSC_SUCCESS); 5718 } 5719 5720 /*@ 5721 MatAssemblyEnd - Completes assembling the matrix. This routine should 5722 be called after `MatAssemblyBegin()`. 5723 5724 Collective 5725 5726 Input Parameters: 5727 + mat - the matrix 5728 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5729 5730 Options Database Keys: 5731 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 5732 . -mat_view ::ascii_info_detail - Prints more detailed info 5733 . -mat_view - Prints matrix in ASCII format 5734 . -mat_view ::ascii_matlab - Prints matrix in Matlab format 5735 . -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 5736 . -display <name> - Sets display name (default is host) 5737 . -draw_pause <sec> - Sets number of seconds to pause after display 5738 . -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See [Using MATLAB with PETSc](ch_matlab)) 5739 . -viewer_socket_machine <machine> - Machine to use for socket 5740 . -viewer_socket_port <port> - Port number to use for socket 5741 - -mat_view binary:filename[:append] - Save matrix to file in binary format 5742 5743 Level: beginner 5744 5745 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()` 5746 @*/ 5747 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type) 5748 { 5749 static PetscInt inassm = 0; 5750 PetscBool flg = PETSC_FALSE; 5751 5752 PetscFunctionBegin; 5753 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5754 PetscValidType(mat, 1); 5755 5756 inassm++; 5757 MatAssemblyEnd_InUse++; 5758 if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */ 5759 PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0)); 5760 PetscTryTypeMethod(mat, assemblyend, type); 5761 PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0)); 5762 } else PetscTryTypeMethod(mat, assemblyend, type); 5763 5764 /* Flush assembly is not a true assembly */ 5765 if (type != MAT_FLUSH_ASSEMBLY) { 5766 if (mat->num_ass) { 5767 if (!mat->symmetry_eternal) { 5768 mat->symmetric = PETSC_BOOL3_UNKNOWN; 5769 mat->hermitian = PETSC_BOOL3_UNKNOWN; 5770 } 5771 if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN; 5772 if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN; 5773 } 5774 mat->num_ass++; 5775 mat->assembled = PETSC_TRUE; 5776 mat->ass_nonzerostate = mat->nonzerostate; 5777 } 5778 5779 mat->insertmode = NOT_SET_VALUES; 5780 MatAssemblyEnd_InUse--; 5781 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5782 if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) { 5783 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 5784 5785 if (mat->checksymmetryonassembly) { 5786 PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg)); 5787 if (flg) { 5788 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5789 } else { 5790 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5791 } 5792 } 5793 if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL)); 5794 } 5795 inassm--; 5796 PetscFunctionReturn(PETSC_SUCCESS); 5797 } 5798 5799 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 5800 /*@ 5801 MatSetOption - Sets a parameter option for a matrix. Some options 5802 may be specific to certain storage formats. Some options 5803 determine how values will be inserted (or added). Sorted, 5804 row-oriented input will generally assemble the fastest. The default 5805 is row-oriented. 5806 5807 Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption` 5808 5809 Input Parameters: 5810 + mat - the matrix 5811 . op - the option, one of those listed below (and possibly others), 5812 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5813 5814 Options Describing Matrix Structure: 5815 + `MAT_SPD` - symmetric positive definite 5816 . `MAT_SYMMETRIC` - symmetric in terms of both structure and value 5817 . `MAT_HERMITIAN` - transpose is the complex conjugation 5818 . `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure 5819 . `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix 5820 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix 5821 . `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix 5822 5823 These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they 5824 do not need to be computed (usually at a high cost) 5825 5826 Options For Use with `MatSetValues()`: 5827 Insert a logically dense subblock, which can be 5828 . `MAT_ROW_ORIENTED` - row-oriented (default) 5829 5830 These options reflect the data you pass in with `MatSetValues()`; it has 5831 nothing to do with how the data is stored internally in the matrix 5832 data structure. 5833 5834 When (re)assembling a matrix, we can restrict the input for 5835 efficiency/debugging purposes. These options include 5836 . `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow) 5837 . `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated 5838 . `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries 5839 . `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry 5840 . `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly 5841 . `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if 5842 any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves 5843 performance for very large process counts. 5844 - `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset 5845 of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly 5846 functions, instead sending only neighbor messages. 5847 5848 Level: intermediate 5849 5850 Notes: 5851 Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg! 5852 5853 Some options are relevant only for particular matrix types and 5854 are thus ignored by others. Other options are not supported by 5855 certain matrix types and will generate an error message if set. 5856 5857 If using Fortran to compute a matrix, one may need to 5858 use the column-oriented option (or convert to the row-oriented 5859 format). 5860 5861 `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion 5862 that would generate a new entry in the nonzero structure is instead 5863 ignored. Thus, if memory has not already been allocated for this particular 5864 data, then the insertion is ignored. For dense matrices, in which 5865 the entire array is allocated, no entries are ever ignored. 5866 Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction 5867 5868 `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion 5869 that would generate a new entry in the nonzero structure instead produces 5870 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 5871 5872 `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion 5873 that would generate a new entry that has not been preallocated will 5874 instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats 5875 only.) This is a useful flag when debugging matrix memory preallocation. 5876 If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 5877 5878 `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for 5879 other processors should be dropped, rather than stashed. 5880 This is useful if you know that the "owning" processor is also 5881 always generating the correct matrix entries, so that PETSc need 5882 not transfer duplicate entries generated on another processor. 5883 5884 `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the 5885 searches during matrix assembly. When this flag is set, the hash table 5886 is created during the first matrix assembly. This hash table is 5887 used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()` 5888 to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag 5889 should be used with `MAT_USE_HASH_TABLE` flag. This option is currently 5890 supported by `MATMPIBAIJ` format only. 5891 5892 `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries 5893 are kept in the nonzero structure 5894 5895 `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating 5896 a zero location in the matrix 5897 5898 `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types 5899 5900 `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the 5901 zero row routines and thus improves performance for very large process counts. 5902 5903 `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular 5904 part of the matrix (since they should match the upper triangular part). 5905 5906 `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a 5907 single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common 5908 with finite difference schemes with non-periodic boundary conditions. 5909 5910 Developer Notes: 5911 `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other 5912 places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRIC` or `MAT_SPD` would need to be changed back 5913 to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had 5914 not changed. 5915 5916 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()` 5917 @*/ 5918 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg) 5919 { 5920 PetscFunctionBegin; 5921 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5922 if (op > 0) { 5923 PetscValidLogicalCollectiveEnum(mat, op, 2); 5924 PetscValidLogicalCollectiveBool(mat, flg, 3); 5925 } 5926 5927 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); 5928 5929 switch (op) { 5930 case MAT_FORCE_DIAGONAL_ENTRIES: 5931 mat->force_diagonals = flg; 5932 PetscFunctionReturn(PETSC_SUCCESS); 5933 case MAT_NO_OFF_PROC_ENTRIES: 5934 mat->nooffprocentries = flg; 5935 PetscFunctionReturn(PETSC_SUCCESS); 5936 case MAT_SUBSET_OFF_PROC_ENTRIES: 5937 mat->assembly_subset = flg; 5938 if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */ 5939 #if !defined(PETSC_HAVE_MPIUNI) 5940 PetscCall(MatStashScatterDestroy_BTS(&mat->stash)); 5941 #endif 5942 mat->stash.first_assembly_done = PETSC_FALSE; 5943 } 5944 PetscFunctionReturn(PETSC_SUCCESS); 5945 case MAT_NO_OFF_PROC_ZERO_ROWS: 5946 mat->nooffproczerorows = flg; 5947 PetscFunctionReturn(PETSC_SUCCESS); 5948 case MAT_SPD: 5949 if (flg) { 5950 mat->spd = PETSC_BOOL3_TRUE; 5951 mat->symmetric = PETSC_BOOL3_TRUE; 5952 mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5953 } else { 5954 mat->spd = PETSC_BOOL3_FALSE; 5955 } 5956 break; 5957 case MAT_SYMMETRIC: 5958 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5959 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5960 #if !defined(PETSC_USE_COMPLEX) 5961 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5962 #endif 5963 break; 5964 case MAT_HERMITIAN: 5965 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5966 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5967 #if !defined(PETSC_USE_COMPLEX) 5968 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5969 #endif 5970 break; 5971 case MAT_STRUCTURALLY_SYMMETRIC: 5972 mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5973 break; 5974 case MAT_SYMMETRY_ETERNAL: 5975 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"); 5976 mat->symmetry_eternal = flg; 5977 if (flg) mat->structural_symmetry_eternal = PETSC_TRUE; 5978 break; 5979 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 5980 PetscCheck(mat->structurally_symmetric != PETSC_BOOL3_UNKNOWN, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot set MAT_STRUCTURAL_SYMMETRY_ETERNAL without first setting MAT_STRUCTURAL_SYMMETRIC to true or false"); 5981 mat->structural_symmetry_eternal = flg; 5982 break; 5983 case MAT_SPD_ETERNAL: 5984 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"); 5985 mat->spd_eternal = flg; 5986 if (flg) { 5987 mat->structural_symmetry_eternal = PETSC_TRUE; 5988 mat->symmetry_eternal = PETSC_TRUE; 5989 } 5990 break; 5991 case MAT_STRUCTURE_ONLY: 5992 mat->structure_only = flg; 5993 break; 5994 case MAT_SORTED_FULL: 5995 mat->sortedfull = flg; 5996 break; 5997 default: 5998 break; 5999 } 6000 PetscTryTypeMethod(mat, setoption, op, flg); 6001 PetscFunctionReturn(PETSC_SUCCESS); 6002 } 6003 6004 /*@ 6005 MatGetOption - Gets a parameter option that has been set for a matrix. 6006 6007 Logically Collective 6008 6009 Input Parameters: 6010 + mat - the matrix 6011 - op - the option, this only responds to certain options, check the code for which ones 6012 6013 Output Parameter: 6014 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 6015 6016 Level: intermediate 6017 6018 Notes: 6019 Can only be called after `MatSetSizes()` and `MatSetType()` have been set. 6020 6021 Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or 6022 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6023 6024 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, 6025 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6026 @*/ 6027 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg) 6028 { 6029 PetscFunctionBegin; 6030 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6031 PetscValidType(mat, 1); 6032 6033 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); 6034 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()"); 6035 6036 switch (op) { 6037 case MAT_NO_OFF_PROC_ENTRIES: 6038 *flg = mat->nooffprocentries; 6039 break; 6040 case MAT_NO_OFF_PROC_ZERO_ROWS: 6041 *flg = mat->nooffproczerorows; 6042 break; 6043 case MAT_SYMMETRIC: 6044 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()"); 6045 break; 6046 case MAT_HERMITIAN: 6047 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()"); 6048 break; 6049 case MAT_STRUCTURALLY_SYMMETRIC: 6050 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()"); 6051 break; 6052 case MAT_SPD: 6053 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()"); 6054 break; 6055 case MAT_SYMMETRY_ETERNAL: 6056 *flg = mat->symmetry_eternal; 6057 break; 6058 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6059 *flg = mat->symmetry_eternal; 6060 break; 6061 default: 6062 break; 6063 } 6064 PetscFunctionReturn(PETSC_SUCCESS); 6065 } 6066 6067 /*@ 6068 MatZeroEntries - Zeros all entries of a matrix. For sparse matrices 6069 this routine retains the old nonzero structure. 6070 6071 Logically Collective 6072 6073 Input Parameter: 6074 . mat - the matrix 6075 6076 Level: intermediate 6077 6078 Note: 6079 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. 6080 See the Performance chapter of the users manual for information on preallocating matrices. 6081 6082 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()` 6083 @*/ 6084 PetscErrorCode MatZeroEntries(Mat mat) 6085 { 6086 PetscFunctionBegin; 6087 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6088 PetscValidType(mat, 1); 6089 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6090 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"); 6091 MatCheckPreallocated(mat, 1); 6092 6093 PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0)); 6094 PetscUseTypeMethod(mat, zeroentries); 6095 PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0)); 6096 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6097 PetscFunctionReturn(PETSC_SUCCESS); 6098 } 6099 6100 /*@ 6101 MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal) 6102 of a set of rows and columns of a matrix. 6103 6104 Collective 6105 6106 Input Parameters: 6107 + mat - the matrix 6108 . numRows - the number of rows/columns to zero 6109 . rows - the global row indices 6110 . diag - value put in the diagonal of the eliminated rows 6111 . x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call 6112 - b - optional vector of the right hand side, that will be adjusted by provided solution entries 6113 6114 Level: intermediate 6115 6116 Notes: 6117 This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6118 6119 For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`. 6120 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 6121 6122 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6123 Krylov method to take advantage of the known solution on the zeroed rows. 6124 6125 For the parallel case, all processes that share the matrix (i.e., 6126 those in the communicator used for matrix creation) MUST call this 6127 routine, regardless of whether any rows being zeroed are owned by 6128 them. 6129 6130 Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix. 6131 6132 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6133 list only rows local to itself). 6134 6135 The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine. 6136 6137 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6138 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6139 @*/ 6140 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6141 { 6142 PetscFunctionBegin; 6143 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6144 PetscValidType(mat, 1); 6145 if (numRows) PetscValidIntPointer(rows, 3); 6146 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6147 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6148 MatCheckPreallocated(mat, 1); 6149 6150 PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b); 6151 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6152 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6153 PetscFunctionReturn(PETSC_SUCCESS); 6154 } 6155 6156 /*@ 6157 MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal) 6158 of a set of rows and columns of a matrix. 6159 6160 Collective 6161 6162 Input Parameters: 6163 + mat - the matrix 6164 . is - the rows to zero 6165 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6166 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6167 - b - optional vector of right hand side, that will be adjusted by provided solution 6168 6169 Level: intermediate 6170 6171 Note: 6172 See `MatZeroRowsColumns()` for details on how this routine operates. 6173 6174 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6175 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()` 6176 @*/ 6177 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6178 { 6179 PetscInt numRows; 6180 const PetscInt *rows; 6181 6182 PetscFunctionBegin; 6183 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6184 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6185 PetscValidType(mat, 1); 6186 PetscValidType(is, 2); 6187 PetscCall(ISGetLocalSize(is, &numRows)); 6188 PetscCall(ISGetIndices(is, &rows)); 6189 PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b)); 6190 PetscCall(ISRestoreIndices(is, &rows)); 6191 PetscFunctionReturn(PETSC_SUCCESS); 6192 } 6193 6194 /*@ 6195 MatZeroRows - Zeros all entries (except possibly the main diagonal) 6196 of a set of rows of a matrix. 6197 6198 Collective 6199 6200 Input Parameters: 6201 + mat - the matrix 6202 . numRows - the number of rows to zero 6203 . rows - the global row indices 6204 . diag - value put in the diagonal of the zeroed rows 6205 . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call 6206 - b - optional vector of right hand side, that will be adjusted by provided solution entries 6207 6208 Level: intermediate 6209 6210 Notes: 6211 This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6212 6213 For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`. 6214 6215 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6216 Krylov method to take advantage of the known solution on the zeroed rows. 6217 6218 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) 6219 from the matrix. 6220 6221 Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix 6222 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 6223 formats this does not alter the nonzero structure. 6224 6225 If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure 6226 of the matrix is not changed the values are 6227 merely zeroed. 6228 6229 The user can set a value in the diagonal entry (or for the `MATAIJ` format 6230 formats can optionally remove the main diagonal entry from the 6231 nonzero structure as well, by passing 0.0 as the final argument). 6232 6233 For the parallel case, all processes that share the matrix (i.e., 6234 those in the communicator used for matrix creation) MUST call this 6235 routine, regardless of whether any rows being zeroed are owned by 6236 them. 6237 6238 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6239 list only rows local to itself). 6240 6241 You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it 6242 owns that are to be zeroed. This saves a global synchronization in the implementation. 6243 6244 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6245 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE` 6246 @*/ 6247 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6248 { 6249 PetscFunctionBegin; 6250 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6251 PetscValidType(mat, 1); 6252 if (numRows) PetscValidIntPointer(rows, 3); 6253 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6254 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6255 MatCheckPreallocated(mat, 1); 6256 6257 PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b); 6258 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6259 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6260 PetscFunctionReturn(PETSC_SUCCESS); 6261 } 6262 6263 /*@ 6264 MatZeroRowsIS - Zeros all entries (except possibly the main diagonal) 6265 of a set of rows of a matrix. 6266 6267 Collective 6268 6269 Input Parameters: 6270 + mat - the matrix 6271 . is - index set of rows to remove (if `NULL` then no row is removed) 6272 . diag - value put in all diagonals of eliminated rows 6273 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6274 - b - optional vector of right hand side, that will be adjusted by provided solution 6275 6276 Level: intermediate 6277 6278 Note: 6279 See `MatZeroRows()` for details on how this routine operates. 6280 6281 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6282 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6283 @*/ 6284 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6285 { 6286 PetscInt numRows = 0; 6287 const PetscInt *rows = NULL; 6288 6289 PetscFunctionBegin; 6290 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6291 PetscValidType(mat, 1); 6292 if (is) { 6293 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6294 PetscCall(ISGetLocalSize(is, &numRows)); 6295 PetscCall(ISGetIndices(is, &rows)); 6296 } 6297 PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b)); 6298 if (is) PetscCall(ISRestoreIndices(is, &rows)); 6299 PetscFunctionReturn(PETSC_SUCCESS); 6300 } 6301 6302 /*@ 6303 MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal) 6304 of a set of rows of a matrix. These rows must be local to the process. 6305 6306 Collective 6307 6308 Input Parameters: 6309 + mat - the matrix 6310 . numRows - the number of rows to remove 6311 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6312 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6313 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6314 - b - optional vector of right hand side, that will be adjusted by provided solution 6315 6316 Level: intermediate 6317 6318 Notes: 6319 See `MatZeroRows()` for details on how this routine operates. 6320 6321 The grid coordinates are across the entire grid, not just the local portion 6322 6323 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6324 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6325 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6326 `DM_BOUNDARY_PERIODIC` boundary type. 6327 6328 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 6329 a single value per point) you can skip filling those indices. 6330 6331 Fortran Notes: 6332 `idxm` and `idxn` should be declared as 6333 $ MatStencil idxm(4, m) 6334 and the values inserted using 6335 .vb 6336 idxm(MatStencil_i, 1) = i 6337 idxm(MatStencil_j, 1) = j 6338 idxm(MatStencil_k, 1) = k 6339 idxm(MatStencil_c, 1) = c 6340 etc 6341 .ve 6342 6343 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6344 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6345 @*/ 6346 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6347 { 6348 PetscInt dim = mat->stencil.dim; 6349 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6350 PetscInt *dims = mat->stencil.dims + 1; 6351 PetscInt *starts = mat->stencil.starts; 6352 PetscInt *dxm = (PetscInt *)rows; 6353 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6354 6355 PetscFunctionBegin; 6356 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6357 PetscValidType(mat, 1); 6358 if (numRows) PetscValidPointer(rows, 3); 6359 6360 PetscCall(PetscMalloc1(numRows, &jdxm)); 6361 for (i = 0; i < numRows; ++i) { 6362 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6363 for (j = 0; j < 3 - sdim; ++j) dxm++; 6364 /* Local index in X dir */ 6365 tmp = *dxm++ - starts[0]; 6366 /* Loop over remaining dimensions */ 6367 for (j = 0; j < dim - 1; ++j) { 6368 /* If nonlocal, set index to be negative */ 6369 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6370 /* Update local index */ 6371 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6372 } 6373 /* Skip component slot if necessary */ 6374 if (mat->stencil.noc) dxm++; 6375 /* Local row number */ 6376 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6377 } 6378 PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b)); 6379 PetscCall(PetscFree(jdxm)); 6380 PetscFunctionReturn(PETSC_SUCCESS); 6381 } 6382 6383 /*@ 6384 MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal) 6385 of a set of rows and columns of a matrix. 6386 6387 Collective 6388 6389 Input Parameters: 6390 + mat - the matrix 6391 . numRows - the number of rows/columns to remove 6392 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6393 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6394 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6395 - b - optional vector of right hand side, that will be adjusted by provided solution 6396 6397 Level: intermediate 6398 6399 Notes: 6400 See `MatZeroRowsColumns()` for details on how this routine operates. 6401 6402 The grid coordinates are across the entire grid, not just the local portion 6403 6404 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6405 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6406 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6407 `DM_BOUNDARY_PERIODIC` boundary type. 6408 6409 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 6410 a single value per point) you can skip filling those indices. 6411 6412 Fortran Notes: 6413 `idxm` and `idxn` should be declared as 6414 $ MatStencil idxm(4, m) 6415 and the values inserted using 6416 .vb 6417 idxm(MatStencil_i, 1) = i 6418 idxm(MatStencil_j, 1) = j 6419 idxm(MatStencil_k, 1) = k 6420 idxm(MatStencil_c, 1) = c 6421 etc 6422 .ve 6423 6424 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6425 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()` 6426 @*/ 6427 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6428 { 6429 PetscInt dim = mat->stencil.dim; 6430 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6431 PetscInt *dims = mat->stencil.dims + 1; 6432 PetscInt *starts = mat->stencil.starts; 6433 PetscInt *dxm = (PetscInt *)rows; 6434 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6435 6436 PetscFunctionBegin; 6437 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6438 PetscValidType(mat, 1); 6439 if (numRows) PetscValidPointer(rows, 3); 6440 6441 PetscCall(PetscMalloc1(numRows, &jdxm)); 6442 for (i = 0; i < numRows; ++i) { 6443 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6444 for (j = 0; j < 3 - sdim; ++j) dxm++; 6445 /* Local index in X dir */ 6446 tmp = *dxm++ - starts[0]; 6447 /* Loop over remaining dimensions */ 6448 for (j = 0; j < dim - 1; ++j) { 6449 /* If nonlocal, set index to be negative */ 6450 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6451 /* Update local index */ 6452 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6453 } 6454 /* Skip component slot if necessary */ 6455 if (mat->stencil.noc) dxm++; 6456 /* Local row number */ 6457 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6458 } 6459 PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b)); 6460 PetscCall(PetscFree(jdxm)); 6461 PetscFunctionReturn(PETSC_SUCCESS); 6462 } 6463 6464 /*@C 6465 MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal) 6466 of a set of rows of a matrix; using local numbering of rows. 6467 6468 Collective 6469 6470 Input Parameters: 6471 + mat - the matrix 6472 . numRows - the number of rows to remove 6473 . rows - the local row indices 6474 . diag - value put in all diagonals of eliminated rows 6475 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6476 - b - optional vector of right hand side, that will be adjusted by provided solution 6477 6478 Level: intermediate 6479 6480 Notes: 6481 Before calling `MatZeroRowsLocal()`, the user must first set the 6482 local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`. 6483 6484 See `MatZeroRows()` for details on how this routine operates. 6485 6486 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`, 6487 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6488 @*/ 6489 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6490 { 6491 PetscFunctionBegin; 6492 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6493 PetscValidType(mat, 1); 6494 if (numRows) PetscValidIntPointer(rows, 3); 6495 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6496 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6497 MatCheckPreallocated(mat, 1); 6498 6499 if (mat->ops->zerorowslocal) { 6500 PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b); 6501 } else { 6502 IS is, newis; 6503 const PetscInt *newRows; 6504 6505 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6506 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6507 PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis)); 6508 PetscCall(ISGetIndices(newis, &newRows)); 6509 PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b); 6510 PetscCall(ISRestoreIndices(newis, &newRows)); 6511 PetscCall(ISDestroy(&newis)); 6512 PetscCall(ISDestroy(&is)); 6513 } 6514 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6515 PetscFunctionReturn(PETSC_SUCCESS); 6516 } 6517 6518 /*@ 6519 MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal) 6520 of a set of rows of a matrix; using local numbering of rows. 6521 6522 Collective 6523 6524 Input Parameters: 6525 + mat - the matrix 6526 . is - index set of rows to remove 6527 . diag - value put in all diagonals of eliminated rows 6528 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6529 - b - optional vector of right hand side, that will be adjusted by provided solution 6530 6531 Level: intermediate 6532 6533 Notes: 6534 Before calling `MatZeroRowsLocalIS()`, the user must first set the 6535 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6536 6537 See `MatZeroRows()` for details on how this routine operates. 6538 6539 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6540 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6541 @*/ 6542 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6543 { 6544 PetscInt numRows; 6545 const PetscInt *rows; 6546 6547 PetscFunctionBegin; 6548 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6549 PetscValidType(mat, 1); 6550 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6551 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6552 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6553 MatCheckPreallocated(mat, 1); 6554 6555 PetscCall(ISGetLocalSize(is, &numRows)); 6556 PetscCall(ISGetIndices(is, &rows)); 6557 PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b)); 6558 PetscCall(ISRestoreIndices(is, &rows)); 6559 PetscFunctionReturn(PETSC_SUCCESS); 6560 } 6561 6562 /*@ 6563 MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal) 6564 of a set of rows and columns of a matrix; using local numbering of rows. 6565 6566 Collective 6567 6568 Input Parameters: 6569 + mat - the matrix 6570 . numRows - the number of rows to remove 6571 . rows - the global row indices 6572 . diag - value put in all diagonals of eliminated rows 6573 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6574 - b - optional vector of right hand side, that will be adjusted by provided solution 6575 6576 Level: intermediate 6577 6578 Notes: 6579 Before calling `MatZeroRowsColumnsLocal()`, the user must first set the 6580 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6581 6582 See `MatZeroRowsColumns()` for details on how this routine operates. 6583 6584 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6585 `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6586 @*/ 6587 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6588 { 6589 IS is, newis; 6590 const PetscInt *newRows; 6591 6592 PetscFunctionBegin; 6593 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6594 PetscValidType(mat, 1); 6595 if (numRows) PetscValidIntPointer(rows, 3); 6596 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6597 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6598 MatCheckPreallocated(mat, 1); 6599 6600 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6601 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6602 PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis)); 6603 PetscCall(ISGetIndices(newis, &newRows)); 6604 PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b); 6605 PetscCall(ISRestoreIndices(newis, &newRows)); 6606 PetscCall(ISDestroy(&newis)); 6607 PetscCall(ISDestroy(&is)); 6608 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6609 PetscFunctionReturn(PETSC_SUCCESS); 6610 } 6611 6612 /*@ 6613 MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal) 6614 of a set of rows and columns of a matrix; using local numbering of rows. 6615 6616 Collective 6617 6618 Input Parameters: 6619 + mat - the matrix 6620 . is - index set of rows to remove 6621 . diag - value put in all diagonals of eliminated rows 6622 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6623 - b - optional vector of right hand side, that will be adjusted by provided solution 6624 6625 Level: intermediate 6626 6627 Notes: 6628 Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the 6629 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6630 6631 See `MatZeroRowsColumns()` for details on how this routine operates. 6632 6633 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6634 `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6635 @*/ 6636 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6637 { 6638 PetscInt numRows; 6639 const PetscInt *rows; 6640 6641 PetscFunctionBegin; 6642 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6643 PetscValidType(mat, 1); 6644 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6645 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6646 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6647 MatCheckPreallocated(mat, 1); 6648 6649 PetscCall(ISGetLocalSize(is, &numRows)); 6650 PetscCall(ISGetIndices(is, &rows)); 6651 PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b)); 6652 PetscCall(ISRestoreIndices(is, &rows)); 6653 PetscFunctionReturn(PETSC_SUCCESS); 6654 } 6655 6656 /*@C 6657 MatGetSize - Returns the numbers of rows and columns in a matrix. 6658 6659 Not Collective 6660 6661 Input Parameter: 6662 . mat - the matrix 6663 6664 Output Parameters: 6665 + m - the number of global rows 6666 - n - the number of global columns 6667 6668 Level: beginner 6669 6670 Note: 6671 Both output parameters can be `NULL` on input. 6672 6673 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()` 6674 @*/ 6675 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n) 6676 { 6677 PetscFunctionBegin; 6678 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6679 if (m) *m = mat->rmap->N; 6680 if (n) *n = mat->cmap->N; 6681 PetscFunctionReturn(PETSC_SUCCESS); 6682 } 6683 6684 /*@C 6685 MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns 6686 of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`. 6687 6688 Not Collective 6689 6690 Input Parameter: 6691 . mat - the matrix 6692 6693 Output Parameters: 6694 + m - the number of local rows, use `NULL` to not obtain this value 6695 - n - the number of local columns, use `NULL` to not obtain this value 6696 6697 Level: beginner 6698 6699 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()` 6700 @*/ 6701 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n) 6702 { 6703 PetscFunctionBegin; 6704 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6705 if (m) PetscValidIntPointer(m, 2); 6706 if (n) PetscValidIntPointer(n, 3); 6707 if (m) *m = mat->rmap->n; 6708 if (n) *n = mat->cmap->n; 6709 PetscFunctionReturn(PETSC_SUCCESS); 6710 } 6711 6712 /*@C 6713 MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a 6714 vector one multiplies this matrix by that are owned by this processor. 6715 6716 Not Collective, unless matrix has not been allocated, then collective 6717 6718 Input Parameter: 6719 . mat - the matrix 6720 6721 Output Parameters: 6722 + m - the global index of the first local column, use `NULL` to not obtain this value 6723 - n - one more than the global index of the last local column, use `NULL` to not obtain this value 6724 6725 Level: developer 6726 6727 Notes: 6728 Retursns the columns of the "diagonal block" for most sparse matrix formats. See [Matrix 6729 Layouts](sec_matlayout) for details on matrix layouts. 6730 6731 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout` 6732 @*/ 6733 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n) 6734 { 6735 PetscFunctionBegin; 6736 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6737 PetscValidType(mat, 1); 6738 if (m) PetscValidIntPointer(m, 2); 6739 if (n) PetscValidIntPointer(n, 3); 6740 MatCheckPreallocated(mat, 1); 6741 if (m) *m = mat->cmap->rstart; 6742 if (n) *n = mat->cmap->rend; 6743 PetscFunctionReturn(PETSC_SUCCESS); 6744 } 6745 6746 /*@C 6747 MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6748 this MPI process. 6749 6750 Not Collective 6751 6752 Input Parameter: 6753 . mat - the matrix 6754 6755 Output Parameters: 6756 + m - the global index of the first local row, use `NULL` to not obtain this value 6757 - n - one more than the global index of the last local row, use `NULL` to not obtain this value 6758 6759 Level: beginner 6760 6761 Note: 6762 For all matrices it returns the range of matrix rows associated with rows of a vector that 6763 would contain the result of a matrix vector product with this matrix. See [Matrix 6764 Layouts](sec_matlayout) for details on matrix layouts. 6765 6766 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, 6767 `PetscLayout` 6768 @*/ 6769 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n) 6770 { 6771 PetscFunctionBegin; 6772 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6773 PetscValidType(mat, 1); 6774 if (m) PetscValidIntPointer(m, 2); 6775 if (n) PetscValidIntPointer(n, 3); 6776 MatCheckPreallocated(mat, 1); 6777 if (m) *m = mat->rmap->rstart; 6778 if (n) *n = mat->rmap->rend; 6779 PetscFunctionReturn(PETSC_SUCCESS); 6780 } 6781 6782 /*@C 6783 MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and 6784 `MATSCALAPACK`, returns the range of matrix rows owned by each process. 6785 6786 Not Collective, unless matrix has not been allocated 6787 6788 Input Parameter: 6789 . mat - the matrix 6790 6791 Output Parameter: 6792 . ranges - start of each processors portion plus one more than the total length at the end 6793 6794 Level: beginner 6795 6796 Notes: 6797 For all matrices it returns the ranges of matrix rows associated with rows of a vector that 6798 would contain the result of a matrix vector product with this matrix. See [Matrix 6799 Layouts](sec_matlayout) for details on matrix layouts. 6800 6801 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout` 6802 @*/ 6803 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges) 6804 { 6805 PetscFunctionBegin; 6806 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6807 PetscValidType(mat, 1); 6808 MatCheckPreallocated(mat, 1); 6809 PetscCall(PetscLayoutGetRanges(mat->rmap, ranges)); 6810 PetscFunctionReturn(PETSC_SUCCESS); 6811 } 6812 6813 /*@C 6814 MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a 6815 vector one multiplies this vector by that are owned by each processor. 6816 6817 Not Collective, unless matrix has not been allocated 6818 6819 Input Parameter: 6820 . mat - the matrix 6821 6822 Output Parameter: 6823 . ranges - start of each processors portion plus one more then the total length at the end 6824 6825 Level: beginner 6826 6827 Notes: 6828 Returns the columns of the "diagonal blocks", for most sparse matrix formats. See [Matrix 6829 Layouts](sec_matlayout) for details on matrix layouts. 6830 6831 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()` 6832 @*/ 6833 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges) 6834 { 6835 PetscFunctionBegin; 6836 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6837 PetscValidType(mat, 1); 6838 MatCheckPreallocated(mat, 1); 6839 PetscCall(PetscLayoutGetRanges(mat->cmap, ranges)); 6840 PetscFunctionReturn(PETSC_SUCCESS); 6841 } 6842 6843 /*@C 6844 MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. 6845 6846 Not Collective 6847 6848 Input Parameter: 6849 . A - matrix 6850 6851 Output Parameters: 6852 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value 6853 - cols - columns in which this process owns elements, use `NULL` to not obtain this value 6854 6855 Level: intermediate 6856 6857 Notes: 6858 For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this corresponds to values 6859 returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and 6860 `MATSCALAPACK` the ownership is more complicated. See [Matrix Layouts](sec_matlayout) for 6861 details on matrix layouts. 6862 6863 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK`` 6864 @*/ 6865 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols) 6866 { 6867 PetscErrorCode (*f)(Mat, IS *, IS *); 6868 6869 PetscFunctionBegin; 6870 MatCheckPreallocated(A, 1); 6871 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f)); 6872 if (f) { 6873 PetscCall((*f)(A, rows, cols)); 6874 } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */ 6875 if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows)); 6876 if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols)); 6877 } 6878 PetscFunctionReturn(PETSC_SUCCESS); 6879 } 6880 6881 /*@C 6882 MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()` 6883 Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()` 6884 to complete the factorization. 6885 6886 Collective 6887 6888 Input Parameters: 6889 + fact - the factorized matrix obtained with `MatGetFactor()` 6890 . mat - the matrix 6891 . row - row permutation 6892 . col - column permutation 6893 - info - structure containing 6894 .vb 6895 levels - number of levels of fill. 6896 expected fill - as ratio of original fill. 6897 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 6898 missing diagonal entries) 6899 .ve 6900 6901 Level: developer 6902 6903 Notes: 6904 See [Matrix Factorization](sec_matfactor) for additional information. 6905 6906 Most users should employ the `KSP` interface for linear solvers 6907 instead of working directly with matrix algebra routines such as this. 6908 See, e.g., `KSPCreate()`. 6909 6910 Uses the definition of level of fill as in Y. Saad, 2003 6911 6912 Developer Notes: 6913 The Fortran interface is not autogenerated as the 6914 interface definition cannot be generated correctly [due to `MatFactorInfo`] 6915 6916 References: 6917 . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003 6918 6919 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 6920 `MatGetOrdering()`, `MatFactorInfo` 6921 @*/ 6922 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 6923 { 6924 PetscFunctionBegin; 6925 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 6926 PetscValidType(mat, 2); 6927 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 6928 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 6929 PetscValidPointer(info, 5); 6930 PetscValidPointer(fact, 1); 6931 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels); 6932 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 6933 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6934 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6935 MatCheckPreallocated(mat, 2); 6936 6937 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0)); 6938 PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info); 6939 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0)); 6940 PetscFunctionReturn(PETSC_SUCCESS); 6941 } 6942 6943 /*@C 6944 MatICCFactorSymbolic - Performs symbolic incomplete 6945 Cholesky factorization for a symmetric matrix. Use 6946 `MatCholeskyFactorNumeric()` to complete the factorization. 6947 6948 Collective 6949 6950 Input Parameters: 6951 + fact - the factorized matrix obtained with `MatGetFactor()` 6952 . mat - the matrix to be factored 6953 . perm - row and column permutation 6954 - info - structure containing 6955 .vb 6956 levels - number of levels of fill. 6957 expected fill - as ratio of original fill. 6958 .ve 6959 6960 Level: developer 6961 6962 Notes: 6963 Most users should employ the `KSP` interface for linear solvers 6964 instead of working directly with matrix algebra routines such as this. 6965 See, e.g., `KSPCreate()`. 6966 6967 This uses the definition of level of fill as in Y. Saad, 2003 6968 6969 Developer Notes: 6970 The Fortran interface is not autogenerated as the 6971 interface definition cannot be generated correctly [due to `MatFactorInfo`] 6972 6973 References: 6974 . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003 6975 6976 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 6977 @*/ 6978 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 6979 { 6980 PetscFunctionBegin; 6981 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 6982 PetscValidType(mat, 2); 6983 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 6984 PetscValidPointer(info, 4); 6985 PetscValidPointer(fact, 1); 6986 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6987 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels); 6988 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 6989 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6990 MatCheckPreallocated(mat, 2); 6991 6992 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 6993 PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info); 6994 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 6995 PetscFunctionReturn(PETSC_SUCCESS); 6996 } 6997 6998 /*@C 6999 MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat 7000 points to an array of valid matrices, they may be reused to store the new 7001 submatrices. 7002 7003 Collective 7004 7005 Input Parameters: 7006 + mat - the matrix 7007 . n - the number of submatrixes to be extracted (on this processor, may be zero) 7008 . irow - index set of rows to extract 7009 . icol - index set of columns to extract 7010 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7011 7012 Output Parameter: 7013 . submat - the array of submatrices 7014 7015 Level: advanced 7016 7017 Notes: 7018 `MatCreateSubMatrices()` can extract ONLY sequential submatrices 7019 (from both sequential and parallel matrices). Use `MatCreateSubMatrix()` 7020 to extract a parallel submatrix. 7021 7022 Some matrix types place restrictions on the row and column 7023 indices, such as that they be sorted or that they be equal to each other. 7024 7025 The index sets may not have duplicate entries. 7026 7027 When extracting submatrices from a parallel matrix, each processor can 7028 form a different submatrix by setting the rows and columns of its 7029 individual index sets according to the local submatrix desired. 7030 7031 When finished using the submatrices, the user should destroy 7032 them with `MatDestroySubMatrices()`. 7033 7034 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 7035 original matrix has not changed from that last call to `MatCreateSubMatrices()`. 7036 7037 This routine creates the matrices in submat; you should NOT create them before 7038 calling it. It also allocates the array of matrix pointers submat. 7039 7040 For `MATBAIJ` matrices the index sets must respect the block structure, that is if they 7041 request one row/column in a block, they must request all rows/columns that are in 7042 that block. For example, if the block size is 2 you cannot request just row 0 and 7043 column 0. 7044 7045 Fortran Notes: 7046 The Fortran interface is slightly different from that given below; it 7047 requires one to pass in as `submat` a `Mat` (integer) array of size at least n+1. 7048 7049 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7050 @*/ 7051 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7052 { 7053 PetscInt i; 7054 PetscBool eq; 7055 7056 PetscFunctionBegin; 7057 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7058 PetscValidType(mat, 1); 7059 if (n) { 7060 PetscValidPointer(irow, 3); 7061 for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3); 7062 PetscValidPointer(icol, 4); 7063 for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4); 7064 } 7065 PetscValidPointer(submat, 6); 7066 if (n && scall == MAT_REUSE_MATRIX) { 7067 PetscValidPointer(*submat, 6); 7068 for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6); 7069 } 7070 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7071 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7072 MatCheckPreallocated(mat, 1); 7073 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7074 PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat); 7075 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7076 for (i = 0; i < n; i++) { 7077 (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */ 7078 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7079 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7080 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 7081 if (mat->boundtocpu && mat->bindingpropagates) { 7082 PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE)); 7083 PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE)); 7084 } 7085 #endif 7086 } 7087 PetscFunctionReturn(PETSC_SUCCESS); 7088 } 7089 7090 /*@C 7091 MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms). 7092 7093 Collective 7094 7095 Input Parameters: 7096 + mat - the matrix 7097 . n - the number of submatrixes to be extracted 7098 . irow - index set of rows to extract 7099 . icol - index set of columns to extract 7100 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7101 7102 Output Parameter: 7103 . submat - the array of submatrices 7104 7105 Level: advanced 7106 7107 Note: 7108 This is used by `PCGASM` 7109 7110 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7111 @*/ 7112 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7113 { 7114 PetscInt i; 7115 PetscBool eq; 7116 7117 PetscFunctionBegin; 7118 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7119 PetscValidType(mat, 1); 7120 if (n) { 7121 PetscValidPointer(irow, 3); 7122 PetscValidHeaderSpecific(*irow, IS_CLASSID, 3); 7123 PetscValidPointer(icol, 4); 7124 PetscValidHeaderSpecific(*icol, IS_CLASSID, 4); 7125 } 7126 PetscValidPointer(submat, 6); 7127 if (n && scall == MAT_REUSE_MATRIX) { 7128 PetscValidPointer(*submat, 6); 7129 PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6); 7130 } 7131 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7132 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7133 MatCheckPreallocated(mat, 1); 7134 7135 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7136 PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat); 7137 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7138 for (i = 0; i < n; i++) { 7139 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7140 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7141 } 7142 PetscFunctionReturn(PETSC_SUCCESS); 7143 } 7144 7145 /*@C 7146 MatDestroyMatrices - Destroys an array of matrices. 7147 7148 Collective 7149 7150 Input Parameters: 7151 + n - the number of local matrices 7152 - mat - the matrices (this is a pointer to the array of matrices) 7153 7154 Level: advanced 7155 7156 Note: 7157 Frees not only the matrices, but also the array that contains the matrices 7158 7159 Fortran Notes: 7160 This does not free the array. 7161 7162 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()` 7163 @*/ 7164 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[]) 7165 { 7166 PetscInt i; 7167 7168 PetscFunctionBegin; 7169 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7170 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7171 PetscValidPointer(mat, 2); 7172 7173 for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i])); 7174 7175 /* memory is allocated even if n = 0 */ 7176 PetscCall(PetscFree(*mat)); 7177 PetscFunctionReturn(PETSC_SUCCESS); 7178 } 7179 7180 /*@C 7181 MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`. 7182 7183 Collective 7184 7185 Input Parameters: 7186 + n - the number of local matrices 7187 - mat - the matrices (this is a pointer to the array of matrices, just to match the calling 7188 sequence of `MatCreateSubMatrices()`) 7189 7190 Level: advanced 7191 7192 Note: 7193 Frees not only the matrices, but also the array that contains the matrices 7194 7195 Fortran Notes: 7196 This does not free the array. 7197 7198 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7199 @*/ 7200 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[]) 7201 { 7202 Mat mat0; 7203 7204 PetscFunctionBegin; 7205 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7206 /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */ 7207 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7208 PetscValidPointer(mat, 2); 7209 7210 mat0 = (*mat)[0]; 7211 if (mat0 && mat0->ops->destroysubmatrices) { 7212 PetscCall((*mat0->ops->destroysubmatrices)(n, mat)); 7213 } else { 7214 PetscCall(MatDestroyMatrices(n, mat)); 7215 } 7216 PetscFunctionReturn(PETSC_SUCCESS); 7217 } 7218 7219 /*@C 7220 MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process 7221 7222 Collective 7223 7224 Input Parameter: 7225 . mat - the matrix 7226 7227 Output Parameter: 7228 . matstruct - the sequential matrix with the nonzero structure of mat 7229 7230 Level: developer 7231 7232 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7233 @*/ 7234 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct) 7235 { 7236 PetscFunctionBegin; 7237 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7238 PetscValidPointer(matstruct, 2); 7239 7240 PetscValidType(mat, 1); 7241 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7242 MatCheckPreallocated(mat, 1); 7243 7244 PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7245 PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct); 7246 PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7247 PetscFunctionReturn(PETSC_SUCCESS); 7248 } 7249 7250 /*@C 7251 MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`. 7252 7253 Collective 7254 7255 Input Parameter: 7256 . mat - the matrix (this is a pointer to the array of matrices, just to match the calling 7257 sequence of `MatGetSeqNonzeroStructure()`) 7258 7259 Level: advanced 7260 7261 Note: 7262 Frees not only the matrices, but also the array that contains the matrices 7263 7264 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()` 7265 @*/ 7266 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat) 7267 { 7268 PetscFunctionBegin; 7269 PetscValidPointer(mat, 1); 7270 PetscCall(MatDestroy(mat)); 7271 PetscFunctionReturn(PETSC_SUCCESS); 7272 } 7273 7274 /*@ 7275 MatIncreaseOverlap - Given a set of submatrices indicated by index sets, 7276 replaces the index sets by larger ones that represent submatrices with 7277 additional overlap. 7278 7279 Collective 7280 7281 Input Parameters: 7282 + mat - the matrix 7283 . n - the number of index sets 7284 . is - the array of index sets (these index sets will changed during the call) 7285 - ov - the additional overlap requested 7286 7287 Options Database Key: 7288 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7289 7290 Level: developer 7291 7292 Note: 7293 The computed overlap preserves the matrix block sizes when the blocks are square. 7294 That is: if a matrix nonzero for a given block would increase the overlap all columns associated with 7295 that block are included in the overlap regardless of whether each specific column would increase the overlap. 7296 7297 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()` 7298 @*/ 7299 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov) 7300 { 7301 PetscInt i, bs, cbs; 7302 7303 PetscFunctionBegin; 7304 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7305 PetscValidType(mat, 1); 7306 PetscValidLogicalCollectiveInt(mat, n, 2); 7307 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7308 if (n) { 7309 PetscValidPointer(is, 3); 7310 for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3); 7311 } 7312 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7313 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7314 MatCheckPreallocated(mat, 1); 7315 7316 if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS); 7317 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7318 PetscUseTypeMethod(mat, increaseoverlap, n, is, ov); 7319 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7320 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 7321 if (bs == cbs) { 7322 for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs)); 7323 } 7324 PetscFunctionReturn(PETSC_SUCCESS); 7325 } 7326 7327 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt); 7328 7329 /*@ 7330 MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across 7331 a sub communicator, replaces the index sets by larger ones that represent submatrices with 7332 additional overlap. 7333 7334 Collective 7335 7336 Input Parameters: 7337 + mat - the matrix 7338 . n - the number of index sets 7339 . is - the array of index sets (these index sets will changed during the call) 7340 - ov - the additional overlap requested 7341 7342 ` Options Database Key: 7343 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7344 7345 Level: developer 7346 7347 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()` 7348 @*/ 7349 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov) 7350 { 7351 PetscInt i; 7352 7353 PetscFunctionBegin; 7354 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7355 PetscValidType(mat, 1); 7356 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7357 if (n) { 7358 PetscValidPointer(is, 3); 7359 PetscValidHeaderSpecific(*is, IS_CLASSID, 3); 7360 } 7361 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7362 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7363 MatCheckPreallocated(mat, 1); 7364 if (!ov) PetscFunctionReturn(PETSC_SUCCESS); 7365 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7366 for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov)); 7367 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7368 PetscFunctionReturn(PETSC_SUCCESS); 7369 } 7370 7371 /*@ 7372 MatGetBlockSize - Returns the matrix block size. 7373 7374 Not Collective 7375 7376 Input Parameter: 7377 . mat - the matrix 7378 7379 Output Parameter: 7380 . bs - block size 7381 7382 Level: intermediate 7383 7384 Notes: 7385 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7386 7387 If the block size has not been set yet this routine returns 1. 7388 7389 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()` 7390 @*/ 7391 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs) 7392 { 7393 PetscFunctionBegin; 7394 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7395 PetscValidIntPointer(bs, 2); 7396 *bs = PetscAbs(mat->rmap->bs); 7397 PetscFunctionReturn(PETSC_SUCCESS); 7398 } 7399 7400 /*@ 7401 MatGetBlockSizes - Returns the matrix block row and column sizes. 7402 7403 Not Collective 7404 7405 Input Parameter: 7406 . mat - the matrix 7407 7408 Output Parameters: 7409 + rbs - row block size 7410 - cbs - column block size 7411 7412 Level: intermediate 7413 7414 Notes: 7415 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7416 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7417 7418 If a block size has not been set yet this routine returns 1. 7419 7420 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()` 7421 @*/ 7422 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs) 7423 { 7424 PetscFunctionBegin; 7425 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7426 if (rbs) PetscValidIntPointer(rbs, 2); 7427 if (cbs) PetscValidIntPointer(cbs, 3); 7428 if (rbs) *rbs = PetscAbs(mat->rmap->bs); 7429 if (cbs) *cbs = PetscAbs(mat->cmap->bs); 7430 PetscFunctionReturn(PETSC_SUCCESS); 7431 } 7432 7433 /*@ 7434 MatSetBlockSize - Sets the matrix block size. 7435 7436 Logically Collective 7437 7438 Input Parameters: 7439 + mat - the matrix 7440 - bs - block size 7441 7442 Level: intermediate 7443 7444 Notes: 7445 Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix. 7446 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7447 7448 For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size 7449 is compatible with the matrix local sizes. 7450 7451 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()` 7452 @*/ 7453 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs) 7454 { 7455 PetscFunctionBegin; 7456 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7457 PetscValidLogicalCollectiveInt(mat, bs, 2); 7458 PetscCall(MatSetBlockSizes(mat, bs, bs)); 7459 PetscFunctionReturn(PETSC_SUCCESS); 7460 } 7461 7462 typedef struct { 7463 PetscInt n; 7464 IS *is; 7465 Mat *mat; 7466 PetscObjectState nonzerostate; 7467 Mat C; 7468 } EnvelopeData; 7469 7470 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata) 7471 { 7472 for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i])); 7473 PetscCall(PetscFree(edata->is)); 7474 PetscCall(PetscFree(edata)); 7475 return PETSC_SUCCESS; 7476 } 7477 7478 /* 7479 MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores 7480 the sizes of these blocks in the matrix. An individual block may lie over several processes. 7481 7482 Collective 7483 7484 Input Parameter: 7485 . mat - the matrix 7486 7487 Notes: 7488 There can be zeros within the blocks 7489 7490 The blocks can overlap between processes, including laying on more than two processes 7491 7492 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()` 7493 */ 7494 static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat) 7495 { 7496 PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend; 7497 PetscInt *diag, *odiag, sc; 7498 VecScatter scatter; 7499 PetscScalar *seqv; 7500 const PetscScalar *parv; 7501 const PetscInt *ia, *ja; 7502 PetscBool set, flag, done; 7503 Mat AA = mat, A; 7504 MPI_Comm comm; 7505 PetscMPIInt rank, size, tag; 7506 MPI_Status status; 7507 PetscContainer container; 7508 EnvelopeData *edata; 7509 Vec seq, par; 7510 IS isglobal; 7511 7512 PetscFunctionBegin; 7513 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7514 PetscCall(MatIsSymmetricKnown(mat, &set, &flag)); 7515 if (!set || !flag) { 7516 /* TODO: only needs nonzero structure of transpose */ 7517 PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA)); 7518 PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN)); 7519 } 7520 PetscCall(MatAIJGetLocalMat(AA, &A)); 7521 PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7522 PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix"); 7523 7524 PetscCall(MatGetLocalSize(mat, &n, NULL)); 7525 PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag)); 7526 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 7527 PetscCallMPI(MPI_Comm_size(comm, &size)); 7528 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7529 7530 PetscCall(PetscMalloc2(n, &sizes, n, &starts)); 7531 7532 if (rank > 0) { 7533 PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7534 PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7535 } 7536 PetscCall(MatGetOwnershipRange(mat, &rstart, NULL)); 7537 for (i = 0; i < n; i++) { 7538 env = PetscMax(env, ja[ia[i + 1] - 1]); 7539 II = rstart + i; 7540 if (env == II) { 7541 starts[lblocks] = tbs; 7542 sizes[lblocks++] = 1 + II - tbs; 7543 tbs = 1 + II; 7544 } 7545 } 7546 if (rank < size - 1) { 7547 PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm)); 7548 PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm)); 7549 } 7550 7551 PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7552 if (!set || !flag) PetscCall(MatDestroy(&AA)); 7553 PetscCall(MatDestroy(&A)); 7554 7555 PetscCall(PetscNew(&edata)); 7556 PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate)); 7557 edata->n = lblocks; 7558 /* create IS needed for extracting blocks from the original matrix */ 7559 PetscCall(PetscMalloc1(lblocks, &edata->is)); 7560 for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i])); 7561 7562 /* Create the resulting inverse matrix structure with preallocation information */ 7563 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C)); 7564 PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 7565 PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat)); 7566 PetscCall(MatSetType(edata->C, MATAIJ)); 7567 7568 /* Communicate the start and end of each row, from each block to the correct rank */ 7569 /* TODO: Use PetscSF instead of VecScatter */ 7570 for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i]; 7571 PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq)); 7572 PetscCall(VecGetArrayWrite(seq, &seqv)); 7573 for (PetscInt i = 0; i < lblocks; i++) { 7574 for (PetscInt j = 0; j < sizes[i]; j++) { 7575 seqv[cnt] = starts[i]; 7576 seqv[cnt + 1] = starts[i] + sizes[i]; 7577 cnt += 2; 7578 } 7579 } 7580 PetscCall(VecRestoreArrayWrite(seq, &seqv)); 7581 PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 7582 sc -= cnt; 7583 PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par)); 7584 PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal)); 7585 PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter)); 7586 PetscCall(ISDestroy(&isglobal)); 7587 PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7588 PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7589 PetscCall(VecScatterDestroy(&scatter)); 7590 PetscCall(VecDestroy(&seq)); 7591 PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend)); 7592 PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag)); 7593 PetscCall(VecGetArrayRead(par, &parv)); 7594 cnt = 0; 7595 PetscCall(MatGetSize(mat, NULL, &n)); 7596 for (PetscInt i = 0; i < mat->rmap->n; i++) { 7597 PetscInt start, end, d = 0, od = 0; 7598 7599 start = (PetscInt)PetscRealPart(parv[cnt]); 7600 end = (PetscInt)PetscRealPart(parv[cnt + 1]); 7601 cnt += 2; 7602 7603 if (start < cstart) { 7604 od += cstart - start + n - cend; 7605 d += cend - cstart; 7606 } else if (start < cend) { 7607 od += n - cend; 7608 d += cend - start; 7609 } else od += n - start; 7610 if (end <= cstart) { 7611 od -= cstart - end + n - cend; 7612 d -= cend - cstart; 7613 } else if (end < cend) { 7614 od -= n - cend; 7615 d -= cend - end; 7616 } else od -= n - end; 7617 7618 odiag[i] = od; 7619 diag[i] = d; 7620 } 7621 PetscCall(VecRestoreArrayRead(par, &parv)); 7622 PetscCall(VecDestroy(&par)); 7623 PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL)); 7624 PetscCall(PetscFree2(diag, odiag)); 7625 PetscCall(PetscFree2(sizes, starts)); 7626 7627 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container)); 7628 PetscCall(PetscContainerSetPointer(container, edata)); 7629 PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy)); 7630 PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container)); 7631 PetscCall(PetscObjectDereference((PetscObject)container)); 7632 PetscFunctionReturn(PETSC_SUCCESS); 7633 } 7634 7635 /*@ 7636 MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A 7637 7638 Collective 7639 7640 Input Parameters: 7641 + A - the matrix 7642 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine 7643 7644 Output Parameter: 7645 . C - matrix with inverted block diagonal of `A` 7646 7647 Level: advanced 7648 7649 Note: 7650 For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal. 7651 7652 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()` 7653 @*/ 7654 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C) 7655 { 7656 PetscContainer container; 7657 EnvelopeData *edata; 7658 PetscObjectState nonzerostate; 7659 7660 PetscFunctionBegin; 7661 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7662 if (!container) { 7663 PetscCall(MatComputeVariableBlockEnvelope(A)); 7664 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7665 } 7666 PetscCall(PetscContainerGetPointer(container, (void **)&edata)); 7667 PetscCall(MatGetNonzeroState(A, &nonzerostate)); 7668 PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure"); 7669 PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output"); 7670 7671 PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat)); 7672 *C = edata->C; 7673 7674 for (PetscInt i = 0; i < edata->n; i++) { 7675 Mat D; 7676 PetscScalar *dvalues; 7677 7678 PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D)); 7679 PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE)); 7680 PetscCall(MatSeqDenseInvert(D)); 7681 PetscCall(MatDenseGetArray(D, &dvalues)); 7682 PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES)); 7683 PetscCall(MatDestroy(&D)); 7684 } 7685 PetscCall(MatDestroySubMatrices(edata->n, &edata->mat)); 7686 PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY)); 7687 PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY)); 7688 PetscFunctionReturn(PETSC_SUCCESS); 7689 } 7690 7691 /*@ 7692 MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size 7693 7694 Logically Collective 7695 7696 Input Parameters: 7697 + mat - the matrix 7698 . nblocks - the number of blocks on this process, each block can only exist on a single process 7699 - bsizes - the block sizes 7700 7701 Level: intermediate 7702 7703 Notes: 7704 Currently used by `PCVPBJACOBI` for `MATAIJ` matrices 7705 7706 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. 7707 7708 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, 7709 `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI` 7710 @*/ 7711 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes) 7712 { 7713 PetscInt i, ncnt = 0, nlocal; 7714 7715 PetscFunctionBegin; 7716 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7717 PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero"); 7718 PetscCall(MatGetLocalSize(mat, &nlocal, NULL)); 7719 for (i = 0; i < nblocks; i++) ncnt += bsizes[i]; 7720 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); 7721 PetscCall(PetscFree(mat->bsizes)); 7722 mat->nblocks = nblocks; 7723 PetscCall(PetscMalloc1(nblocks, &mat->bsizes)); 7724 PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks)); 7725 PetscFunctionReturn(PETSC_SUCCESS); 7726 } 7727 7728 /*@C 7729 MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size 7730 7731 Logically Collective; No Fortran Support 7732 7733 Input Parameter: 7734 . mat - the matrix 7735 7736 Output Parameters: 7737 + nblocks - the number of blocks on this process 7738 - bsizes - the block sizes 7739 7740 Level: intermediate 7741 7742 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()` 7743 @*/ 7744 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes) 7745 { 7746 PetscFunctionBegin; 7747 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7748 *nblocks = mat->nblocks; 7749 *bsizes = mat->bsizes; 7750 PetscFunctionReturn(PETSC_SUCCESS); 7751 } 7752 7753 /*@ 7754 MatSetBlockSizes - Sets the matrix block row and column sizes. 7755 7756 Logically Collective 7757 7758 Input Parameters: 7759 + mat - the matrix 7760 . rbs - row block size 7761 - cbs - column block size 7762 7763 Level: intermediate 7764 7765 Notes: 7766 Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix. 7767 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7768 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7769 7770 For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes 7771 are compatible with the matrix local sizes. 7772 7773 The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`. 7774 7775 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()` 7776 @*/ 7777 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs) 7778 { 7779 PetscFunctionBegin; 7780 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7781 PetscValidLogicalCollectiveInt(mat, rbs, 2); 7782 PetscValidLogicalCollectiveInt(mat, cbs, 3); 7783 PetscTryTypeMethod(mat, setblocksizes, rbs, cbs); 7784 if (mat->rmap->refcnt) { 7785 ISLocalToGlobalMapping l2g = NULL; 7786 PetscLayout nmap = NULL; 7787 7788 PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap)); 7789 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g)); 7790 PetscCall(PetscLayoutDestroy(&mat->rmap)); 7791 mat->rmap = nmap; 7792 mat->rmap->mapping = l2g; 7793 } 7794 if (mat->cmap->refcnt) { 7795 ISLocalToGlobalMapping l2g = NULL; 7796 PetscLayout nmap = NULL; 7797 7798 PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap)); 7799 if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g)); 7800 PetscCall(PetscLayoutDestroy(&mat->cmap)); 7801 mat->cmap = nmap; 7802 mat->cmap->mapping = l2g; 7803 } 7804 PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs)); 7805 PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs)); 7806 PetscFunctionReturn(PETSC_SUCCESS); 7807 } 7808 7809 /*@ 7810 MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices 7811 7812 Logically Collective 7813 7814 Input Parameters: 7815 + mat - the matrix 7816 . fromRow - matrix from which to copy row block size 7817 - fromCol - matrix from which to copy column block size (can be same as fromRow) 7818 7819 Level: developer 7820 7821 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()` 7822 @*/ 7823 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol) 7824 { 7825 PetscFunctionBegin; 7826 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7827 PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2); 7828 PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3); 7829 if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs)); 7830 if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs)); 7831 PetscFunctionReturn(PETSC_SUCCESS); 7832 } 7833 7834 /*@ 7835 MatResidual - Default routine to calculate the residual r = b - Ax 7836 7837 Collective 7838 7839 Input Parameters: 7840 + mat - the matrix 7841 . b - the right-hand-side 7842 - x - the approximate solution 7843 7844 Output Parameter: 7845 . r - location to store the residual 7846 7847 Level: developer 7848 7849 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()` 7850 @*/ 7851 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r) 7852 { 7853 PetscFunctionBegin; 7854 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7855 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 7856 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 7857 PetscValidHeaderSpecific(r, VEC_CLASSID, 4); 7858 PetscValidType(mat, 1); 7859 MatCheckPreallocated(mat, 1); 7860 PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0)); 7861 if (!mat->ops->residual) { 7862 PetscCall(MatMult(mat, x, r)); 7863 PetscCall(VecAYPX(r, -1.0, b)); 7864 } else { 7865 PetscUseTypeMethod(mat, residual, b, x, r); 7866 } 7867 PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0)); 7868 PetscFunctionReturn(PETSC_SUCCESS); 7869 } 7870 7871 /*MC 7872 MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix 7873 7874 Synopsis: 7875 MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 7876 7877 Not Collective 7878 7879 Input Parameters: 7880 + A - the matrix 7881 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7882 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7883 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7884 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7885 always used. 7886 7887 Output Parameters: 7888 + n - number of local rows in the (possibly compressed) matrix 7889 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 7890 . ja - the column indices 7891 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7892 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7893 7894 Level: developer 7895 7896 Note: 7897 Use `MatRestoreRowIJF90()` when you no longer need access to the data 7898 7899 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()` 7900 M*/ 7901 7902 /*MC 7903 MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()` 7904 7905 Synopsis: 7906 MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 7907 7908 Not Collective 7909 7910 Input Parameters: 7911 + A - the matrix 7912 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7913 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7914 inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7915 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7916 always used. 7917 . n - number of local rows in the (possibly compressed) matrix 7918 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 7919 . ja - the column indices 7920 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7921 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7922 7923 Level: developer 7924 7925 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()` 7926 M*/ 7927 7928 /*@C 7929 MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix 7930 7931 Collective 7932 7933 Input Parameters: 7934 + mat - the matrix 7935 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7936 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7937 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7938 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7939 always used. 7940 7941 Output Parameters: 7942 + n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed 7943 . 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 7944 . ja - the column indices, use `NULL` if not needed 7945 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7946 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7947 7948 Level: developer 7949 7950 Notes: 7951 You CANNOT change any of the ia[] or ja[] values. 7952 7953 Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values. 7954 7955 Fortran Notes: 7956 Use 7957 .vb 7958 PetscInt, pointer :: ia(:),ja(:) 7959 call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr) 7960 ! Access the ith and jth entries via ia(i) and ja(j) 7961 .ve 7962 `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()` 7963 7964 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()` 7965 @*/ 7966 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7967 { 7968 PetscFunctionBegin; 7969 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7970 PetscValidType(mat, 1); 7971 if (n) PetscValidIntPointer(n, 5); 7972 if (ia) PetscValidPointer(ia, 6); 7973 if (ja) PetscValidPointer(ja, 7); 7974 if (done) PetscValidBoolPointer(done, 8); 7975 MatCheckPreallocated(mat, 1); 7976 if (!mat->ops->getrowij && done) *done = PETSC_FALSE; 7977 else { 7978 if (done) *done = PETSC_TRUE; 7979 PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0)); 7980 PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done); 7981 PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0)); 7982 } 7983 PetscFunctionReturn(PETSC_SUCCESS); 7984 } 7985 7986 /*@C 7987 MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices. 7988 7989 Collective 7990 7991 Input Parameters: 7992 + mat - the matrix 7993 . shift - 1 or zero indicating we want the indices starting at 0 or 1 7994 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be 7995 symmetrized 7996 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7997 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7998 always used. 7999 . n - number of columns in the (possibly compressed) matrix 8000 . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix 8001 - ja - the row indices 8002 8003 Output Parameter: 8004 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned 8005 8006 Level: developer 8007 8008 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 8009 @*/ 8010 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8011 { 8012 PetscFunctionBegin; 8013 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8014 PetscValidType(mat, 1); 8015 PetscValidIntPointer(n, 5); 8016 if (ia) PetscValidPointer(ia, 6); 8017 if (ja) PetscValidPointer(ja, 7); 8018 PetscValidBoolPointer(done, 8); 8019 MatCheckPreallocated(mat, 1); 8020 if (!mat->ops->getcolumnij) *done = PETSC_FALSE; 8021 else { 8022 *done = PETSC_TRUE; 8023 PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8024 } 8025 PetscFunctionReturn(PETSC_SUCCESS); 8026 } 8027 8028 /*@C 8029 MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`. 8030 8031 Collective 8032 8033 Input Parameters: 8034 + mat - the matrix 8035 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8036 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8037 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8038 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8039 always used. 8040 . n - size of (possibly compressed) matrix 8041 . ia - the row pointers 8042 - ja - the column indices 8043 8044 Output Parameter: 8045 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8046 8047 Level: developer 8048 8049 Note: 8050 This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental 8051 us of the array after it has been restored. If you pass `NULL`, it will 8052 not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid. 8053 8054 Fortran Notes: 8055 `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()` 8056 8057 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()` 8058 @*/ 8059 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8060 { 8061 PetscFunctionBegin; 8062 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8063 PetscValidType(mat, 1); 8064 if (ia) PetscValidPointer(ia, 6); 8065 if (ja) PetscValidPointer(ja, 7); 8066 if (done) PetscValidBoolPointer(done, 8); 8067 MatCheckPreallocated(mat, 1); 8068 8069 if (!mat->ops->restorerowij && done) *done = PETSC_FALSE; 8070 else { 8071 if (done) *done = PETSC_TRUE; 8072 PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8073 if (n) *n = 0; 8074 if (ia) *ia = NULL; 8075 if (ja) *ja = NULL; 8076 } 8077 PetscFunctionReturn(PETSC_SUCCESS); 8078 } 8079 8080 /*@C 8081 MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`. 8082 8083 Collective 8084 8085 Input Parameters: 8086 + mat - the matrix 8087 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8088 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8089 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8090 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8091 always used. 8092 8093 Output Parameters: 8094 + n - size of (possibly compressed) matrix 8095 . ia - the column pointers 8096 . ja - the row indices 8097 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8098 8099 Level: developer 8100 8101 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()` 8102 @*/ 8103 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8104 { 8105 PetscFunctionBegin; 8106 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8107 PetscValidType(mat, 1); 8108 if (ia) PetscValidPointer(ia, 6); 8109 if (ja) PetscValidPointer(ja, 7); 8110 PetscValidBoolPointer(done, 8); 8111 MatCheckPreallocated(mat, 1); 8112 8113 if (!mat->ops->restorecolumnij) *done = PETSC_FALSE; 8114 else { 8115 *done = PETSC_TRUE; 8116 PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8117 if (n) *n = 0; 8118 if (ia) *ia = NULL; 8119 if (ja) *ja = NULL; 8120 } 8121 PetscFunctionReturn(PETSC_SUCCESS); 8122 } 8123 8124 /*@C 8125 MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or 8126 `MatGetColumnIJ()`. 8127 8128 Collective 8129 8130 Input Parameters: 8131 + mat - the matrix 8132 . ncolors - maximum color value 8133 . n - number of entries in colorarray 8134 - colorarray - array indicating color for each column 8135 8136 Output Parameter: 8137 . iscoloring - coloring generated using colorarray information 8138 8139 Level: developer 8140 8141 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()` 8142 @*/ 8143 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring) 8144 { 8145 PetscFunctionBegin; 8146 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8147 PetscValidType(mat, 1); 8148 PetscValidIntPointer(colorarray, 4); 8149 PetscValidPointer(iscoloring, 5); 8150 MatCheckPreallocated(mat, 1); 8151 8152 if (!mat->ops->coloringpatch) { 8153 PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring)); 8154 } else { 8155 PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring); 8156 } 8157 PetscFunctionReturn(PETSC_SUCCESS); 8158 } 8159 8160 /*@ 8161 MatSetUnfactored - Resets a factored matrix to be treated as unfactored. 8162 8163 Logically Collective 8164 8165 Input Parameter: 8166 . mat - the factored matrix to be reset 8167 8168 Level: developer 8169 8170 Notes: 8171 This routine should be used only with factored matrices formed by in-place 8172 factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE` 8173 format). This option can save memory, for example, when solving nonlinear 8174 systems with a matrix-free Newton-Krylov method and a matrix-based, in-place 8175 ILU(0) preconditioner. 8176 8177 One can specify in-place ILU(0) factorization by calling 8178 .vb 8179 PCType(pc,PCILU); 8180 PCFactorSeUseInPlace(pc); 8181 .ve 8182 or by using the options -pc_type ilu -pc_factor_in_place 8183 8184 In-place factorization ILU(0) can also be used as a local 8185 solver for the blocks within the block Jacobi or additive Schwarz 8186 methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc 8187 for details on setting local solver options. 8188 8189 Most users should employ the `KSP` interface for linear solvers 8190 instead of working directly with matrix algebra routines such as this. 8191 See, e.g., `KSPCreate()`. 8192 8193 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()` 8194 @*/ 8195 PetscErrorCode MatSetUnfactored(Mat mat) 8196 { 8197 PetscFunctionBegin; 8198 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8199 PetscValidType(mat, 1); 8200 MatCheckPreallocated(mat, 1); 8201 mat->factortype = MAT_FACTOR_NONE; 8202 if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS); 8203 PetscUseTypeMethod(mat, setunfactored); 8204 PetscFunctionReturn(PETSC_SUCCESS); 8205 } 8206 8207 /*MC 8208 MatDenseGetArrayF90 - Accesses a matrix array from Fortran 8209 8210 Synopsis: 8211 MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8212 8213 Not Collective 8214 8215 Input Parameter: 8216 . x - matrix 8217 8218 Output Parameters: 8219 + xx_v - the Fortran pointer to the array 8220 - ierr - error code 8221 8222 Example of Usage: 8223 .vb 8224 PetscScalar, pointer xx_v(:,:) 8225 .... 8226 call MatDenseGetArrayF90(x,xx_v,ierr) 8227 a = xx_v(3) 8228 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8229 .ve 8230 8231 Level: advanced 8232 8233 .seealso: [](ch_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()` 8234 M*/ 8235 8236 /*MC 8237 MatDenseRestoreArrayF90 - Restores a matrix array that has been 8238 accessed with `MatDenseGetArrayF90()`. 8239 8240 Synopsis: 8241 MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8242 8243 Not Collective 8244 8245 Input Parameters: 8246 + x - matrix 8247 - xx_v - the Fortran90 pointer to the array 8248 8249 Output Parameter: 8250 . ierr - error code 8251 8252 Example of Usage: 8253 .vb 8254 PetscScalar, pointer xx_v(:,:) 8255 .... 8256 call MatDenseGetArrayF90(x,xx_v,ierr) 8257 a = xx_v(3) 8258 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8259 .ve 8260 8261 Level: advanced 8262 8263 .seealso: [](ch_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()` 8264 M*/ 8265 8266 /*MC 8267 MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran. 8268 8269 Synopsis: 8270 MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8271 8272 Not Collective 8273 8274 Input Parameter: 8275 . x - matrix 8276 8277 Output Parameters: 8278 + xx_v - the Fortran pointer to the array 8279 - ierr - error code 8280 8281 Example of Usage: 8282 .vb 8283 PetscScalar, pointer xx_v(:) 8284 .... 8285 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8286 a = xx_v(3) 8287 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8288 .ve 8289 8290 Level: advanced 8291 8292 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()` 8293 M*/ 8294 8295 /*MC 8296 MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been 8297 accessed with `MatSeqAIJGetArrayF90()`. 8298 8299 Synopsis: 8300 MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8301 8302 Not Collective 8303 8304 Input Parameters: 8305 + x - matrix 8306 - xx_v - the Fortran90 pointer to the array 8307 8308 Output Parameter: 8309 . ierr - error code 8310 8311 Example of Usage: 8312 .vb 8313 PetscScalar, pointer xx_v(:) 8314 .... 8315 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8316 a = xx_v(3) 8317 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8318 .ve 8319 8320 Level: advanced 8321 8322 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()` 8323 M*/ 8324 8325 /*@ 8326 MatCreateSubMatrix - Gets a single submatrix on the same number of processors 8327 as the original matrix. 8328 8329 Collective 8330 8331 Input Parameters: 8332 + mat - the original matrix 8333 . isrow - parallel `IS` containing the rows this processor should obtain 8334 . 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. 8335 - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 8336 8337 Output Parameter: 8338 . newmat - the new submatrix, of the same type as the original matrix 8339 8340 Level: advanced 8341 8342 Notes: 8343 The submatrix will be able to be multiplied with vectors using the same layout as `iscol`. 8344 8345 Some matrix types place restrictions on the row and column indices, such 8346 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; 8347 for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row. 8348 8349 The index sets may not have duplicate entries. 8350 8351 The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`, 8352 the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls 8353 to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX` 8354 will reuse the matrix generated the first time. You should call `MatDestroy()` on `newmat` when 8355 you are finished using it. 8356 8357 The communicator of the newly obtained matrix is ALWAYS the same as the communicator of 8358 the input matrix. 8359 8360 If `iscol` is `NULL` then all columns are obtained (not supported in Fortran). 8361 8362 Example usage: 8363 Consider the following 8x8 matrix with 34 non-zero values, that is 8364 assembled across 3 processors. Let's assume that proc0 owns 3 rows, 8365 proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 8366 as follows 8367 .vb 8368 1 2 0 | 0 3 0 | 0 4 8369 Proc0 0 5 6 | 7 0 0 | 8 0 8370 9 0 10 | 11 0 0 | 12 0 8371 ------------------------------------- 8372 13 0 14 | 15 16 17 | 0 0 8373 Proc1 0 18 0 | 19 20 21 | 0 0 8374 0 0 0 | 22 23 0 | 24 0 8375 ------------------------------------- 8376 Proc2 25 26 27 | 0 0 28 | 29 0 8377 30 0 0 | 31 32 33 | 0 34 8378 .ve 8379 8380 Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6]. The resulting submatrix is 8381 8382 .vb 8383 2 0 | 0 3 0 | 0 8384 Proc0 5 6 | 7 0 0 | 8 8385 ------------------------------- 8386 Proc1 18 0 | 19 20 21 | 0 8387 ------------------------------- 8388 Proc2 26 27 | 0 0 28 | 29 8389 0 0 | 31 32 33 | 0 8390 .ve 8391 8392 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()` 8393 @*/ 8394 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat) 8395 { 8396 PetscMPIInt size; 8397 Mat *local; 8398 IS iscoltmp; 8399 PetscBool flg; 8400 8401 PetscFunctionBegin; 8402 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8403 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 8404 if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 8405 PetscValidPointer(newmat, 5); 8406 if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5); 8407 PetscValidType(mat, 1); 8408 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8409 PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX"); 8410 8411 MatCheckPreallocated(mat, 1); 8412 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8413 8414 if (!iscol || isrow == iscol) { 8415 PetscBool stride; 8416 PetscMPIInt grabentirematrix = 0, grab; 8417 PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride)); 8418 if (stride) { 8419 PetscInt first, step, n, rstart, rend; 8420 PetscCall(ISStrideGetInfo(isrow, &first, &step)); 8421 if (step == 1) { 8422 PetscCall(MatGetOwnershipRange(mat, &rstart, &rend)); 8423 if (rstart == first) { 8424 PetscCall(ISGetLocalSize(isrow, &n)); 8425 if (n == rend - rstart) grabentirematrix = 1; 8426 } 8427 } 8428 } 8429 PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat))); 8430 if (grab) { 8431 PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n")); 8432 if (cll == MAT_INITIAL_MATRIX) { 8433 *newmat = mat; 8434 PetscCall(PetscObjectReference((PetscObject)mat)); 8435 } 8436 PetscFunctionReturn(PETSC_SUCCESS); 8437 } 8438 } 8439 8440 if (!iscol) { 8441 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp)); 8442 } else { 8443 iscoltmp = iscol; 8444 } 8445 8446 /* if original matrix is on just one processor then use submatrix generated */ 8447 if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) { 8448 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat)); 8449 goto setproperties; 8450 } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) { 8451 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local)); 8452 *newmat = *local; 8453 PetscCall(PetscFree(local)); 8454 goto setproperties; 8455 } else if (!mat->ops->createsubmatrix) { 8456 /* Create a new matrix type that implements the operation using the full matrix */ 8457 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8458 switch (cll) { 8459 case MAT_INITIAL_MATRIX: 8460 PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat)); 8461 break; 8462 case MAT_REUSE_MATRIX: 8463 PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp)); 8464 break; 8465 default: 8466 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX"); 8467 } 8468 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8469 goto setproperties; 8470 } 8471 8472 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8473 PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat); 8474 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8475 8476 setproperties: 8477 PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg)); 8478 if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat)); 8479 if (!iscol) PetscCall(ISDestroy(&iscoltmp)); 8480 if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat)); 8481 PetscFunctionReturn(PETSC_SUCCESS); 8482 } 8483 8484 /*@ 8485 MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix 8486 8487 Not Collective 8488 8489 Input Parameters: 8490 + A - the matrix we wish to propagate options from 8491 - B - the matrix we wish to propagate options to 8492 8493 Level: beginner 8494 8495 Note: 8496 Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL` 8497 8498 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 8499 @*/ 8500 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B) 8501 { 8502 PetscFunctionBegin; 8503 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8504 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 8505 B->symmetry_eternal = A->symmetry_eternal; 8506 B->structural_symmetry_eternal = A->structural_symmetry_eternal; 8507 B->symmetric = A->symmetric; 8508 B->structurally_symmetric = A->structurally_symmetric; 8509 B->spd = A->spd; 8510 B->hermitian = A->hermitian; 8511 PetscFunctionReturn(PETSC_SUCCESS); 8512 } 8513 8514 /*@ 8515 MatStashSetInitialSize - sets the sizes of the matrix stash, that is 8516 used during the assembly process to store values that belong to 8517 other processors. 8518 8519 Not Collective 8520 8521 Input Parameters: 8522 + mat - the matrix 8523 . size - the initial size of the stash. 8524 - bsize - the initial size of the block-stash(if used). 8525 8526 Options Database Keys: 8527 + -matstash_initial_size <size> or <size0,size1,...sizep-1> - set initial size 8528 - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1> - set initial block size 8529 8530 Level: intermediate 8531 8532 Notes: 8533 The block-stash is used for values set with `MatSetValuesBlocked()` while 8534 the stash is used for values set with `MatSetValues()` 8535 8536 Run with the option -info and look for output of the form 8537 MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs. 8538 to determine the appropriate value, MM, to use for size and 8539 MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs. 8540 to determine the value, BMM to use for bsize 8541 8542 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()` 8543 @*/ 8544 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize) 8545 { 8546 PetscFunctionBegin; 8547 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8548 PetscValidType(mat, 1); 8549 PetscCall(MatStashSetInitialSize_Private(&mat->stash, size)); 8550 PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize)); 8551 PetscFunctionReturn(PETSC_SUCCESS); 8552 } 8553 8554 /*@ 8555 MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of 8556 the matrix 8557 8558 Neighbor-wise Collective 8559 8560 Input Parameters: 8561 + A - the matrix 8562 . x - the vector to be multiplied by the interpolation operator 8563 - y - the vector to be added to the result 8564 8565 Output Parameter: 8566 . w - the resulting vector 8567 8568 Level: intermediate 8569 8570 Notes: 8571 `w` may be the same vector as `y`. 8572 8573 This allows one to use either the restriction or interpolation (its transpose) 8574 matrix to do the interpolation 8575 8576 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8577 @*/ 8578 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w) 8579 { 8580 PetscInt M, N, Ny; 8581 8582 PetscFunctionBegin; 8583 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8584 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8585 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8586 PetscValidHeaderSpecific(w, VEC_CLASSID, 4); 8587 PetscCall(MatGetSize(A, &M, &N)); 8588 PetscCall(VecGetSize(y, &Ny)); 8589 if (M == Ny) { 8590 PetscCall(MatMultAdd(A, x, y, w)); 8591 } else { 8592 PetscCall(MatMultTransposeAdd(A, x, y, w)); 8593 } 8594 PetscFunctionReturn(PETSC_SUCCESS); 8595 } 8596 8597 /*@ 8598 MatInterpolate - y = A*x or A'*x depending on the shape of 8599 the matrix 8600 8601 Neighbor-wise Collective 8602 8603 Input Parameters: 8604 + A - the matrix 8605 - x - the vector to be interpolated 8606 8607 Output Parameter: 8608 . y - the resulting vector 8609 8610 Level: intermediate 8611 8612 Note: 8613 This allows one to use either the restriction or interpolation (its transpose) 8614 matrix to do the interpolation 8615 8616 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8617 @*/ 8618 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y) 8619 { 8620 PetscInt M, N, Ny; 8621 8622 PetscFunctionBegin; 8623 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8624 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8625 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8626 PetscCall(MatGetSize(A, &M, &N)); 8627 PetscCall(VecGetSize(y, &Ny)); 8628 if (M == Ny) { 8629 PetscCall(MatMult(A, x, y)); 8630 } else { 8631 PetscCall(MatMultTranspose(A, x, y)); 8632 } 8633 PetscFunctionReturn(PETSC_SUCCESS); 8634 } 8635 8636 /*@ 8637 MatRestrict - y = A*x or A'*x 8638 8639 Neighbor-wise Collective 8640 8641 Input Parameters: 8642 + A - the matrix 8643 - x - the vector to be restricted 8644 8645 Output Parameter: 8646 . y - the resulting vector 8647 8648 Level: intermediate 8649 8650 Note: 8651 This allows one to use either the restriction or interpolation (its transpose) 8652 matrix to do the restriction 8653 8654 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG` 8655 @*/ 8656 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y) 8657 { 8658 PetscInt M, N, Ny; 8659 8660 PetscFunctionBegin; 8661 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8662 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8663 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8664 PetscCall(MatGetSize(A, &M, &N)); 8665 PetscCall(VecGetSize(y, &Ny)); 8666 if (M == Ny) { 8667 PetscCall(MatMult(A, x, y)); 8668 } else { 8669 PetscCall(MatMultTranspose(A, x, y)); 8670 } 8671 PetscFunctionReturn(PETSC_SUCCESS); 8672 } 8673 8674 /*@ 8675 MatMatInterpolateAdd - Y = W + A*X or W + A'*X 8676 8677 Neighbor-wise Collective 8678 8679 Input Parameters: 8680 + A - the matrix 8681 . x - the input dense matrix to be multiplied 8682 - w - the input dense matrix to be added to the result 8683 8684 Output Parameter: 8685 . y - the output dense matrix 8686 8687 Level: intermediate 8688 8689 Note: 8690 This allows one to use either the restriction or interpolation (its transpose) 8691 matrix to do the interpolation. y matrix can be reused if already created with the proper sizes, 8692 otherwise it will be recreated. y must be initialized to `NULL` if not supplied. 8693 8694 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG` 8695 @*/ 8696 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y) 8697 { 8698 PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0; 8699 PetscBool trans = PETSC_TRUE; 8700 MatReuse reuse = MAT_INITIAL_MATRIX; 8701 8702 PetscFunctionBegin; 8703 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8704 PetscValidHeaderSpecific(x, MAT_CLASSID, 2); 8705 PetscValidType(x, 2); 8706 if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3); 8707 if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4); 8708 PetscCall(MatGetSize(A, &M, &N)); 8709 PetscCall(MatGetSize(x, &Mx, &Nx)); 8710 if (N == Mx) trans = PETSC_FALSE; 8711 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); 8712 Mo = trans ? N : M; 8713 if (*y) { 8714 PetscCall(MatGetSize(*y, &My, &Ny)); 8715 if (Mo == My && Nx == Ny) { 8716 reuse = MAT_REUSE_MATRIX; 8717 } else { 8718 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); 8719 PetscCall(MatDestroy(y)); 8720 } 8721 } 8722 8723 if (w && *y == w) { /* this is to minimize changes in PCMG */ 8724 PetscBool flg; 8725 8726 PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w)); 8727 if (w) { 8728 PetscInt My, Ny, Mw, Nw; 8729 8730 PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg)); 8731 PetscCall(MatGetSize(*y, &My, &Ny)); 8732 PetscCall(MatGetSize(w, &Mw, &Nw)); 8733 if (!flg || My != Mw || Ny != Nw) w = NULL; 8734 } 8735 if (!w) { 8736 PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w)); 8737 PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w)); 8738 PetscCall(PetscObjectDereference((PetscObject)w)); 8739 } else { 8740 PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN)); 8741 } 8742 } 8743 if (!trans) { 8744 PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8745 } else { 8746 PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8747 } 8748 if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN)); 8749 PetscFunctionReturn(PETSC_SUCCESS); 8750 } 8751 8752 /*@ 8753 MatMatInterpolate - Y = A*X or A'*X 8754 8755 Neighbor-wise Collective 8756 8757 Input Parameters: 8758 + A - the matrix 8759 - x - the input dense matrix 8760 8761 Output Parameter: 8762 . y - the output dense matrix 8763 8764 Level: intermediate 8765 8766 Note: 8767 This allows one to use either the restriction or interpolation (its transpose) 8768 matrix to do the interpolation. y matrix can be reused if already created with the proper sizes, 8769 otherwise it will be recreated. y must be initialized to `NULL` if not supplied. 8770 8771 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG` 8772 @*/ 8773 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y) 8774 { 8775 PetscFunctionBegin; 8776 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8777 PetscFunctionReturn(PETSC_SUCCESS); 8778 } 8779 8780 /*@ 8781 MatMatRestrict - Y = A*X or A'*X 8782 8783 Neighbor-wise Collective 8784 8785 Input Parameters: 8786 + A - the matrix 8787 - x - the input dense matrix 8788 8789 Output Parameter: 8790 . y - the output dense matrix 8791 8792 Level: intermediate 8793 8794 Note: 8795 This allows one to use either the restriction or interpolation (its transpose) 8796 matrix to do the restriction. y matrix can be reused if already created with the proper sizes, 8797 otherwise it will be recreated. y must be initialized to `NULL` if not supplied. 8798 8799 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG` 8800 @*/ 8801 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y) 8802 { 8803 PetscFunctionBegin; 8804 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8805 PetscFunctionReturn(PETSC_SUCCESS); 8806 } 8807 8808 /*@ 8809 MatGetNullSpace - retrieves the null space of a matrix. 8810 8811 Logically Collective 8812 8813 Input Parameters: 8814 + mat - the matrix 8815 - nullsp - the null space object 8816 8817 Level: developer 8818 8819 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace` 8820 @*/ 8821 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp) 8822 { 8823 PetscFunctionBegin; 8824 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8825 PetscValidPointer(nullsp, 2); 8826 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp; 8827 PetscFunctionReturn(PETSC_SUCCESS); 8828 } 8829 8830 /*@ 8831 MatSetNullSpace - attaches a null space to a matrix. 8832 8833 Logically Collective 8834 8835 Input Parameters: 8836 + mat - the matrix 8837 - nullsp - the null space object 8838 8839 Level: advanced 8840 8841 Notes: 8842 This null space is used by the `KSP` linear solvers to solve singular systems. 8843 8844 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` 8845 8846 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 8847 to zero but the linear system will still be solved in a least squares sense. 8848 8849 The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that 8850 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). 8851 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 8852 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 8853 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). 8854 This \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix. 8855 8856 If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called 8857 `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this 8858 routine also automatically calls `MatSetTransposeNullSpace()`. 8859 8860 The user should call `MatNullSpaceDestroy()`. 8861 8862 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, 8863 `KSPSetPCSide()` 8864 @*/ 8865 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp) 8866 { 8867 PetscFunctionBegin; 8868 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8869 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8870 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8871 PetscCall(MatNullSpaceDestroy(&mat->nullsp)); 8872 mat->nullsp = nullsp; 8873 if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp)); 8874 PetscFunctionReturn(PETSC_SUCCESS); 8875 } 8876 8877 /*@ 8878 MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix. 8879 8880 Logically Collective 8881 8882 Input Parameters: 8883 + mat - the matrix 8884 - nullsp - the null space object 8885 8886 Level: developer 8887 8888 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()` 8889 @*/ 8890 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp) 8891 { 8892 PetscFunctionBegin; 8893 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8894 PetscValidType(mat, 1); 8895 PetscValidPointer(nullsp, 2); 8896 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp; 8897 PetscFunctionReturn(PETSC_SUCCESS); 8898 } 8899 8900 /*@ 8901 MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix 8902 8903 Logically Collective 8904 8905 Input Parameters: 8906 + mat - the matrix 8907 - nullsp - the null space object 8908 8909 Level: advanced 8910 8911 Notes: 8912 This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning. 8913 8914 See `MatSetNullSpace()` 8915 8916 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()` 8917 @*/ 8918 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp) 8919 { 8920 PetscFunctionBegin; 8921 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8922 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8923 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8924 PetscCall(MatNullSpaceDestroy(&mat->transnullsp)); 8925 mat->transnullsp = nullsp; 8926 PetscFunctionReturn(PETSC_SUCCESS); 8927 } 8928 8929 /*@ 8930 MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions 8931 This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix. 8932 8933 Logically Collective 8934 8935 Input Parameters: 8936 + mat - the matrix 8937 - nullsp - the null space object 8938 8939 Level: advanced 8940 8941 Notes: 8942 Overwrites any previous near null space that may have been attached 8943 8944 You can remove the null space by calling this routine with an nullsp of `NULL` 8945 8946 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()` 8947 @*/ 8948 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp) 8949 { 8950 PetscFunctionBegin; 8951 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8952 PetscValidType(mat, 1); 8953 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8954 MatCheckPreallocated(mat, 1); 8955 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8956 PetscCall(MatNullSpaceDestroy(&mat->nearnullsp)); 8957 mat->nearnullsp = nullsp; 8958 PetscFunctionReturn(PETSC_SUCCESS); 8959 } 8960 8961 /*@ 8962 MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()` 8963 8964 Not Collective 8965 8966 Input Parameter: 8967 . mat - the matrix 8968 8969 Output Parameter: 8970 . nullsp - the null space object, `NULL` if not set 8971 8972 Level: advanced 8973 8974 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()` 8975 @*/ 8976 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp) 8977 { 8978 PetscFunctionBegin; 8979 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8980 PetscValidType(mat, 1); 8981 PetscValidPointer(nullsp, 2); 8982 MatCheckPreallocated(mat, 1); 8983 *nullsp = mat->nearnullsp; 8984 PetscFunctionReturn(PETSC_SUCCESS); 8985 } 8986 8987 /*@C 8988 MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix. 8989 8990 Collective 8991 8992 Input Parameters: 8993 + mat - the matrix 8994 . row - row/column permutation 8995 - info - information on desired factorization process 8996 8997 Level: developer 8998 8999 Notes: 9000 Probably really in-place only when level of fill is zero, otherwise allocates 9001 new space to store factored matrix and deletes previous memory. 9002 9003 Most users should employ the `KSP` interface for linear solvers 9004 instead of working directly with matrix algebra routines such as this. 9005 See, e.g., `KSPCreate()`. 9006 9007 Developer Notes: 9008 The Fortran interface is not autogenerated as the 9009 interface definition cannot be generated correctly [due to `MatFactorInfo`] 9010 9011 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 9012 @*/ 9013 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info) 9014 { 9015 PetscFunctionBegin; 9016 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9017 PetscValidType(mat, 1); 9018 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 9019 PetscValidPointer(info, 3); 9020 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 9021 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 9022 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 9023 MatCheckPreallocated(mat, 1); 9024 PetscUseTypeMethod(mat, iccfactor, row, info); 9025 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9026 PetscFunctionReturn(PETSC_SUCCESS); 9027 } 9028 9029 /*@ 9030 MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the 9031 ghosted ones. 9032 9033 Not Collective 9034 9035 Input Parameters: 9036 + mat - the matrix 9037 - diag - the diagonal values, including ghost ones 9038 9039 Level: developer 9040 9041 Notes: 9042 Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices 9043 9044 This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()` 9045 9046 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 9047 @*/ 9048 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag) 9049 { 9050 PetscMPIInt size; 9051 9052 PetscFunctionBegin; 9053 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9054 PetscValidHeaderSpecific(diag, VEC_CLASSID, 2); 9055 PetscValidType(mat, 1); 9056 9057 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled"); 9058 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 9059 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 9060 if (size == 1) { 9061 PetscInt n, m; 9062 PetscCall(VecGetSize(diag, &n)); 9063 PetscCall(MatGetSize(mat, NULL, &m)); 9064 PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions"); 9065 PetscCall(MatDiagonalScale(mat, NULL, diag)); 9066 } else { 9067 PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag)); 9068 } 9069 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 9070 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9071 PetscFunctionReturn(PETSC_SUCCESS); 9072 } 9073 9074 /*@ 9075 MatGetInertia - Gets the inertia from a factored matrix 9076 9077 Collective 9078 9079 Input Parameter: 9080 . mat - the matrix 9081 9082 Output Parameters: 9083 + nneg - number of negative eigenvalues 9084 . nzero - number of zero eigenvalues 9085 - npos - number of positive eigenvalues 9086 9087 Level: advanced 9088 9089 Note: 9090 Matrix must have been factored by `MatCholeskyFactor()` 9091 9092 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()` 9093 @*/ 9094 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos) 9095 { 9096 PetscFunctionBegin; 9097 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9098 PetscValidType(mat, 1); 9099 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9100 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled"); 9101 PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos); 9102 PetscFunctionReturn(PETSC_SUCCESS); 9103 } 9104 9105 /*@C 9106 MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors 9107 9108 Neighbor-wise Collective 9109 9110 Input Parameters: 9111 + mat - the factored matrix obtained with `MatGetFactor()` 9112 - b - the right-hand-side vectors 9113 9114 Output Parameter: 9115 . x - the result vectors 9116 9117 Level: developer 9118 9119 Note: 9120 The vectors `b` and `x` cannot be the same. I.e., one cannot 9121 call `MatSolves`(A,x,x). 9122 9123 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()` 9124 @*/ 9125 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x) 9126 { 9127 PetscFunctionBegin; 9128 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9129 PetscValidType(mat, 1); 9130 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 9131 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9132 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 9133 9134 MatCheckPreallocated(mat, 1); 9135 PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0)); 9136 PetscUseTypeMethod(mat, solves, b, x); 9137 PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0)); 9138 PetscFunctionReturn(PETSC_SUCCESS); 9139 } 9140 9141 /*@ 9142 MatIsSymmetric - Test whether a matrix is symmetric 9143 9144 Collective 9145 9146 Input Parameters: 9147 + A - the matrix to test 9148 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose) 9149 9150 Output Parameter: 9151 . flg - the result 9152 9153 Level: intermediate 9154 9155 Notes: 9156 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9157 9158 If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()` 9159 9160 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9161 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9162 9163 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`, 9164 `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL` 9165 @*/ 9166 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg) 9167 { 9168 PetscFunctionBegin; 9169 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9170 PetscValidBoolPointer(flg, 3); 9171 9172 if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE; 9173 else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE; 9174 else { 9175 PetscUseTypeMethod(A, issymmetric, tol, flg); 9176 if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg)); 9177 } 9178 PetscFunctionReturn(PETSC_SUCCESS); 9179 } 9180 9181 /*@ 9182 MatIsHermitian - Test whether a matrix is Hermitian 9183 9184 Collective 9185 9186 Input Parameters: 9187 + A - the matrix to test 9188 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian) 9189 9190 Output Parameter: 9191 . flg - the result 9192 9193 Level: intermediate 9194 9195 Notes: 9196 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9197 9198 If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()` 9199 9200 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9201 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`) 9202 9203 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, 9204 `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL` 9205 @*/ 9206 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg) 9207 { 9208 PetscFunctionBegin; 9209 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9210 PetscValidBoolPointer(flg, 3); 9211 9212 if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE; 9213 else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE; 9214 else { 9215 PetscUseTypeMethod(A, ishermitian, tol, flg); 9216 if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg)); 9217 } 9218 PetscFunctionReturn(PETSC_SUCCESS); 9219 } 9220 9221 /*@ 9222 MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state 9223 9224 Not Collective 9225 9226 Input Parameter: 9227 . A - the matrix to check 9228 9229 Output Parameters: 9230 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid) 9231 - flg - the result (only valid if set is `PETSC_TRUE`) 9232 9233 Level: advanced 9234 9235 Notes: 9236 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()` 9237 if you want it explicitly checked 9238 9239 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9240 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9241 9242 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9243 @*/ 9244 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9245 { 9246 PetscFunctionBegin; 9247 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9248 PetscValidBoolPointer(set, 2); 9249 PetscValidBoolPointer(flg, 3); 9250 if (A->symmetric != PETSC_BOOL3_UNKNOWN) { 9251 *set = PETSC_TRUE; 9252 *flg = PetscBool3ToBool(A->symmetric); 9253 } else { 9254 *set = PETSC_FALSE; 9255 } 9256 PetscFunctionReturn(PETSC_SUCCESS); 9257 } 9258 9259 /*@ 9260 MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state 9261 9262 Not Collective 9263 9264 Input Parameter: 9265 . A - the matrix to check 9266 9267 Output Parameters: 9268 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid) 9269 - flg - the result (only valid if set is `PETSC_TRUE`) 9270 9271 Level: advanced 9272 9273 Notes: 9274 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). 9275 9276 One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD 9277 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`) 9278 9279 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9280 @*/ 9281 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg) 9282 { 9283 PetscFunctionBegin; 9284 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9285 PetscValidBoolPointer(set, 2); 9286 PetscValidBoolPointer(flg, 3); 9287 if (A->spd != PETSC_BOOL3_UNKNOWN) { 9288 *set = PETSC_TRUE; 9289 *flg = PetscBool3ToBool(A->spd); 9290 } else { 9291 *set = PETSC_FALSE; 9292 } 9293 PetscFunctionReturn(PETSC_SUCCESS); 9294 } 9295 9296 /*@ 9297 MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state 9298 9299 Not Collective 9300 9301 Input Parameter: 9302 . A - the matrix to check 9303 9304 Output Parameters: 9305 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid) 9306 - flg - the result (only valid if set is `PETSC_TRUE`) 9307 9308 Level: advanced 9309 9310 Notes: 9311 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()` 9312 if you want it explicitly checked 9313 9314 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9315 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9316 9317 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()` 9318 @*/ 9319 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg) 9320 { 9321 PetscFunctionBegin; 9322 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9323 PetscValidBoolPointer(set, 2); 9324 PetscValidBoolPointer(flg, 3); 9325 if (A->hermitian != PETSC_BOOL3_UNKNOWN) { 9326 *set = PETSC_TRUE; 9327 *flg = PetscBool3ToBool(A->hermitian); 9328 } else { 9329 *set = PETSC_FALSE; 9330 } 9331 PetscFunctionReturn(PETSC_SUCCESS); 9332 } 9333 9334 /*@ 9335 MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric 9336 9337 Collective 9338 9339 Input Parameter: 9340 . A - the matrix to test 9341 9342 Output Parameter: 9343 . flg - the result 9344 9345 Level: intermediate 9346 9347 Notes: 9348 If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()` 9349 9350 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 9351 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9352 9353 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()` 9354 @*/ 9355 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg) 9356 { 9357 PetscFunctionBegin; 9358 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9359 PetscValidBoolPointer(flg, 2); 9360 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9361 *flg = PetscBool3ToBool(A->structurally_symmetric); 9362 } else { 9363 PetscUseTypeMethod(A, isstructurallysymmetric, flg); 9364 PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg)); 9365 } 9366 PetscFunctionReturn(PETSC_SUCCESS); 9367 } 9368 9369 /*@ 9370 MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state 9371 9372 Not Collective 9373 9374 Input Parameter: 9375 . A - the matrix to check 9376 9377 Output Parameters: 9378 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid) 9379 - flg - the result (only valid if set is PETSC_TRUE) 9380 9381 Level: advanced 9382 9383 Notes: 9384 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 9385 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9386 9387 Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation) 9388 9389 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9390 @*/ 9391 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9392 { 9393 PetscFunctionBegin; 9394 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9395 PetscValidBoolPointer(set, 2); 9396 PetscValidBoolPointer(flg, 3); 9397 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9398 *set = PETSC_TRUE; 9399 *flg = PetscBool3ToBool(A->structurally_symmetric); 9400 } else { 9401 *set = PETSC_FALSE; 9402 } 9403 PetscFunctionReturn(PETSC_SUCCESS); 9404 } 9405 9406 /*@ 9407 MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need 9408 to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process 9409 9410 Not Collective 9411 9412 Input Parameter: 9413 . mat - the matrix 9414 9415 Output Parameters: 9416 + nstash - the size of the stash 9417 . reallocs - the number of additional mallocs incurred. 9418 . bnstash - the size of the block stash 9419 - breallocs - the number of additional mallocs incurred.in the block stash 9420 9421 Level: advanced 9422 9423 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()` 9424 @*/ 9425 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs) 9426 { 9427 PetscFunctionBegin; 9428 PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs)); 9429 PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs)); 9430 PetscFunctionReturn(PETSC_SUCCESS); 9431 } 9432 9433 /*@C 9434 MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same 9435 parallel layout, `PetscLayout` for rows and columns 9436 9437 Collective 9438 9439 Input Parameter: 9440 . mat - the matrix 9441 9442 Output Parameters: 9443 + right - (optional) vector that the matrix can be multiplied against 9444 - left - (optional) vector that the matrix vector product can be stored in 9445 9446 Level: advanced 9447 9448 Notes: 9449 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()`. 9450 9451 These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed 9452 9453 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()` 9454 @*/ 9455 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left) 9456 { 9457 PetscFunctionBegin; 9458 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9459 PetscValidType(mat, 1); 9460 if (mat->ops->getvecs) { 9461 PetscUseTypeMethod(mat, getvecs, right, left); 9462 } else { 9463 if (right) { 9464 PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup"); 9465 PetscCall(VecCreateWithLayout_Private(mat->cmap, right)); 9466 PetscCall(VecSetType(*right, mat->defaultvectype)); 9467 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9468 if (mat->boundtocpu && mat->bindingpropagates) { 9469 PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE)); 9470 PetscCall(VecBindToCPU(*right, PETSC_TRUE)); 9471 } 9472 #endif 9473 } 9474 if (left) { 9475 PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup"); 9476 PetscCall(VecCreateWithLayout_Private(mat->rmap, left)); 9477 PetscCall(VecSetType(*left, mat->defaultvectype)); 9478 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9479 if (mat->boundtocpu && mat->bindingpropagates) { 9480 PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE)); 9481 PetscCall(VecBindToCPU(*left, PETSC_TRUE)); 9482 } 9483 #endif 9484 } 9485 } 9486 PetscFunctionReturn(PETSC_SUCCESS); 9487 } 9488 9489 /*@C 9490 MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure 9491 with default values. 9492 9493 Not Collective 9494 9495 Input Parameter: 9496 . info - the `MatFactorInfo` data structure 9497 9498 Level: developer 9499 9500 Notes: 9501 The solvers are generally used through the `KSP` and `PC` objects, for example 9502 `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC` 9503 9504 Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed 9505 9506 Developer Notes: 9507 The Fortran interface is not autogenerated as the 9508 interface definition cannot be generated correctly [due to `MatFactorInfo`] 9509 9510 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo` 9511 @*/ 9512 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info) 9513 { 9514 PetscFunctionBegin; 9515 PetscCall(PetscMemzero(info, sizeof(MatFactorInfo))); 9516 PetscFunctionReturn(PETSC_SUCCESS); 9517 } 9518 9519 /*@ 9520 MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed 9521 9522 Collective 9523 9524 Input Parameters: 9525 + mat - the factored matrix 9526 - is - the index set defining the Schur indices (0-based) 9527 9528 Level: advanced 9529 9530 Notes: 9531 Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system. 9532 9533 You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call. 9534 9535 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9536 9537 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`, 9538 `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9539 @*/ 9540 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is) 9541 { 9542 PetscErrorCode (*f)(Mat, IS); 9543 9544 PetscFunctionBegin; 9545 PetscValidType(mat, 1); 9546 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9547 PetscValidType(is, 2); 9548 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 9549 PetscCheckSameComm(mat, 1, is, 2); 9550 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 9551 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f)); 9552 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO"); 9553 PetscCall(MatDestroy(&mat->schur)); 9554 PetscCall((*f)(mat, is)); 9555 PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created"); 9556 PetscFunctionReturn(PETSC_SUCCESS); 9557 } 9558 9559 /*@ 9560 MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step 9561 9562 Logically Collective 9563 9564 Input Parameters: 9565 + F - the factored matrix obtained by calling `MatGetFactor()` 9566 . S - location where to return the Schur complement, can be `NULL` 9567 - status - the status of the Schur complement matrix, can be `NULL` 9568 9569 Level: advanced 9570 9571 Notes: 9572 You must call `MatFactorSetSchurIS()` before calling this routine. 9573 9574 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9575 9576 The routine provides a copy of the Schur matrix stored within the solver data structures. 9577 The caller must destroy the object when it is no longer needed. 9578 If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse. 9579 9580 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) 9581 9582 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9583 9584 Developer Notes: 9585 The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc 9586 matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix. 9587 9588 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9589 @*/ 9590 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9591 { 9592 PetscFunctionBegin; 9593 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9594 if (S) PetscValidPointer(S, 2); 9595 if (status) PetscValidPointer(status, 3); 9596 if (S) { 9597 PetscErrorCode (*f)(Mat, Mat *); 9598 9599 PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f)); 9600 if (f) { 9601 PetscCall((*f)(F, S)); 9602 } else { 9603 PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S)); 9604 } 9605 } 9606 if (status) *status = F->schur_status; 9607 PetscFunctionReturn(PETSC_SUCCESS); 9608 } 9609 9610 /*@ 9611 MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix 9612 9613 Logically Collective 9614 9615 Input Parameters: 9616 + F - the factored matrix obtained by calling `MatGetFactor()` 9617 . S - location where to return the Schur complement, can be `NULL` 9618 - status - the status of the Schur complement matrix, can be `NULL` 9619 9620 Level: advanced 9621 9622 Notes: 9623 You must call `MatFactorSetSchurIS()` before calling this routine. 9624 9625 Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS` 9626 9627 The routine returns a the Schur Complement stored within the data structures of the solver. 9628 9629 If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement. 9630 9631 The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed. 9632 9633 Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix 9634 9635 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9636 9637 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9638 @*/ 9639 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9640 { 9641 PetscFunctionBegin; 9642 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9643 if (S) PetscValidPointer(S, 2); 9644 if (status) PetscValidPointer(status, 3); 9645 if (S) *S = F->schur; 9646 if (status) *status = F->schur_status; 9647 PetscFunctionReturn(PETSC_SUCCESS); 9648 } 9649 9650 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F) 9651 { 9652 Mat S = F->schur; 9653 9654 PetscFunctionBegin; 9655 switch (F->schur_status) { 9656 case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through 9657 case MAT_FACTOR_SCHUR_INVERTED: 9658 if (S) { 9659 S->ops->solve = NULL; 9660 S->ops->matsolve = NULL; 9661 S->ops->solvetranspose = NULL; 9662 S->ops->matsolvetranspose = NULL; 9663 S->ops->solveadd = NULL; 9664 S->ops->solvetransposeadd = NULL; 9665 S->factortype = MAT_FACTOR_NONE; 9666 PetscCall(PetscFree(S->solvertype)); 9667 } 9668 case MAT_FACTOR_SCHUR_FACTORED: // fall-through 9669 break; 9670 default: 9671 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9672 } 9673 PetscFunctionReturn(PETSC_SUCCESS); 9674 } 9675 9676 /*@ 9677 MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()` 9678 9679 Logically Collective 9680 9681 Input Parameters: 9682 + F - the factored matrix obtained by calling `MatGetFactor()` 9683 . S - location where the Schur complement is stored 9684 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`) 9685 9686 Level: advanced 9687 9688 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9689 @*/ 9690 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status) 9691 { 9692 PetscFunctionBegin; 9693 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9694 if (S) { 9695 PetscValidHeaderSpecific(*S, MAT_CLASSID, 2); 9696 *S = NULL; 9697 } 9698 F->schur_status = status; 9699 PetscCall(MatFactorUpdateSchurStatus_Private(F)); 9700 PetscFunctionReturn(PETSC_SUCCESS); 9701 } 9702 9703 /*@ 9704 MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step 9705 9706 Logically Collective 9707 9708 Input Parameters: 9709 + F - the factored matrix obtained by calling `MatGetFactor()` 9710 . rhs - location where the right hand side of the Schur complement system is stored 9711 - sol - location where the solution of the Schur complement system has to be returned 9712 9713 Level: advanced 9714 9715 Notes: 9716 The sizes of the vectors should match the size of the Schur complement 9717 9718 Must be called after `MatFactorSetSchurIS()` 9719 9720 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()` 9721 @*/ 9722 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol) 9723 { 9724 PetscFunctionBegin; 9725 PetscValidType(F, 1); 9726 PetscValidType(rhs, 2); 9727 PetscValidType(sol, 3); 9728 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9729 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9730 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9731 PetscCheckSameComm(F, 1, rhs, 2); 9732 PetscCheckSameComm(F, 1, sol, 3); 9733 PetscCall(MatFactorFactorizeSchurComplement(F)); 9734 switch (F->schur_status) { 9735 case MAT_FACTOR_SCHUR_FACTORED: 9736 PetscCall(MatSolveTranspose(F->schur, rhs, sol)); 9737 break; 9738 case MAT_FACTOR_SCHUR_INVERTED: 9739 PetscCall(MatMultTranspose(F->schur, rhs, sol)); 9740 break; 9741 default: 9742 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9743 } 9744 PetscFunctionReturn(PETSC_SUCCESS); 9745 } 9746 9747 /*@ 9748 MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step 9749 9750 Logically Collective 9751 9752 Input Parameters: 9753 + F - the factored matrix obtained by calling `MatGetFactor()` 9754 . rhs - location where the right hand side of the Schur complement system is stored 9755 - sol - location where the solution of the Schur complement system has to be returned 9756 9757 Level: advanced 9758 9759 Notes: 9760 The sizes of the vectors should match the size of the Schur complement 9761 9762 Must be called after `MatFactorSetSchurIS()` 9763 9764 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()` 9765 @*/ 9766 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol) 9767 { 9768 PetscFunctionBegin; 9769 PetscValidType(F, 1); 9770 PetscValidType(rhs, 2); 9771 PetscValidType(sol, 3); 9772 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9773 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9774 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9775 PetscCheckSameComm(F, 1, rhs, 2); 9776 PetscCheckSameComm(F, 1, sol, 3); 9777 PetscCall(MatFactorFactorizeSchurComplement(F)); 9778 switch (F->schur_status) { 9779 case MAT_FACTOR_SCHUR_FACTORED: 9780 PetscCall(MatSolve(F->schur, rhs, sol)); 9781 break; 9782 case MAT_FACTOR_SCHUR_INVERTED: 9783 PetscCall(MatMult(F->schur, rhs, sol)); 9784 break; 9785 default: 9786 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9787 } 9788 PetscFunctionReturn(PETSC_SUCCESS); 9789 } 9790 9791 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat); 9792 #if PetscDefined(HAVE_CUDA) 9793 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat); 9794 #endif 9795 9796 /* Schur status updated in the interface */ 9797 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F) 9798 { 9799 Mat S = F->schur; 9800 9801 PetscFunctionBegin; 9802 if (S) { 9803 PetscMPIInt size; 9804 PetscBool isdense, isdensecuda; 9805 9806 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size)); 9807 PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented"); 9808 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense)); 9809 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda)); 9810 PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name); 9811 PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0)); 9812 if (isdense) { 9813 PetscCall(MatSeqDenseInvertFactors_Private(S)); 9814 } else if (isdensecuda) { 9815 #if defined(PETSC_HAVE_CUDA) 9816 PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S)); 9817 #endif 9818 } 9819 // HIP?????????????? 9820 PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0)); 9821 } 9822 PetscFunctionReturn(PETSC_SUCCESS); 9823 } 9824 9825 /*@ 9826 MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step 9827 9828 Logically Collective 9829 9830 Input Parameter: 9831 . F - the factored matrix obtained by calling `MatGetFactor()` 9832 9833 Level: advanced 9834 9835 Notes: 9836 Must be called after `MatFactorSetSchurIS()`. 9837 9838 Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it. 9839 9840 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()` 9841 @*/ 9842 PetscErrorCode MatFactorInvertSchurComplement(Mat F) 9843 { 9844 PetscFunctionBegin; 9845 PetscValidType(F, 1); 9846 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9847 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS); 9848 PetscCall(MatFactorFactorizeSchurComplement(F)); 9849 PetscCall(MatFactorInvertSchurComplement_Private(F)); 9850 F->schur_status = MAT_FACTOR_SCHUR_INVERTED; 9851 PetscFunctionReturn(PETSC_SUCCESS); 9852 } 9853 9854 /*@ 9855 MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step 9856 9857 Logically Collective 9858 9859 Input Parameter: 9860 . F - the factored matrix obtained by calling `MatGetFactor()` 9861 9862 Level: advanced 9863 9864 Note: 9865 Must be called after `MatFactorSetSchurIS()` 9866 9867 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()` 9868 @*/ 9869 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F) 9870 { 9871 MatFactorInfo info; 9872 9873 PetscFunctionBegin; 9874 PetscValidType(F, 1); 9875 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9876 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS); 9877 PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0)); 9878 PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo))); 9879 if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */ 9880 PetscCall(MatCholeskyFactor(F->schur, NULL, &info)); 9881 } else { 9882 PetscCall(MatLUFactor(F->schur, NULL, NULL, &info)); 9883 } 9884 PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0)); 9885 F->schur_status = MAT_FACTOR_SCHUR_FACTORED; 9886 PetscFunctionReturn(PETSC_SUCCESS); 9887 } 9888 9889 /*@ 9890 MatPtAP - Creates the matrix product C = P^T * A * P 9891 9892 Neighbor-wise Collective 9893 9894 Input Parameters: 9895 + A - the matrix 9896 . P - the projection matrix 9897 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9898 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate 9899 if the result is a dense matrix this is irrelevant 9900 9901 Output Parameter: 9902 . C - the product matrix 9903 9904 Level: intermediate 9905 9906 Notes: 9907 C will be created and must be destroyed by the user with `MatDestroy()`. 9908 9909 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9910 9911 Developer Notes: 9912 For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`. 9913 9914 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()` 9915 @*/ 9916 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C) 9917 { 9918 PetscFunctionBegin; 9919 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 9920 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9921 9922 if (scall == MAT_INITIAL_MATRIX) { 9923 PetscCall(MatProductCreate(A, P, NULL, C)); 9924 PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP)); 9925 PetscCall(MatProductSetAlgorithm(*C, "default")); 9926 PetscCall(MatProductSetFill(*C, fill)); 9927 9928 (*C)->product->api_user = PETSC_TRUE; 9929 PetscCall(MatProductSetFromOptions(*C)); 9930 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); 9931 PetscCall(MatProductSymbolic(*C)); 9932 } else { /* scall == MAT_REUSE_MATRIX */ 9933 PetscCall(MatProductReplaceMats(A, P, NULL, *C)); 9934 } 9935 9936 PetscCall(MatProductNumeric(*C)); 9937 (*C)->symmetric = A->symmetric; 9938 (*C)->spd = A->spd; 9939 PetscFunctionReturn(PETSC_SUCCESS); 9940 } 9941 9942 /*@ 9943 MatRARt - Creates the matrix product C = R * A * R^T 9944 9945 Neighbor-wise Collective 9946 9947 Input Parameters: 9948 + A - the matrix 9949 . R - the projection matrix 9950 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9951 - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate 9952 if the result is a dense matrix this is irrelevant 9953 9954 Output Parameter: 9955 . C - the product matrix 9956 9957 Level: intermediate 9958 9959 Notes: 9960 C will be created and must be destroyed by the user with `MatDestroy()`. 9961 9962 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9963 9964 This routine is currently only implemented for pairs of `MATAIJ` matrices and classes 9965 which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes, 9966 parallel MatRARt is implemented via explicit transpose of R, which could be very expensive. 9967 We recommend using MatPtAP(). 9968 9969 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()` 9970 @*/ 9971 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C) 9972 { 9973 PetscFunctionBegin; 9974 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 9975 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9976 9977 if (scall == MAT_INITIAL_MATRIX) { 9978 PetscCall(MatProductCreate(A, R, NULL, C)); 9979 PetscCall(MatProductSetType(*C, MATPRODUCT_RARt)); 9980 PetscCall(MatProductSetAlgorithm(*C, "default")); 9981 PetscCall(MatProductSetFill(*C, fill)); 9982 9983 (*C)->product->api_user = PETSC_TRUE; 9984 PetscCall(MatProductSetFromOptions(*C)); 9985 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); 9986 PetscCall(MatProductSymbolic(*C)); 9987 } else { /* scall == MAT_REUSE_MATRIX */ 9988 PetscCall(MatProductReplaceMats(A, R, NULL, *C)); 9989 } 9990 9991 PetscCall(MatProductNumeric(*C)); 9992 if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 9993 PetscFunctionReturn(PETSC_SUCCESS); 9994 } 9995 9996 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C) 9997 { 9998 PetscFunctionBegin; 9999 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10000 10001 if (scall == MAT_INITIAL_MATRIX) { 10002 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype])); 10003 PetscCall(MatProductCreate(A, B, NULL, C)); 10004 PetscCall(MatProductSetType(*C, ptype)); 10005 PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT)); 10006 PetscCall(MatProductSetFill(*C, fill)); 10007 10008 (*C)->product->api_user = PETSC_TRUE; 10009 PetscCall(MatProductSetFromOptions(*C)); 10010 PetscCall(MatProductSymbolic(*C)); 10011 } else { /* scall == MAT_REUSE_MATRIX */ 10012 Mat_Product *product = (*C)->product; 10013 PetscBool isdense; 10014 10015 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, "")); 10016 if (isdense && product && product->type != ptype) { 10017 PetscCall(MatProductClear(*C)); 10018 product = NULL; 10019 } 10020 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype])); 10021 if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */ 10022 PetscCheck(isdense, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first"); 10023 PetscCall(MatProductCreate_Private(A, B, NULL, *C)); 10024 product = (*C)->product; 10025 product->fill = fill; 10026 product->api_user = PETSC_TRUE; 10027 product->clear = PETSC_TRUE; 10028 10029 PetscCall(MatProductSetType(*C, ptype)); 10030 PetscCall(MatProductSetFromOptions(*C)); 10031 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); 10032 PetscCall(MatProductSymbolic(*C)); 10033 } else { /* user may change input matrices A or B when REUSE */ 10034 PetscCall(MatProductReplaceMats(A, B, NULL, *C)); 10035 } 10036 } 10037 PetscCall(MatProductNumeric(*C)); 10038 PetscFunctionReturn(PETSC_SUCCESS); 10039 } 10040 10041 /*@ 10042 MatMatMult - Performs matrix-matrix multiplication C=A*B. 10043 10044 Neighbor-wise Collective 10045 10046 Input Parameters: 10047 + A - the left matrix 10048 . B - the right matrix 10049 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10050 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate 10051 if the result is a dense matrix this is irrelevant 10052 10053 Output Parameter: 10054 . C - the product matrix 10055 10056 Notes: 10057 Unless scall is `MAT_REUSE_MATRIX` C will be created. 10058 10059 `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 10060 call to this function with `MAT_INITIAL_MATRIX`. 10061 10062 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed. 10063 10064 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`, 10065 rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse. 10066 10067 Example of Usage: 10068 .vb 10069 MatProductCreate(A,B,NULL,&C); 10070 MatProductSetType(C,MATPRODUCT_AB); 10071 MatProductSymbolic(C); 10072 MatProductNumeric(C); // compute C=A * B 10073 MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1 10074 MatProductNumeric(C); 10075 MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1 10076 MatProductNumeric(C); 10077 .ve 10078 10079 Level: intermediate 10080 10081 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()` 10082 @*/ 10083 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10084 { 10085 PetscFunctionBegin; 10086 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C)); 10087 PetscFunctionReturn(PETSC_SUCCESS); 10088 } 10089 10090 /*@ 10091 MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T. 10092 10093 Neighbor-wise Collective 10094 10095 Input Parameters: 10096 + A - the left matrix 10097 . B - the right matrix 10098 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10099 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 10100 10101 Output Parameter: 10102 . C - the product matrix 10103 10104 Level: intermediate 10105 10106 Notes: 10107 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10108 10109 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call 10110 10111 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10112 actually needed. 10113 10114 This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class, 10115 and for pairs of `MATMPIDENSE` matrices. 10116 10117 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt` 10118 10119 Options Database Keys: 10120 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the 10121 first redundantly copies the transposed B matrix on each process and requires O(log P) communication complexity; 10122 the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity. 10123 10124 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType` 10125 @*/ 10126 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10127 { 10128 PetscFunctionBegin; 10129 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C)); 10130 if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10131 PetscFunctionReturn(PETSC_SUCCESS); 10132 } 10133 10134 /*@ 10135 MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B. 10136 10137 Neighbor-wise Collective 10138 10139 Input Parameters: 10140 + A - the left matrix 10141 . B - the right matrix 10142 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10143 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 10144 10145 Output Parameter: 10146 . C - the product matrix 10147 10148 Level: intermediate 10149 10150 Notes: 10151 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10152 10153 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call. 10154 10155 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB` 10156 10157 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10158 actually needed. 10159 10160 This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes 10161 which inherit from `MATSEQAIJ`. C will be of the same type as the input matrices. 10162 10163 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()` 10164 @*/ 10165 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10166 { 10167 PetscFunctionBegin; 10168 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C)); 10169 PetscFunctionReturn(PETSC_SUCCESS); 10170 } 10171 10172 /*@ 10173 MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C. 10174 10175 Neighbor-wise Collective 10176 10177 Input Parameters: 10178 + A - the left matrix 10179 . B - the middle matrix 10180 . C - the right matrix 10181 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10182 - 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 10183 if the result is a dense matrix this is irrelevant 10184 10185 Output Parameter: 10186 . D - the product matrix 10187 10188 Level: intermediate 10189 10190 Notes: 10191 Unless scall is `MAT_REUSE_MATRIX` D will be created. 10192 10193 `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call 10194 10195 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC` 10196 10197 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10198 actually needed. 10199 10200 If you have many matrices with the same non-zero structure to multiply, you 10201 should use `MAT_REUSE_MATRIX` in all calls but the first 10202 10203 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()` 10204 @*/ 10205 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D) 10206 { 10207 PetscFunctionBegin; 10208 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6); 10209 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10210 10211 if (scall == MAT_INITIAL_MATRIX) { 10212 PetscCall(MatProductCreate(A, B, C, D)); 10213 PetscCall(MatProductSetType(*D, MATPRODUCT_ABC)); 10214 PetscCall(MatProductSetAlgorithm(*D, "default")); 10215 PetscCall(MatProductSetFill(*D, fill)); 10216 10217 (*D)->product->api_user = PETSC_TRUE; 10218 PetscCall(MatProductSetFromOptions(*D)); 10219 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, 10220 ((PetscObject)C)->type_name); 10221 PetscCall(MatProductSymbolic(*D)); 10222 } else { /* user may change input matrices when REUSE */ 10223 PetscCall(MatProductReplaceMats(A, B, C, *D)); 10224 } 10225 PetscCall(MatProductNumeric(*D)); 10226 PetscFunctionReturn(PETSC_SUCCESS); 10227 } 10228 10229 /*@ 10230 MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators. 10231 10232 Collective 10233 10234 Input Parameters: 10235 + mat - the matrix 10236 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices) 10237 . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used) 10238 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10239 10240 Output Parameter: 10241 . matredundant - redundant matrix 10242 10243 Level: advanced 10244 10245 Notes: 10246 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 10247 original matrix has not changed from that last call to MatCreateRedundantMatrix(). 10248 10249 This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before 10250 calling it. 10251 10252 `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be. 10253 10254 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm` 10255 @*/ 10256 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant) 10257 { 10258 MPI_Comm comm; 10259 PetscMPIInt size; 10260 PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs; 10261 Mat_Redundant *redund = NULL; 10262 PetscSubcomm psubcomm = NULL; 10263 MPI_Comm subcomm_in = subcomm; 10264 Mat *matseq; 10265 IS isrow, iscol; 10266 PetscBool newsubcomm = PETSC_FALSE; 10267 10268 PetscFunctionBegin; 10269 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10270 if (nsubcomm && reuse == MAT_REUSE_MATRIX) { 10271 PetscValidPointer(*matredundant, 5); 10272 PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5); 10273 } 10274 10275 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10276 if (size == 1 || nsubcomm == 1) { 10277 if (reuse == MAT_INITIAL_MATRIX) { 10278 PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant)); 10279 } else { 10280 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"); 10281 PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN)); 10282 } 10283 PetscFunctionReturn(PETSC_SUCCESS); 10284 } 10285 10286 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10287 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10288 MatCheckPreallocated(mat, 1); 10289 10290 PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0)); 10291 if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */ 10292 /* create psubcomm, then get subcomm */ 10293 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10294 PetscCallMPI(MPI_Comm_size(comm, &size)); 10295 PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size); 10296 10297 PetscCall(PetscSubcommCreate(comm, &psubcomm)); 10298 PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm)); 10299 PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS)); 10300 PetscCall(PetscSubcommSetFromOptions(psubcomm)); 10301 PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL)); 10302 newsubcomm = PETSC_TRUE; 10303 PetscCall(PetscSubcommDestroy(&psubcomm)); 10304 } 10305 10306 /* get isrow, iscol and a local sequential matrix matseq[0] */ 10307 if (reuse == MAT_INITIAL_MATRIX) { 10308 mloc_sub = PETSC_DECIDE; 10309 nloc_sub = PETSC_DECIDE; 10310 if (bs < 1) { 10311 PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M)); 10312 PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N)); 10313 } else { 10314 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M)); 10315 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N)); 10316 } 10317 PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm)); 10318 rstart = rend - mloc_sub; 10319 PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow)); 10320 PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol)); 10321 } else { /* reuse == MAT_REUSE_MATRIX */ 10322 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"); 10323 /* retrieve subcomm */ 10324 PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm)); 10325 redund = (*matredundant)->redundant; 10326 isrow = redund->isrow; 10327 iscol = redund->iscol; 10328 matseq = redund->matseq; 10329 } 10330 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq)); 10331 10332 /* get matredundant over subcomm */ 10333 if (reuse == MAT_INITIAL_MATRIX) { 10334 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant)); 10335 10336 /* create a supporting struct and attach it to C for reuse */ 10337 PetscCall(PetscNew(&redund)); 10338 (*matredundant)->redundant = redund; 10339 redund->isrow = isrow; 10340 redund->iscol = iscol; 10341 redund->matseq = matseq; 10342 if (newsubcomm) { 10343 redund->subcomm = subcomm; 10344 } else { 10345 redund->subcomm = MPI_COMM_NULL; 10346 } 10347 } else { 10348 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant)); 10349 } 10350 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 10351 if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) { 10352 PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE)); 10353 PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE)); 10354 } 10355 #endif 10356 PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0)); 10357 PetscFunctionReturn(PETSC_SUCCESS); 10358 } 10359 10360 /*@C 10361 MatGetMultiProcBlock - Create multiple 'parallel submatrices' from 10362 a given `Mat`. Each submatrix can span multiple procs. 10363 10364 Collective 10365 10366 Input Parameters: 10367 + mat - the matrix 10368 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))` 10369 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10370 10371 Output Parameter: 10372 . subMat - parallel sub-matrices each spanning a given `subcomm` 10373 10374 Level: advanced 10375 10376 Notes: 10377 The submatrix partition across processors is dictated by `subComm` a 10378 communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm` 10379 is not restricted to be grouped with consecutive original ranks. 10380 10381 Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices 10382 map directly to the layout of the original matrix [wrt the local 10383 row,col partitioning]. So the original 'DiagonalMat' naturally maps 10384 into the 'DiagonalMat' of the `subMat`, hence it is used directly from 10385 the `subMat`. However the offDiagMat looses some columns - and this is 10386 reconstructed with `MatSetValues()` 10387 10388 This is used by `PCBJACOBI` when a single block spans multiple MPI processes. 10389 10390 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI` 10391 @*/ 10392 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) 10393 { 10394 PetscMPIInt commsize, subCommSize; 10395 10396 PetscFunctionBegin; 10397 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize)); 10398 PetscCallMPI(MPI_Comm_size(subComm, &subCommSize)); 10399 PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize); 10400 10401 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"); 10402 PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10403 PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat); 10404 PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10405 PetscFunctionReturn(PETSC_SUCCESS); 10406 } 10407 10408 /*@ 10409 MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering 10410 10411 Not Collective 10412 10413 Input Parameters: 10414 + mat - matrix to extract local submatrix from 10415 . isrow - local row indices for submatrix 10416 - iscol - local column indices for submatrix 10417 10418 Output Parameter: 10419 . submat - the submatrix 10420 10421 Level: intermediate 10422 10423 Notes: 10424 `submat` should be disposed of with `MatRestoreLocalSubMatrix()`. 10425 10426 Depending on the format of `mat`, the returned submat may not implement `MatMult()`. Its communicator may be 10427 the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of `mat`'s. 10428 10429 `submat` always implements `MatSetValuesLocal()`. If `isrow` and `iscol` have the same block size, then 10430 `MatSetValuesBlockedLocal()` will also be implemented. 10431 10432 `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`. 10433 Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided. 10434 10435 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()` 10436 @*/ 10437 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10438 { 10439 PetscFunctionBegin; 10440 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10441 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10442 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10443 PetscCheckSameComm(isrow, 2, iscol, 3); 10444 PetscValidPointer(submat, 4); 10445 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call"); 10446 10447 if (mat->ops->getlocalsubmatrix) { 10448 PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat); 10449 } else { 10450 PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat)); 10451 } 10452 PetscFunctionReturn(PETSC_SUCCESS); 10453 } 10454 10455 /*@ 10456 MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()` 10457 10458 Not Collective 10459 10460 Input Parameters: 10461 + mat - matrix to extract local submatrix from 10462 . isrow - local row indices for submatrix 10463 . iscol - local column indices for submatrix 10464 - submat - the submatrix 10465 10466 Level: intermediate 10467 10468 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()` 10469 @*/ 10470 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10471 { 10472 PetscFunctionBegin; 10473 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10474 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10475 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10476 PetscCheckSameComm(isrow, 2, iscol, 3); 10477 PetscValidPointer(submat, 4); 10478 if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4); 10479 10480 if (mat->ops->restorelocalsubmatrix) { 10481 PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat); 10482 } else { 10483 PetscCall(MatDestroy(submat)); 10484 } 10485 *submat = NULL; 10486 PetscFunctionReturn(PETSC_SUCCESS); 10487 } 10488 10489 /*@ 10490 MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix 10491 10492 Collective 10493 10494 Input Parameter: 10495 . mat - the matrix 10496 10497 Output Parameter: 10498 . is - if any rows have zero diagonals this contains the list of them 10499 10500 Level: developer 10501 10502 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10503 @*/ 10504 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is) 10505 { 10506 PetscFunctionBegin; 10507 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10508 PetscValidType(mat, 1); 10509 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10510 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10511 10512 if (!mat->ops->findzerodiagonals) { 10513 Vec diag; 10514 const PetscScalar *a; 10515 PetscInt *rows; 10516 PetscInt rStart, rEnd, r, nrow = 0; 10517 10518 PetscCall(MatCreateVecs(mat, &diag, NULL)); 10519 PetscCall(MatGetDiagonal(mat, diag)); 10520 PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd)); 10521 PetscCall(VecGetArrayRead(diag, &a)); 10522 for (r = 0; r < rEnd - rStart; ++r) 10523 if (a[r] == 0.0) ++nrow; 10524 PetscCall(PetscMalloc1(nrow, &rows)); 10525 nrow = 0; 10526 for (r = 0; r < rEnd - rStart; ++r) 10527 if (a[r] == 0.0) rows[nrow++] = r + rStart; 10528 PetscCall(VecRestoreArrayRead(diag, &a)); 10529 PetscCall(VecDestroy(&diag)); 10530 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is)); 10531 } else { 10532 PetscUseTypeMethod(mat, findzerodiagonals, is); 10533 } 10534 PetscFunctionReturn(PETSC_SUCCESS); 10535 } 10536 10537 /*@ 10538 MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size) 10539 10540 Collective 10541 10542 Input Parameter: 10543 . mat - the matrix 10544 10545 Output Parameter: 10546 . is - contains the list of rows with off block diagonal entries 10547 10548 Level: developer 10549 10550 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10551 @*/ 10552 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is) 10553 { 10554 PetscFunctionBegin; 10555 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10556 PetscValidType(mat, 1); 10557 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10558 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10559 10560 PetscUseTypeMethod(mat, findoffblockdiagonalentries, is); 10561 PetscFunctionReturn(PETSC_SUCCESS); 10562 } 10563 10564 /*@C 10565 MatInvertBlockDiagonal - Inverts the block diagonal entries. 10566 10567 Collective; No Fortran Support 10568 10569 Input Parameter: 10570 . mat - the matrix 10571 10572 Output Parameter: 10573 . values - the block inverses in column major order (FORTRAN-like) 10574 10575 Level: advanced 10576 10577 Notes: 10578 The size of the blocks is determined by the block size of the matrix. 10579 10580 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10581 10582 The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size 10583 10584 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()` 10585 @*/ 10586 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values) 10587 { 10588 PetscFunctionBegin; 10589 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10590 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10591 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10592 PetscUseTypeMethod(mat, invertblockdiagonal, values); 10593 PetscFunctionReturn(PETSC_SUCCESS); 10594 } 10595 10596 /*@C 10597 MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries. 10598 10599 Collective; No Fortran Support 10600 10601 Input Parameters: 10602 + mat - the matrix 10603 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()` 10604 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()` 10605 10606 Output Parameter: 10607 . values - the block inverses in column major order (FORTRAN-like) 10608 10609 Level: advanced 10610 10611 Notes: 10612 Use `MatInvertBlockDiagonal()` if all blocks have the same size 10613 10614 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10615 10616 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()` 10617 @*/ 10618 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values) 10619 { 10620 PetscFunctionBegin; 10621 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10622 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10623 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10624 PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values); 10625 PetscFunctionReturn(PETSC_SUCCESS); 10626 } 10627 10628 /*@ 10629 MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A 10630 10631 Collective 10632 10633 Input Parameters: 10634 + A - the matrix 10635 - C - matrix with inverted block diagonal of `A`. This matrix should be created and may have its type set. 10636 10637 Level: advanced 10638 10639 Note: 10640 The blocksize of the matrix is used to determine the blocks on the diagonal of `C` 10641 10642 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()` 10643 @*/ 10644 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C) 10645 { 10646 const PetscScalar *vals; 10647 PetscInt *dnnz; 10648 PetscInt m, rstart, rend, bs, i, j; 10649 10650 PetscFunctionBegin; 10651 PetscCall(MatInvertBlockDiagonal(A, &vals)); 10652 PetscCall(MatGetBlockSize(A, &bs)); 10653 PetscCall(MatGetLocalSize(A, &m, NULL)); 10654 PetscCall(MatSetLayouts(C, A->rmap, A->cmap)); 10655 PetscCall(PetscMalloc1(m / bs, &dnnz)); 10656 for (j = 0; j < m / bs; j++) dnnz[j] = 1; 10657 PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL)); 10658 PetscCall(PetscFree(dnnz)); 10659 PetscCall(MatGetOwnershipRange(C, &rstart, &rend)); 10660 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE)); 10661 for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES)); 10662 PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 10663 PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 10664 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE)); 10665 PetscFunctionReturn(PETSC_SUCCESS); 10666 } 10667 10668 /*@C 10669 MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created 10670 via `MatTransposeColoringCreate()`. 10671 10672 Collective 10673 10674 Input Parameter: 10675 . c - coloring context 10676 10677 Level: intermediate 10678 10679 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()` 10680 @*/ 10681 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c) 10682 { 10683 MatTransposeColoring matcolor = *c; 10684 10685 PetscFunctionBegin; 10686 if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS); 10687 if (--((PetscObject)matcolor)->refct > 0) { 10688 matcolor = NULL; 10689 PetscFunctionReturn(PETSC_SUCCESS); 10690 } 10691 10692 PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow)); 10693 PetscCall(PetscFree(matcolor->rows)); 10694 PetscCall(PetscFree(matcolor->den2sp)); 10695 PetscCall(PetscFree(matcolor->colorforcol)); 10696 PetscCall(PetscFree(matcolor->columns)); 10697 if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart)); 10698 PetscCall(PetscHeaderDestroy(c)); 10699 PetscFunctionReturn(PETSC_SUCCESS); 10700 } 10701 10702 /*@C 10703 MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which 10704 a `MatTransposeColoring` context has been created, computes a dense B^T by applying 10705 `MatTransposeColoring` to sparse B. 10706 10707 Collective 10708 10709 Input Parameters: 10710 + coloring - coloring context created with `MatTransposeColoringCreate()` 10711 - B - sparse matrix 10712 10713 Output Parameter: 10714 . Btdense - dense matrix B^T 10715 10716 Level: developer 10717 10718 Note: 10719 These are used internally for some implementations of `MatRARt()` 10720 10721 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()` 10722 @*/ 10723 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense) 10724 { 10725 PetscFunctionBegin; 10726 PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10727 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 10728 PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3); 10729 10730 PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense)); 10731 PetscFunctionReturn(PETSC_SUCCESS); 10732 } 10733 10734 /*@C 10735 MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which 10736 a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense 10737 in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix 10738 `Csp` from `Cden`. 10739 10740 Collective 10741 10742 Input Parameters: 10743 + matcoloring - coloring context created with `MatTransposeColoringCreate()` 10744 - Cden - matrix product of a sparse matrix and a dense matrix Btdense 10745 10746 Output Parameter: 10747 . Csp - sparse matrix 10748 10749 Level: developer 10750 10751 Note: 10752 These are used internally for some implementations of `MatRARt()` 10753 10754 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()` 10755 @*/ 10756 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp) 10757 { 10758 PetscFunctionBegin; 10759 PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10760 PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2); 10761 PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3); 10762 10763 PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp)); 10764 PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY)); 10765 PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY)); 10766 PetscFunctionReturn(PETSC_SUCCESS); 10767 } 10768 10769 /*@C 10770 MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T. 10771 10772 Collective 10773 10774 Input Parameters: 10775 + mat - the matrix product C 10776 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()` 10777 10778 Output Parameter: 10779 . color - the new coloring context 10780 10781 Level: intermediate 10782 10783 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`, 10784 `MatTransColoringApplyDenToSp()` 10785 @*/ 10786 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color) 10787 { 10788 MatTransposeColoring c; 10789 MPI_Comm comm; 10790 10791 PetscFunctionBegin; 10792 PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10793 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10794 PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL)); 10795 10796 c->ctype = iscoloring->ctype; 10797 PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c); 10798 10799 *color = c; 10800 PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10801 PetscFunctionReturn(PETSC_SUCCESS); 10802 } 10803 10804 /*@ 10805 MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the 10806 matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the 10807 same, otherwise it will be larger 10808 10809 Not Collective 10810 10811 Input Parameter: 10812 . mat - the matrix 10813 10814 Output Parameter: 10815 . state - the current state 10816 10817 Level: intermediate 10818 10819 Notes: 10820 You can only compare states from two different calls to the SAME matrix, you cannot compare calls between 10821 different matrices 10822 10823 Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix 10824 10825 Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers. 10826 10827 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()` 10828 @*/ 10829 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state) 10830 { 10831 PetscFunctionBegin; 10832 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10833 *state = mat->nonzerostate; 10834 PetscFunctionReturn(PETSC_SUCCESS); 10835 } 10836 10837 /*@ 10838 MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential 10839 matrices from each processor 10840 10841 Collective 10842 10843 Input Parameters: 10844 + comm - the communicators the parallel matrix will live on 10845 . seqmat - the input sequential matrices 10846 . n - number of local columns (or `PETSC_DECIDE`) 10847 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10848 10849 Output Parameter: 10850 . mpimat - the parallel matrix generated 10851 10852 Level: developer 10853 10854 Note: 10855 The number of columns of the matrix in EACH processor MUST be the same. 10856 10857 .seealso: [](ch_matrices), `Mat` 10858 @*/ 10859 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat) 10860 { 10861 PetscMPIInt size; 10862 10863 PetscFunctionBegin; 10864 PetscCallMPI(MPI_Comm_size(comm, &size)); 10865 if (size == 1) { 10866 if (reuse == MAT_INITIAL_MATRIX) { 10867 PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat)); 10868 } else { 10869 PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN)); 10870 } 10871 PetscFunctionReturn(PETSC_SUCCESS); 10872 } 10873 10874 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"); 10875 10876 PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0)); 10877 PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat)); 10878 PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0)); 10879 PetscFunctionReturn(PETSC_SUCCESS); 10880 } 10881 10882 /*@ 10883 MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI ranks' ownership ranges. 10884 10885 Collective 10886 10887 Input Parameters: 10888 + A - the matrix to create subdomains from 10889 - N - requested number of subdomains 10890 10891 Output Parameters: 10892 + n - number of subdomains resulting on this MPI process 10893 - iss - `IS` list with indices of subdomains on this MPI process 10894 10895 Level: advanced 10896 10897 Note: 10898 The number of subdomains must be smaller than the communicator size 10899 10900 .seealso: [](ch_matrices), `Mat`, `IS` 10901 @*/ 10902 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[]) 10903 { 10904 MPI_Comm comm, subcomm; 10905 PetscMPIInt size, rank, color; 10906 PetscInt rstart, rend, k; 10907 10908 PetscFunctionBegin; 10909 PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 10910 PetscCallMPI(MPI_Comm_size(comm, &size)); 10911 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 10912 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); 10913 *n = 1; 10914 k = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */ 10915 color = rank / k; 10916 PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm)); 10917 PetscCall(PetscMalloc1(1, iss)); 10918 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 10919 PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0])); 10920 PetscCallMPI(MPI_Comm_free(&subcomm)); 10921 PetscFunctionReturn(PETSC_SUCCESS); 10922 } 10923 10924 /*@ 10925 MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection. 10926 10927 If the interpolation and restriction operators are the same, uses `MatPtAP()`. 10928 If they are not the same, uses `MatMatMatMult()`. 10929 10930 Once the coarse grid problem is constructed, correct for interpolation operators 10931 that are not of full rank, which can legitimately happen in the case of non-nested 10932 geometric multigrid. 10933 10934 Input Parameters: 10935 + restrct - restriction operator 10936 . dA - fine grid matrix 10937 . interpolate - interpolation operator 10938 . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10939 - fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate 10940 10941 Output Parameter: 10942 . A - the Galerkin coarse matrix 10943 10944 Options Database Key: 10945 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used 10946 10947 Level: developer 10948 10949 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()` 10950 @*/ 10951 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A) 10952 { 10953 IS zerorows; 10954 Vec diag; 10955 10956 PetscFunctionBegin; 10957 PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10958 /* Construct the coarse grid matrix */ 10959 if (interpolate == restrct) { 10960 PetscCall(MatPtAP(dA, interpolate, reuse, fill, A)); 10961 } else { 10962 PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A)); 10963 } 10964 10965 /* If the interpolation matrix is not of full rank, A will have zero rows. 10966 This can legitimately happen in the case of non-nested geometric multigrid. 10967 In that event, we set the rows of the matrix to the rows of the identity, 10968 ignoring the equations (as the RHS will also be zero). */ 10969 10970 PetscCall(MatFindZeroRows(*A, &zerorows)); 10971 10972 if (zerorows != NULL) { /* if there are any zero rows */ 10973 PetscCall(MatCreateVecs(*A, &diag, NULL)); 10974 PetscCall(MatGetDiagonal(*A, diag)); 10975 PetscCall(VecISSet(diag, zerorows, 1.0)); 10976 PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES)); 10977 PetscCall(VecDestroy(&diag)); 10978 PetscCall(ISDestroy(&zerorows)); 10979 } 10980 PetscFunctionReturn(PETSC_SUCCESS); 10981 } 10982 10983 /*@C 10984 MatSetOperation - Allows user to set a matrix operation for any matrix type 10985 10986 Logically Collective 10987 10988 Input Parameters: 10989 + mat - the matrix 10990 . op - the name of the operation 10991 - f - the function that provides the operation 10992 10993 Level: developer 10994 10995 Example Usage: 10996 .vb 10997 extern PetscErrorCode usermult(Mat, Vec, Vec); 10998 10999 PetscCall(MatCreateXXX(comm, ..., &A)); 11000 PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFunction)usermult)); 11001 .ve 11002 11003 Notes: 11004 See the file `include/petscmat.h` for a complete list of matrix 11005 operations, which all have the form MATOP_<OPERATION>, where 11006 <OPERATION> is the name (in all capital letters) of the 11007 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11008 11009 All user-provided functions (except for `MATOP_DESTROY`) should have the same calling 11010 sequence as the usual matrix interface routines, since they 11011 are intended to be accessed via the usual matrix interface 11012 routines, e.g., 11013 .vb 11014 MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec) 11015 .ve 11016 11017 In particular each function MUST return `PETSC_SUCCESS` on success and 11018 nonzero on failure. 11019 11020 This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type. 11021 11022 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()` 11023 @*/ 11024 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void)) 11025 { 11026 PetscFunctionBegin; 11027 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11028 if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view; 11029 (((void (**)(void))mat->ops)[op]) = f; 11030 PetscFunctionReturn(PETSC_SUCCESS); 11031 } 11032 11033 /*@C 11034 MatGetOperation - Gets a matrix operation for any matrix type. 11035 11036 Not Collective 11037 11038 Input Parameters: 11039 + mat - the matrix 11040 - op - the name of the operation 11041 11042 Output Parameter: 11043 . f - the function that provides the operation 11044 11045 Level: developer 11046 11047 Example Usage: 11048 .vb 11049 PetscErrorCode (*usermult)(Mat, Vec, Vec); 11050 11051 MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult); 11052 .ve 11053 11054 Notes: 11055 See the file include/petscmat.h for a complete list of matrix 11056 operations, which all have the form MATOP_<OPERATION>, where 11057 <OPERATION> is the name (in all capital letters) of the 11058 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11059 11060 This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type. 11061 11062 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()` 11063 @*/ 11064 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void)) 11065 { 11066 PetscFunctionBegin; 11067 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11068 *f = (((void (**)(void))mat->ops)[op]); 11069 PetscFunctionReturn(PETSC_SUCCESS); 11070 } 11071 11072 /*@ 11073 MatHasOperation - Determines whether the given matrix supports the particular operation. 11074 11075 Not Collective 11076 11077 Input Parameters: 11078 + mat - the matrix 11079 - op - the operation, for example, `MATOP_GET_DIAGONAL` 11080 11081 Output Parameter: 11082 . has - either `PETSC_TRUE` or `PETSC_FALSE` 11083 11084 Level: advanced 11085 11086 Note: 11087 See `MatSetOperation()` for additional discussion on naming convention and usage of `op`. 11088 11089 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()` 11090 @*/ 11091 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has) 11092 { 11093 PetscFunctionBegin; 11094 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11095 PetscValidBoolPointer(has, 3); 11096 if (mat->ops->hasoperation) { 11097 PetscUseTypeMethod(mat, hasoperation, op, has); 11098 } else { 11099 if (((void **)mat->ops)[op]) *has = PETSC_TRUE; 11100 else { 11101 *has = PETSC_FALSE; 11102 if (op == MATOP_CREATE_SUBMATRIX) { 11103 PetscMPIInt size; 11104 11105 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 11106 if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has)); 11107 } 11108 } 11109 } 11110 PetscFunctionReturn(PETSC_SUCCESS); 11111 } 11112 11113 /*@ 11114 MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent 11115 11116 Collective 11117 11118 Input Parameter: 11119 . mat - the matrix 11120 11121 Output Parameter: 11122 . cong - either `PETSC_TRUE` or `PETSC_FALSE` 11123 11124 Level: beginner 11125 11126 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout` 11127 @*/ 11128 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong) 11129 { 11130 PetscFunctionBegin; 11131 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11132 PetscValidType(mat, 1); 11133 PetscValidBoolPointer(cong, 2); 11134 if (!mat->rmap || !mat->cmap) { 11135 *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE; 11136 PetscFunctionReturn(PETSC_SUCCESS); 11137 } 11138 if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */ 11139 PetscCall(PetscLayoutSetUp(mat->rmap)); 11140 PetscCall(PetscLayoutSetUp(mat->cmap)); 11141 PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong)); 11142 if (*cong) mat->congruentlayouts = 1; 11143 else mat->congruentlayouts = 0; 11144 } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE; 11145 PetscFunctionReturn(PETSC_SUCCESS); 11146 } 11147 11148 PetscErrorCode MatSetInf(Mat A) 11149 { 11150 PetscFunctionBegin; 11151 PetscUseTypeMethod(A, setinf); 11152 PetscFunctionReturn(PETSC_SUCCESS); 11153 } 11154 11155 /*@C 11156 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 11157 and possibly removes small values from the graph structure. 11158 11159 Collective 11160 11161 Input Parameters: 11162 + A - the matrix 11163 . sym - `PETSC_TRUE` indicates that the graph should be symmetrized 11164 . scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry 11165 - filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value 11166 11167 Output Parameter: 11168 . graph - the resulting graph 11169 11170 Level: advanced 11171 11172 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG` 11173 @*/ 11174 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph) 11175 { 11176 PetscFunctionBegin; 11177 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11178 PetscValidType(A, 1); 11179 PetscValidLogicalCollectiveBool(A, scale, 3); 11180 PetscValidPointer(graph, 5); 11181 PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph); 11182 PetscFunctionReturn(PETSC_SUCCESS); 11183 } 11184 11185 /*@ 11186 MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place, 11187 meaning the same memory is used for the matrix, and no new memory is allocated. 11188 11189 Collective 11190 11191 Input Parameter: 11192 . A - the matrix 11193 11194 Level: intermediate 11195 11196 Developer Notes: 11197 The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end 11198 of the arrays in the data structure are unneeded. 11199 11200 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatChop()` 11201 @*/ 11202 PetscErrorCode MatEliminateZeros(Mat A) 11203 { 11204 PetscFunctionBegin; 11205 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11206 PetscUseTypeMethod(A, eliminatezeros); 11207 PetscFunctionReturn(PETSC_SUCCESS); 11208 } 11209