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 Level: intermediate 7488 7489 Notes: 7490 There can be zeros within the blocks 7491 7492 The blocks can overlap between processes, including laying on more than two processes 7493 7494 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()` 7495 @*/ 7496 PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat) 7497 { 7498 PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend; 7499 PetscInt *diag, *odiag, sc; 7500 VecScatter scatter; 7501 PetscScalar *seqv; 7502 const PetscScalar *parv; 7503 const PetscInt *ia, *ja; 7504 PetscBool set, flag, done; 7505 Mat AA = mat, A; 7506 MPI_Comm comm; 7507 PetscMPIInt rank, size, tag; 7508 MPI_Status status; 7509 PetscContainer container; 7510 EnvelopeData *edata; 7511 Vec seq, par; 7512 IS isglobal; 7513 7514 PetscFunctionBegin; 7515 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7516 PetscCall(MatIsSymmetricKnown(mat, &set, &flag)); 7517 if (!set || !flag) { 7518 /* TODO: only needs nonzero structure of transpose */ 7519 PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA)); 7520 PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN)); 7521 } 7522 PetscCall(MatAIJGetLocalMat(AA, &A)); 7523 PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7524 PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix"); 7525 7526 PetscCall(MatGetLocalSize(mat, &n, NULL)); 7527 PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag)); 7528 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 7529 PetscCallMPI(MPI_Comm_size(comm, &size)); 7530 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7531 7532 PetscCall(PetscMalloc2(n, &sizes, n, &starts)); 7533 7534 if (rank > 0) { 7535 PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7536 PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7537 } 7538 PetscCall(MatGetOwnershipRange(mat, &rstart, NULL)); 7539 for (i = 0; i < n; i++) { 7540 env = PetscMax(env, ja[ia[i + 1] - 1]); 7541 II = rstart + i; 7542 if (env == II) { 7543 starts[lblocks] = tbs; 7544 sizes[lblocks++] = 1 + II - tbs; 7545 tbs = 1 + II; 7546 } 7547 } 7548 if (rank < size - 1) { 7549 PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm)); 7550 PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm)); 7551 } 7552 7553 PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7554 if (!set || !flag) PetscCall(MatDestroy(&AA)); 7555 PetscCall(MatDestroy(&A)); 7556 7557 PetscCall(PetscNew(&edata)); 7558 PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate)); 7559 edata->n = lblocks; 7560 /* create IS needed for extracting blocks from the original matrix */ 7561 PetscCall(PetscMalloc1(lblocks, &edata->is)); 7562 for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i])); 7563 7564 /* Create the resulting inverse matrix structure with preallocation information */ 7565 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C)); 7566 PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 7567 PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat)); 7568 PetscCall(MatSetType(edata->C, MATAIJ)); 7569 7570 /* Communicate the start and end of each row, from each block to the correct rank */ 7571 /* TODO: Use PetscSF instead of VecScatter */ 7572 for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i]; 7573 PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq)); 7574 PetscCall(VecGetArrayWrite(seq, &seqv)); 7575 for (PetscInt i = 0; i < lblocks; i++) { 7576 for (PetscInt j = 0; j < sizes[i]; j++) { 7577 seqv[cnt] = starts[i]; 7578 seqv[cnt + 1] = starts[i] + sizes[i]; 7579 cnt += 2; 7580 } 7581 } 7582 PetscCall(VecRestoreArrayWrite(seq, &seqv)); 7583 PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 7584 sc -= cnt; 7585 PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par)); 7586 PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal)); 7587 PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter)); 7588 PetscCall(ISDestroy(&isglobal)); 7589 PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7590 PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7591 PetscCall(VecScatterDestroy(&scatter)); 7592 PetscCall(VecDestroy(&seq)); 7593 PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend)); 7594 PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag)); 7595 PetscCall(VecGetArrayRead(par, &parv)); 7596 cnt = 0; 7597 PetscCall(MatGetSize(mat, NULL, &n)); 7598 for (PetscInt i = 0; i < mat->rmap->n; i++) { 7599 PetscInt start, end, d = 0, od = 0; 7600 7601 start = (PetscInt)PetscRealPart(parv[cnt]); 7602 end = (PetscInt)PetscRealPart(parv[cnt + 1]); 7603 cnt += 2; 7604 7605 if (start < cstart) { 7606 od += cstart - start + n - cend; 7607 d += cend - cstart; 7608 } else if (start < cend) { 7609 od += n - cend; 7610 d += cend - start; 7611 } else od += n - start; 7612 if (end <= cstart) { 7613 od -= cstart - end + n - cend; 7614 d -= cend - cstart; 7615 } else if (end < cend) { 7616 od -= n - cend; 7617 d -= cend - end; 7618 } else od -= n - end; 7619 7620 odiag[i] = od; 7621 diag[i] = d; 7622 } 7623 PetscCall(VecRestoreArrayRead(par, &parv)); 7624 PetscCall(VecDestroy(&par)); 7625 PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL)); 7626 PetscCall(PetscFree2(diag, odiag)); 7627 PetscCall(PetscFree2(sizes, starts)); 7628 7629 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container)); 7630 PetscCall(PetscContainerSetPointer(container, edata)); 7631 PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy)); 7632 PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container)); 7633 PetscCall(PetscObjectDereference((PetscObject)container)); 7634 PetscFunctionReturn(PETSC_SUCCESS); 7635 } 7636 7637 /*@ 7638 MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A 7639 7640 Collective 7641 7642 Input Parameters: 7643 + A - the matrix 7644 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine 7645 7646 Output Parameter: 7647 . C - matrix with inverted block diagonal of `A` 7648 7649 Level: advanced 7650 7651 Note: 7652 For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal. 7653 7654 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()` 7655 @*/ 7656 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C) 7657 { 7658 PetscContainer container; 7659 EnvelopeData *edata; 7660 PetscObjectState nonzerostate; 7661 7662 PetscFunctionBegin; 7663 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7664 if (!container) { 7665 PetscCall(MatComputeVariableBlockEnvelope(A)); 7666 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7667 } 7668 PetscCall(PetscContainerGetPointer(container, (void **)&edata)); 7669 PetscCall(MatGetNonzeroState(A, &nonzerostate)); 7670 PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure"); 7671 PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output"); 7672 7673 PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat)); 7674 *C = edata->C; 7675 7676 for (PetscInt i = 0; i < edata->n; i++) { 7677 Mat D; 7678 PetscScalar *dvalues; 7679 7680 PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D)); 7681 PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE)); 7682 PetscCall(MatSeqDenseInvert(D)); 7683 PetscCall(MatDenseGetArray(D, &dvalues)); 7684 PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES)); 7685 PetscCall(MatDestroy(&D)); 7686 } 7687 PetscCall(MatDestroySubMatrices(edata->n, &edata->mat)); 7688 PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY)); 7689 PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY)); 7690 PetscFunctionReturn(PETSC_SUCCESS); 7691 } 7692 7693 /*@ 7694 MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size 7695 7696 Logically Collective 7697 7698 Input Parameters: 7699 + mat - the matrix 7700 . nblocks - the number of blocks on this process, each block can only exist on a single process 7701 - bsizes - the block sizes 7702 7703 Level: intermediate 7704 7705 Notes: 7706 Currently used by `PCVPBJACOBI` for `MATAIJ` matrices 7707 7708 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. 7709 7710 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, 7711 `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI` 7712 @*/ 7713 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes) 7714 { 7715 PetscInt i, ncnt = 0, nlocal; 7716 7717 PetscFunctionBegin; 7718 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7719 PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero"); 7720 PetscCall(MatGetLocalSize(mat, &nlocal, NULL)); 7721 for (i = 0; i < nblocks; i++) ncnt += bsizes[i]; 7722 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); 7723 PetscCall(PetscFree(mat->bsizes)); 7724 mat->nblocks = nblocks; 7725 PetscCall(PetscMalloc1(nblocks, &mat->bsizes)); 7726 PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks)); 7727 PetscFunctionReturn(PETSC_SUCCESS); 7728 } 7729 7730 /*@C 7731 MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size 7732 7733 Logically Collective; No Fortran Support 7734 7735 Input Parameter: 7736 . mat - the matrix 7737 7738 Output Parameters: 7739 + nblocks - the number of blocks on this process 7740 - bsizes - the block sizes 7741 7742 Level: intermediate 7743 7744 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()` 7745 @*/ 7746 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes) 7747 { 7748 PetscFunctionBegin; 7749 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7750 *nblocks = mat->nblocks; 7751 *bsizes = mat->bsizes; 7752 PetscFunctionReturn(PETSC_SUCCESS); 7753 } 7754 7755 /*@ 7756 MatSetBlockSizes - Sets the matrix block row and column sizes. 7757 7758 Logically Collective 7759 7760 Input Parameters: 7761 + mat - the matrix 7762 . rbs - row block size 7763 - cbs - column block size 7764 7765 Level: intermediate 7766 7767 Notes: 7768 Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix. 7769 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7770 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7771 7772 For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes 7773 are compatible with the matrix local sizes. 7774 7775 The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`. 7776 7777 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()` 7778 @*/ 7779 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs) 7780 { 7781 PetscFunctionBegin; 7782 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7783 PetscValidLogicalCollectiveInt(mat, rbs, 2); 7784 PetscValidLogicalCollectiveInt(mat, cbs, 3); 7785 PetscTryTypeMethod(mat, setblocksizes, rbs, cbs); 7786 if (mat->rmap->refcnt) { 7787 ISLocalToGlobalMapping l2g = NULL; 7788 PetscLayout nmap = NULL; 7789 7790 PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap)); 7791 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g)); 7792 PetscCall(PetscLayoutDestroy(&mat->rmap)); 7793 mat->rmap = nmap; 7794 mat->rmap->mapping = l2g; 7795 } 7796 if (mat->cmap->refcnt) { 7797 ISLocalToGlobalMapping l2g = NULL; 7798 PetscLayout nmap = NULL; 7799 7800 PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap)); 7801 if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g)); 7802 PetscCall(PetscLayoutDestroy(&mat->cmap)); 7803 mat->cmap = nmap; 7804 mat->cmap->mapping = l2g; 7805 } 7806 PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs)); 7807 PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs)); 7808 PetscFunctionReturn(PETSC_SUCCESS); 7809 } 7810 7811 /*@ 7812 MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices 7813 7814 Logically Collective 7815 7816 Input Parameters: 7817 + mat - the matrix 7818 . fromRow - matrix from which to copy row block size 7819 - fromCol - matrix from which to copy column block size (can be same as fromRow) 7820 7821 Level: developer 7822 7823 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()` 7824 @*/ 7825 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol) 7826 { 7827 PetscFunctionBegin; 7828 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7829 PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2); 7830 PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3); 7831 if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs)); 7832 if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs)); 7833 PetscFunctionReturn(PETSC_SUCCESS); 7834 } 7835 7836 /*@ 7837 MatResidual - Default routine to calculate the residual r = b - Ax 7838 7839 Collective 7840 7841 Input Parameters: 7842 + mat - the matrix 7843 . b - the right-hand-side 7844 - x - the approximate solution 7845 7846 Output Parameter: 7847 . r - location to store the residual 7848 7849 Level: developer 7850 7851 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()` 7852 @*/ 7853 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r) 7854 { 7855 PetscFunctionBegin; 7856 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7857 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 7858 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 7859 PetscValidHeaderSpecific(r, VEC_CLASSID, 4); 7860 PetscValidType(mat, 1); 7861 MatCheckPreallocated(mat, 1); 7862 PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0)); 7863 if (!mat->ops->residual) { 7864 PetscCall(MatMult(mat, x, r)); 7865 PetscCall(VecAYPX(r, -1.0, b)); 7866 } else { 7867 PetscUseTypeMethod(mat, residual, b, x, r); 7868 } 7869 PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0)); 7870 PetscFunctionReturn(PETSC_SUCCESS); 7871 } 7872 7873 /*MC 7874 MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix 7875 7876 Synopsis: 7877 MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 7878 7879 Not Collective 7880 7881 Input Parameters: 7882 + A - the matrix 7883 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7884 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7885 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7886 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7887 always used. 7888 7889 Output Parameters: 7890 + n - number of local rows in the (possibly compressed) matrix 7891 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 7892 . ja - the column indices 7893 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7894 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7895 7896 Level: developer 7897 7898 Note: 7899 Use `MatRestoreRowIJF90()` when you no longer need access to the data 7900 7901 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()` 7902 M*/ 7903 7904 /*MC 7905 MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()` 7906 7907 Synopsis: 7908 MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 7909 7910 Not Collective 7911 7912 Input Parameters: 7913 + A - the matrix 7914 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7915 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7916 inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7917 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7918 always used. 7919 . n - number of local rows in the (possibly compressed) matrix 7920 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 7921 . ja - the column indices 7922 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7923 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7924 7925 Level: developer 7926 7927 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()` 7928 M*/ 7929 7930 /*@C 7931 MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix 7932 7933 Collective 7934 7935 Input Parameters: 7936 + mat - the matrix 7937 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7938 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7939 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7940 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7941 always used. 7942 7943 Output Parameters: 7944 + n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed 7945 . 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 7946 . ja - the column indices, use `NULL` if not needed 7947 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7948 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7949 7950 Level: developer 7951 7952 Notes: 7953 You CANNOT change any of the ia[] or ja[] values. 7954 7955 Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values. 7956 7957 Fortran Notes: 7958 Use 7959 .vb 7960 PetscInt, pointer :: ia(:),ja(:) 7961 call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr) 7962 ! Access the ith and jth entries via ia(i) and ja(j) 7963 .ve 7964 `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()` 7965 7966 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()` 7967 @*/ 7968 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7969 { 7970 PetscFunctionBegin; 7971 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7972 PetscValidType(mat, 1); 7973 if (n) PetscValidIntPointer(n, 5); 7974 if (ia) PetscValidPointer(ia, 6); 7975 if (ja) PetscValidPointer(ja, 7); 7976 if (done) PetscValidBoolPointer(done, 8); 7977 MatCheckPreallocated(mat, 1); 7978 if (!mat->ops->getrowij && done) *done = PETSC_FALSE; 7979 else { 7980 if (done) *done = PETSC_TRUE; 7981 PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0)); 7982 PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done); 7983 PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0)); 7984 } 7985 PetscFunctionReturn(PETSC_SUCCESS); 7986 } 7987 7988 /*@C 7989 MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices. 7990 7991 Collective 7992 7993 Input Parameters: 7994 + mat - the matrix 7995 . shift - 1 or zero indicating we want the indices starting at 0 or 1 7996 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be 7997 symmetrized 7998 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7999 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8000 always used. 8001 . n - number of columns in the (possibly compressed) matrix 8002 . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix 8003 - ja - the row indices 8004 8005 Output Parameter: 8006 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned 8007 8008 Level: developer 8009 8010 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 8011 @*/ 8012 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8013 { 8014 PetscFunctionBegin; 8015 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8016 PetscValidType(mat, 1); 8017 PetscValidIntPointer(n, 5); 8018 if (ia) PetscValidPointer(ia, 6); 8019 if (ja) PetscValidPointer(ja, 7); 8020 PetscValidBoolPointer(done, 8); 8021 MatCheckPreallocated(mat, 1); 8022 if (!mat->ops->getcolumnij) *done = PETSC_FALSE; 8023 else { 8024 *done = PETSC_TRUE; 8025 PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8026 } 8027 PetscFunctionReturn(PETSC_SUCCESS); 8028 } 8029 8030 /*@C 8031 MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`. 8032 8033 Collective 8034 8035 Input Parameters: 8036 + mat - the matrix 8037 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8038 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8039 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8040 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8041 always used. 8042 . n - size of (possibly compressed) matrix 8043 . ia - the row pointers 8044 - ja - the column indices 8045 8046 Output Parameter: 8047 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8048 8049 Level: developer 8050 8051 Note: 8052 This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental 8053 us of the array after it has been restored. If you pass `NULL`, it will 8054 not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid. 8055 8056 Fortran Notes: 8057 `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()` 8058 8059 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()` 8060 @*/ 8061 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8062 { 8063 PetscFunctionBegin; 8064 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8065 PetscValidType(mat, 1); 8066 if (ia) PetscValidPointer(ia, 6); 8067 if (ja) PetscValidPointer(ja, 7); 8068 if (done) PetscValidBoolPointer(done, 8); 8069 MatCheckPreallocated(mat, 1); 8070 8071 if (!mat->ops->restorerowij && done) *done = PETSC_FALSE; 8072 else { 8073 if (done) *done = PETSC_TRUE; 8074 PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8075 if (n) *n = 0; 8076 if (ia) *ia = NULL; 8077 if (ja) *ja = NULL; 8078 } 8079 PetscFunctionReturn(PETSC_SUCCESS); 8080 } 8081 8082 /*@C 8083 MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`. 8084 8085 Collective 8086 8087 Input Parameters: 8088 + mat - the matrix 8089 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8090 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8091 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8092 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8093 always used. 8094 8095 Output Parameters: 8096 + n - size of (possibly compressed) matrix 8097 . ia - the column pointers 8098 . ja - the row indices 8099 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8100 8101 Level: developer 8102 8103 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()` 8104 @*/ 8105 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8106 { 8107 PetscFunctionBegin; 8108 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8109 PetscValidType(mat, 1); 8110 if (ia) PetscValidPointer(ia, 6); 8111 if (ja) PetscValidPointer(ja, 7); 8112 PetscValidBoolPointer(done, 8); 8113 MatCheckPreallocated(mat, 1); 8114 8115 if (!mat->ops->restorecolumnij) *done = PETSC_FALSE; 8116 else { 8117 *done = PETSC_TRUE; 8118 PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8119 if (n) *n = 0; 8120 if (ia) *ia = NULL; 8121 if (ja) *ja = NULL; 8122 } 8123 PetscFunctionReturn(PETSC_SUCCESS); 8124 } 8125 8126 /*@C 8127 MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or 8128 `MatGetColumnIJ()`. 8129 8130 Collective 8131 8132 Input Parameters: 8133 + mat - the matrix 8134 . ncolors - maximum color value 8135 . n - number of entries in colorarray 8136 - colorarray - array indicating color for each column 8137 8138 Output Parameter: 8139 . iscoloring - coloring generated using colorarray information 8140 8141 Level: developer 8142 8143 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()` 8144 @*/ 8145 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring) 8146 { 8147 PetscFunctionBegin; 8148 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8149 PetscValidType(mat, 1); 8150 PetscValidIntPointer(colorarray, 4); 8151 PetscValidPointer(iscoloring, 5); 8152 MatCheckPreallocated(mat, 1); 8153 8154 if (!mat->ops->coloringpatch) { 8155 PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring)); 8156 } else { 8157 PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring); 8158 } 8159 PetscFunctionReturn(PETSC_SUCCESS); 8160 } 8161 8162 /*@ 8163 MatSetUnfactored - Resets a factored matrix to be treated as unfactored. 8164 8165 Logically Collective 8166 8167 Input Parameter: 8168 . mat - the factored matrix to be reset 8169 8170 Level: developer 8171 8172 Notes: 8173 This routine should be used only with factored matrices formed by in-place 8174 factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE` 8175 format). This option can save memory, for example, when solving nonlinear 8176 systems with a matrix-free Newton-Krylov method and a matrix-based, in-place 8177 ILU(0) preconditioner. 8178 8179 One can specify in-place ILU(0) factorization by calling 8180 .vb 8181 PCType(pc,PCILU); 8182 PCFactorSeUseInPlace(pc); 8183 .ve 8184 or by using the options -pc_type ilu -pc_factor_in_place 8185 8186 In-place factorization ILU(0) can also be used as a local 8187 solver for the blocks within the block Jacobi or additive Schwarz 8188 methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc 8189 for details on setting local solver options. 8190 8191 Most users should employ the `KSP` interface for linear solvers 8192 instead of working directly with matrix algebra routines such as this. 8193 See, e.g., `KSPCreate()`. 8194 8195 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()` 8196 @*/ 8197 PetscErrorCode MatSetUnfactored(Mat mat) 8198 { 8199 PetscFunctionBegin; 8200 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8201 PetscValidType(mat, 1); 8202 MatCheckPreallocated(mat, 1); 8203 mat->factortype = MAT_FACTOR_NONE; 8204 if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS); 8205 PetscUseTypeMethod(mat, setunfactored); 8206 PetscFunctionReturn(PETSC_SUCCESS); 8207 } 8208 8209 /*MC 8210 MatDenseGetArrayF90 - Accesses a matrix array from Fortran 8211 8212 Synopsis: 8213 MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8214 8215 Not Collective 8216 8217 Input Parameter: 8218 . x - matrix 8219 8220 Output Parameters: 8221 + xx_v - the Fortran pointer to the array 8222 - ierr - error code 8223 8224 Example of Usage: 8225 .vb 8226 PetscScalar, pointer xx_v(:,:) 8227 .... 8228 call MatDenseGetArrayF90(x,xx_v,ierr) 8229 a = xx_v(3) 8230 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8231 .ve 8232 8233 Level: advanced 8234 8235 .seealso: [](ch_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()` 8236 M*/ 8237 8238 /*MC 8239 MatDenseRestoreArrayF90 - Restores a matrix array that has been 8240 accessed with `MatDenseGetArrayF90()`. 8241 8242 Synopsis: 8243 MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8244 8245 Not Collective 8246 8247 Input Parameters: 8248 + x - matrix 8249 - xx_v - the Fortran90 pointer to the array 8250 8251 Output Parameter: 8252 . ierr - error code 8253 8254 Example of Usage: 8255 .vb 8256 PetscScalar, pointer xx_v(:,:) 8257 .... 8258 call MatDenseGetArrayF90(x,xx_v,ierr) 8259 a = xx_v(3) 8260 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8261 .ve 8262 8263 Level: advanced 8264 8265 .seealso: [](ch_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()` 8266 M*/ 8267 8268 /*MC 8269 MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran. 8270 8271 Synopsis: 8272 MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8273 8274 Not Collective 8275 8276 Input Parameter: 8277 . x - matrix 8278 8279 Output Parameters: 8280 + xx_v - the Fortran pointer to the array 8281 - ierr - error code 8282 8283 Example of Usage: 8284 .vb 8285 PetscScalar, pointer xx_v(:) 8286 .... 8287 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8288 a = xx_v(3) 8289 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8290 .ve 8291 8292 Level: advanced 8293 8294 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()` 8295 M*/ 8296 8297 /*MC 8298 MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been 8299 accessed with `MatSeqAIJGetArrayF90()`. 8300 8301 Synopsis: 8302 MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8303 8304 Not Collective 8305 8306 Input Parameters: 8307 + x - matrix 8308 - xx_v - the Fortran90 pointer to the array 8309 8310 Output Parameter: 8311 . ierr - error code 8312 8313 Example of Usage: 8314 .vb 8315 PetscScalar, pointer xx_v(:) 8316 .... 8317 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8318 a = xx_v(3) 8319 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8320 .ve 8321 8322 Level: advanced 8323 8324 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()` 8325 M*/ 8326 8327 /*@ 8328 MatCreateSubMatrix - Gets a single submatrix on the same number of processors 8329 as the original matrix. 8330 8331 Collective 8332 8333 Input Parameters: 8334 + mat - the original matrix 8335 . isrow - parallel `IS` containing the rows this processor should obtain 8336 . 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. 8337 - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 8338 8339 Output Parameter: 8340 . newmat - the new submatrix, of the same type as the original matrix 8341 8342 Level: advanced 8343 8344 Notes: 8345 The submatrix will be able to be multiplied with vectors using the same layout as `iscol`. 8346 8347 Some matrix types place restrictions on the row and column indices, such 8348 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; 8349 for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row. 8350 8351 The index sets may not have duplicate entries. 8352 8353 The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`, 8354 the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls 8355 to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX` 8356 will reuse the matrix generated the first time. You should call `MatDestroy()` on `newmat` when 8357 you are finished using it. 8358 8359 The communicator of the newly obtained matrix is ALWAYS the same as the communicator of 8360 the input matrix. 8361 8362 If `iscol` is `NULL` then all columns are obtained (not supported in Fortran). 8363 8364 Example usage: 8365 Consider the following 8x8 matrix with 34 non-zero values, that is 8366 assembled across 3 processors. Let's assume that proc0 owns 3 rows, 8367 proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 8368 as follows 8369 .vb 8370 1 2 0 | 0 3 0 | 0 4 8371 Proc0 0 5 6 | 7 0 0 | 8 0 8372 9 0 10 | 11 0 0 | 12 0 8373 ------------------------------------- 8374 13 0 14 | 15 16 17 | 0 0 8375 Proc1 0 18 0 | 19 20 21 | 0 0 8376 0 0 0 | 22 23 0 | 24 0 8377 ------------------------------------- 8378 Proc2 25 26 27 | 0 0 28 | 29 0 8379 30 0 0 | 31 32 33 | 0 34 8380 .ve 8381 8382 Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6]. The resulting submatrix is 8383 8384 .vb 8385 2 0 | 0 3 0 | 0 8386 Proc0 5 6 | 7 0 0 | 8 8387 ------------------------------- 8388 Proc1 18 0 | 19 20 21 | 0 8389 ------------------------------- 8390 Proc2 26 27 | 0 0 28 | 29 8391 0 0 | 31 32 33 | 0 8392 .ve 8393 8394 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()` 8395 @*/ 8396 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat) 8397 { 8398 PetscMPIInt size; 8399 Mat *local; 8400 IS iscoltmp; 8401 PetscBool flg; 8402 8403 PetscFunctionBegin; 8404 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8405 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 8406 if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 8407 PetscValidPointer(newmat, 5); 8408 if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5); 8409 PetscValidType(mat, 1); 8410 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8411 PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX"); 8412 8413 MatCheckPreallocated(mat, 1); 8414 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8415 8416 if (!iscol || isrow == iscol) { 8417 PetscBool stride; 8418 PetscMPIInt grabentirematrix = 0, grab; 8419 PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride)); 8420 if (stride) { 8421 PetscInt first, step, n, rstart, rend; 8422 PetscCall(ISStrideGetInfo(isrow, &first, &step)); 8423 if (step == 1) { 8424 PetscCall(MatGetOwnershipRange(mat, &rstart, &rend)); 8425 if (rstart == first) { 8426 PetscCall(ISGetLocalSize(isrow, &n)); 8427 if (n == rend - rstart) grabentirematrix = 1; 8428 } 8429 } 8430 } 8431 PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat))); 8432 if (grab) { 8433 PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n")); 8434 if (cll == MAT_INITIAL_MATRIX) { 8435 *newmat = mat; 8436 PetscCall(PetscObjectReference((PetscObject)mat)); 8437 } 8438 PetscFunctionReturn(PETSC_SUCCESS); 8439 } 8440 } 8441 8442 if (!iscol) { 8443 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp)); 8444 } else { 8445 iscoltmp = iscol; 8446 } 8447 8448 /* if original matrix is on just one processor then use submatrix generated */ 8449 if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) { 8450 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat)); 8451 goto setproperties; 8452 } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) { 8453 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local)); 8454 *newmat = *local; 8455 PetscCall(PetscFree(local)); 8456 goto setproperties; 8457 } else if (!mat->ops->createsubmatrix) { 8458 /* Create a new matrix type that implements the operation using the full matrix */ 8459 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8460 switch (cll) { 8461 case MAT_INITIAL_MATRIX: 8462 PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat)); 8463 break; 8464 case MAT_REUSE_MATRIX: 8465 PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp)); 8466 break; 8467 default: 8468 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX"); 8469 } 8470 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8471 goto setproperties; 8472 } 8473 8474 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8475 PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat); 8476 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8477 8478 setproperties: 8479 PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg)); 8480 if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat)); 8481 if (!iscol) PetscCall(ISDestroy(&iscoltmp)); 8482 if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat)); 8483 PetscFunctionReturn(PETSC_SUCCESS); 8484 } 8485 8486 /*@ 8487 MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix 8488 8489 Not Collective 8490 8491 Input Parameters: 8492 + A - the matrix we wish to propagate options from 8493 - B - the matrix we wish to propagate options to 8494 8495 Level: beginner 8496 8497 Note: 8498 Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL` 8499 8500 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 8501 @*/ 8502 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B) 8503 { 8504 PetscFunctionBegin; 8505 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8506 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 8507 B->symmetry_eternal = A->symmetry_eternal; 8508 B->structural_symmetry_eternal = A->structural_symmetry_eternal; 8509 B->symmetric = A->symmetric; 8510 B->structurally_symmetric = A->structurally_symmetric; 8511 B->spd = A->spd; 8512 B->hermitian = A->hermitian; 8513 PetscFunctionReturn(PETSC_SUCCESS); 8514 } 8515 8516 /*@ 8517 MatStashSetInitialSize - sets the sizes of the matrix stash, that is 8518 used during the assembly process to store values that belong to 8519 other processors. 8520 8521 Not Collective 8522 8523 Input Parameters: 8524 + mat - the matrix 8525 . size - the initial size of the stash. 8526 - bsize - the initial size of the block-stash(if used). 8527 8528 Options Database Keys: 8529 + -matstash_initial_size <size> or <size0,size1,...sizep-1> - set initial size 8530 - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1> - set initial block size 8531 8532 Level: intermediate 8533 8534 Notes: 8535 The block-stash is used for values set with `MatSetValuesBlocked()` while 8536 the stash is used for values set with `MatSetValues()` 8537 8538 Run with the option -info and look for output of the form 8539 MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs. 8540 to determine the appropriate value, MM, to use for size and 8541 MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs. 8542 to determine the value, BMM to use for bsize 8543 8544 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()` 8545 @*/ 8546 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize) 8547 { 8548 PetscFunctionBegin; 8549 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8550 PetscValidType(mat, 1); 8551 PetscCall(MatStashSetInitialSize_Private(&mat->stash, size)); 8552 PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize)); 8553 PetscFunctionReturn(PETSC_SUCCESS); 8554 } 8555 8556 /*@ 8557 MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of 8558 the matrix 8559 8560 Neighbor-wise Collective 8561 8562 Input Parameters: 8563 + A - the matrix 8564 . x - the vector to be multiplied by the interpolation operator 8565 - y - the vector to be added to the result 8566 8567 Output Parameter: 8568 . w - the resulting vector 8569 8570 Level: intermediate 8571 8572 Notes: 8573 `w` may be the same vector as `y`. 8574 8575 This allows one to use either the restriction or interpolation (its transpose) 8576 matrix to do the interpolation 8577 8578 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8579 @*/ 8580 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w) 8581 { 8582 PetscInt M, N, Ny; 8583 8584 PetscFunctionBegin; 8585 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8586 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8587 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8588 PetscValidHeaderSpecific(w, VEC_CLASSID, 4); 8589 PetscCall(MatGetSize(A, &M, &N)); 8590 PetscCall(VecGetSize(y, &Ny)); 8591 if (M == Ny) { 8592 PetscCall(MatMultAdd(A, x, y, w)); 8593 } else { 8594 PetscCall(MatMultTransposeAdd(A, x, y, w)); 8595 } 8596 PetscFunctionReturn(PETSC_SUCCESS); 8597 } 8598 8599 /*@ 8600 MatInterpolate - y = A*x or A'*x depending on the shape of 8601 the matrix 8602 8603 Neighbor-wise Collective 8604 8605 Input Parameters: 8606 + A - the matrix 8607 - x - the vector to be interpolated 8608 8609 Output Parameter: 8610 . y - the resulting vector 8611 8612 Level: intermediate 8613 8614 Note: 8615 This allows one to use either the restriction or interpolation (its transpose) 8616 matrix to do the interpolation 8617 8618 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8619 @*/ 8620 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y) 8621 { 8622 PetscInt M, N, Ny; 8623 8624 PetscFunctionBegin; 8625 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8626 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8627 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8628 PetscCall(MatGetSize(A, &M, &N)); 8629 PetscCall(VecGetSize(y, &Ny)); 8630 if (M == Ny) { 8631 PetscCall(MatMult(A, x, y)); 8632 } else { 8633 PetscCall(MatMultTranspose(A, x, y)); 8634 } 8635 PetscFunctionReturn(PETSC_SUCCESS); 8636 } 8637 8638 /*@ 8639 MatRestrict - y = A*x or A'*x 8640 8641 Neighbor-wise Collective 8642 8643 Input Parameters: 8644 + A - the matrix 8645 - x - the vector to be restricted 8646 8647 Output Parameter: 8648 . y - the resulting vector 8649 8650 Level: intermediate 8651 8652 Note: 8653 This allows one to use either the restriction or interpolation (its transpose) 8654 matrix to do the restriction 8655 8656 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG` 8657 @*/ 8658 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y) 8659 { 8660 PetscInt M, N, Ny; 8661 8662 PetscFunctionBegin; 8663 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8664 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8665 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8666 PetscCall(MatGetSize(A, &M, &N)); 8667 PetscCall(VecGetSize(y, &Ny)); 8668 if (M == Ny) { 8669 PetscCall(MatMult(A, x, y)); 8670 } else { 8671 PetscCall(MatMultTranspose(A, x, y)); 8672 } 8673 PetscFunctionReturn(PETSC_SUCCESS); 8674 } 8675 8676 /*@ 8677 MatMatInterpolateAdd - Y = W + A*X or W + A'*X 8678 8679 Neighbor-wise Collective 8680 8681 Input Parameters: 8682 + A - the matrix 8683 . x - the input dense matrix to be multiplied 8684 - w - the input dense matrix to be added to the result 8685 8686 Output Parameter: 8687 . y - the output dense matrix 8688 8689 Level: intermediate 8690 8691 Note: 8692 This allows one to use either the restriction or interpolation (its transpose) 8693 matrix to do the interpolation. y matrix can be reused if already created with the proper sizes, 8694 otherwise it will be recreated. y must be initialized to `NULL` if not supplied. 8695 8696 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG` 8697 @*/ 8698 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y) 8699 { 8700 PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0; 8701 PetscBool trans = PETSC_TRUE; 8702 MatReuse reuse = MAT_INITIAL_MATRIX; 8703 8704 PetscFunctionBegin; 8705 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8706 PetscValidHeaderSpecific(x, MAT_CLASSID, 2); 8707 PetscValidType(x, 2); 8708 if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3); 8709 if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4); 8710 PetscCall(MatGetSize(A, &M, &N)); 8711 PetscCall(MatGetSize(x, &Mx, &Nx)); 8712 if (N == Mx) trans = PETSC_FALSE; 8713 else PetscCheck(M == Mx, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Size mismatch: A %" PetscInt_FMT "x%" PetscInt_FMT ", X %" PetscInt_FMT "x%" PetscInt_FMT, M, N, Mx, Nx); 8714 Mo = trans ? N : M; 8715 if (*y) { 8716 PetscCall(MatGetSize(*y, &My, &Ny)); 8717 if (Mo == My && Nx == Ny) { 8718 reuse = MAT_REUSE_MATRIX; 8719 } else { 8720 PetscCheck(w || *y != w, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot reuse y and w, size mismatch: A %" PetscInt_FMT "x%" PetscInt_FMT ", X %" PetscInt_FMT "x%" PetscInt_FMT ", Y %" PetscInt_FMT "x%" PetscInt_FMT, M, N, Mx, Nx, My, Ny); 8721 PetscCall(MatDestroy(y)); 8722 } 8723 } 8724 8725 if (w && *y == w) { /* this is to minimize changes in PCMG */ 8726 PetscBool flg; 8727 8728 PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w)); 8729 if (w) { 8730 PetscInt My, Ny, Mw, Nw; 8731 8732 PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg)); 8733 PetscCall(MatGetSize(*y, &My, &Ny)); 8734 PetscCall(MatGetSize(w, &Mw, &Nw)); 8735 if (!flg || My != Mw || Ny != Nw) w = NULL; 8736 } 8737 if (!w) { 8738 PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w)); 8739 PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w)); 8740 PetscCall(PetscObjectDereference((PetscObject)w)); 8741 } else { 8742 PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN)); 8743 } 8744 } 8745 if (!trans) { 8746 PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8747 } else { 8748 PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8749 } 8750 if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN)); 8751 PetscFunctionReturn(PETSC_SUCCESS); 8752 } 8753 8754 /*@ 8755 MatMatInterpolate - Y = A*X or A'*X 8756 8757 Neighbor-wise Collective 8758 8759 Input Parameters: 8760 + A - the matrix 8761 - x - the input dense matrix 8762 8763 Output Parameter: 8764 . y - the output dense matrix 8765 8766 Level: intermediate 8767 8768 Note: 8769 This allows one to use either the restriction or interpolation (its transpose) 8770 matrix to do the interpolation. y matrix can be reused if already created with the proper sizes, 8771 otherwise it will be recreated. y must be initialized to `NULL` if not supplied. 8772 8773 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG` 8774 @*/ 8775 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y) 8776 { 8777 PetscFunctionBegin; 8778 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8779 PetscFunctionReturn(PETSC_SUCCESS); 8780 } 8781 8782 /*@ 8783 MatMatRestrict - Y = A*X or A'*X 8784 8785 Neighbor-wise Collective 8786 8787 Input Parameters: 8788 + A - the matrix 8789 - x - the input dense matrix 8790 8791 Output Parameter: 8792 . y - the output dense matrix 8793 8794 Level: intermediate 8795 8796 Note: 8797 This allows one to use either the restriction or interpolation (its transpose) 8798 matrix to do the restriction. y matrix can be reused if already created with the proper sizes, 8799 otherwise it will be recreated. y must be initialized to `NULL` if not supplied. 8800 8801 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG` 8802 @*/ 8803 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y) 8804 { 8805 PetscFunctionBegin; 8806 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8807 PetscFunctionReturn(PETSC_SUCCESS); 8808 } 8809 8810 /*@ 8811 MatGetNullSpace - retrieves the null space of a matrix. 8812 8813 Logically Collective 8814 8815 Input Parameters: 8816 + mat - the matrix 8817 - nullsp - the null space object 8818 8819 Level: developer 8820 8821 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace` 8822 @*/ 8823 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp) 8824 { 8825 PetscFunctionBegin; 8826 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8827 PetscValidPointer(nullsp, 2); 8828 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp; 8829 PetscFunctionReturn(PETSC_SUCCESS); 8830 } 8831 8832 /*@ 8833 MatSetNullSpace - attaches a null space to a matrix. 8834 8835 Logically Collective 8836 8837 Input Parameters: 8838 + mat - the matrix 8839 - nullsp - the null space object 8840 8841 Level: advanced 8842 8843 Notes: 8844 This null space is used by the `KSP` linear solvers to solve singular systems. 8845 8846 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` 8847 8848 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 8849 to zero but the linear system will still be solved in a least squares sense. 8850 8851 The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that 8852 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). 8853 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 8854 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 8855 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). 8856 This \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix. 8857 8858 If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called 8859 `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this 8860 routine also automatically calls `MatSetTransposeNullSpace()`. 8861 8862 The user should call `MatNullSpaceDestroy()`. 8863 8864 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, 8865 `KSPSetPCSide()` 8866 @*/ 8867 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp) 8868 { 8869 PetscFunctionBegin; 8870 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8871 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8872 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8873 PetscCall(MatNullSpaceDestroy(&mat->nullsp)); 8874 mat->nullsp = nullsp; 8875 if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp)); 8876 PetscFunctionReturn(PETSC_SUCCESS); 8877 } 8878 8879 /*@ 8880 MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix. 8881 8882 Logically Collective 8883 8884 Input Parameters: 8885 + mat - the matrix 8886 - nullsp - the null space object 8887 8888 Level: developer 8889 8890 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()` 8891 @*/ 8892 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp) 8893 { 8894 PetscFunctionBegin; 8895 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8896 PetscValidType(mat, 1); 8897 PetscValidPointer(nullsp, 2); 8898 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp; 8899 PetscFunctionReturn(PETSC_SUCCESS); 8900 } 8901 8902 /*@ 8903 MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix 8904 8905 Logically Collective 8906 8907 Input Parameters: 8908 + mat - the matrix 8909 - nullsp - the null space object 8910 8911 Level: advanced 8912 8913 Notes: 8914 This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning. 8915 8916 See `MatSetNullSpace()` 8917 8918 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()` 8919 @*/ 8920 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp) 8921 { 8922 PetscFunctionBegin; 8923 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8924 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8925 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8926 PetscCall(MatNullSpaceDestroy(&mat->transnullsp)); 8927 mat->transnullsp = nullsp; 8928 PetscFunctionReturn(PETSC_SUCCESS); 8929 } 8930 8931 /*@ 8932 MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions 8933 This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix. 8934 8935 Logically Collective 8936 8937 Input Parameters: 8938 + mat - the matrix 8939 - nullsp - the null space object 8940 8941 Level: advanced 8942 8943 Notes: 8944 Overwrites any previous near null space that may have been attached 8945 8946 You can remove the null space by calling this routine with an nullsp of `NULL` 8947 8948 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()` 8949 @*/ 8950 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp) 8951 { 8952 PetscFunctionBegin; 8953 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8954 PetscValidType(mat, 1); 8955 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8956 MatCheckPreallocated(mat, 1); 8957 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8958 PetscCall(MatNullSpaceDestroy(&mat->nearnullsp)); 8959 mat->nearnullsp = nullsp; 8960 PetscFunctionReturn(PETSC_SUCCESS); 8961 } 8962 8963 /*@ 8964 MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()` 8965 8966 Not Collective 8967 8968 Input Parameter: 8969 . mat - the matrix 8970 8971 Output Parameter: 8972 . nullsp - the null space object, `NULL` if not set 8973 8974 Level: advanced 8975 8976 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()` 8977 @*/ 8978 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp) 8979 { 8980 PetscFunctionBegin; 8981 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8982 PetscValidType(mat, 1); 8983 PetscValidPointer(nullsp, 2); 8984 MatCheckPreallocated(mat, 1); 8985 *nullsp = mat->nearnullsp; 8986 PetscFunctionReturn(PETSC_SUCCESS); 8987 } 8988 8989 /*@C 8990 MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix. 8991 8992 Collective 8993 8994 Input Parameters: 8995 + mat - the matrix 8996 . row - row/column permutation 8997 - info - information on desired factorization process 8998 8999 Level: developer 9000 9001 Notes: 9002 Probably really in-place only when level of fill is zero, otherwise allocates 9003 new space to store factored matrix and deletes previous memory. 9004 9005 Most users should employ the `KSP` interface for linear solvers 9006 instead of working directly with matrix algebra routines such as this. 9007 See, e.g., `KSPCreate()`. 9008 9009 Developer Notes: 9010 The Fortran interface is not autogenerated as the 9011 interface definition cannot be generated correctly [due to `MatFactorInfo`] 9012 9013 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 9014 @*/ 9015 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info) 9016 { 9017 PetscFunctionBegin; 9018 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9019 PetscValidType(mat, 1); 9020 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 9021 PetscValidPointer(info, 3); 9022 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 9023 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 9024 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 9025 MatCheckPreallocated(mat, 1); 9026 PetscUseTypeMethod(mat, iccfactor, row, info); 9027 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9028 PetscFunctionReturn(PETSC_SUCCESS); 9029 } 9030 9031 /*@ 9032 MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the 9033 ghosted ones. 9034 9035 Not Collective 9036 9037 Input Parameters: 9038 + mat - the matrix 9039 - diag - the diagonal values, including ghost ones 9040 9041 Level: developer 9042 9043 Notes: 9044 Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices 9045 9046 This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()` 9047 9048 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 9049 @*/ 9050 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag) 9051 { 9052 PetscMPIInt size; 9053 9054 PetscFunctionBegin; 9055 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9056 PetscValidHeaderSpecific(diag, VEC_CLASSID, 2); 9057 PetscValidType(mat, 1); 9058 9059 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled"); 9060 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 9061 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 9062 if (size == 1) { 9063 PetscInt n, m; 9064 PetscCall(VecGetSize(diag, &n)); 9065 PetscCall(MatGetSize(mat, NULL, &m)); 9066 PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions"); 9067 PetscCall(MatDiagonalScale(mat, NULL, diag)); 9068 } else { 9069 PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag)); 9070 } 9071 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 9072 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9073 PetscFunctionReturn(PETSC_SUCCESS); 9074 } 9075 9076 /*@ 9077 MatGetInertia - Gets the inertia from a factored matrix 9078 9079 Collective 9080 9081 Input Parameter: 9082 . mat - the matrix 9083 9084 Output Parameters: 9085 + nneg - number of negative eigenvalues 9086 . nzero - number of zero eigenvalues 9087 - npos - number of positive eigenvalues 9088 9089 Level: advanced 9090 9091 Note: 9092 Matrix must have been factored by `MatCholeskyFactor()` 9093 9094 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()` 9095 @*/ 9096 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos) 9097 { 9098 PetscFunctionBegin; 9099 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9100 PetscValidType(mat, 1); 9101 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9102 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled"); 9103 PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos); 9104 PetscFunctionReturn(PETSC_SUCCESS); 9105 } 9106 9107 /*@C 9108 MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors 9109 9110 Neighbor-wise Collective 9111 9112 Input Parameters: 9113 + mat - the factored matrix obtained with `MatGetFactor()` 9114 - b - the right-hand-side vectors 9115 9116 Output Parameter: 9117 . x - the result vectors 9118 9119 Level: developer 9120 9121 Note: 9122 The vectors `b` and `x` cannot be the same. I.e., one cannot 9123 call `MatSolves`(A,x,x). 9124 9125 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()` 9126 @*/ 9127 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x) 9128 { 9129 PetscFunctionBegin; 9130 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9131 PetscValidType(mat, 1); 9132 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 9133 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9134 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 9135 9136 MatCheckPreallocated(mat, 1); 9137 PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0)); 9138 PetscUseTypeMethod(mat, solves, b, x); 9139 PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0)); 9140 PetscFunctionReturn(PETSC_SUCCESS); 9141 } 9142 9143 /*@ 9144 MatIsSymmetric - Test whether a matrix is symmetric 9145 9146 Collective 9147 9148 Input Parameters: 9149 + A - the matrix to test 9150 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose) 9151 9152 Output Parameter: 9153 . flg - the result 9154 9155 Level: intermediate 9156 9157 Notes: 9158 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9159 9160 If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()` 9161 9162 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9163 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9164 9165 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`, 9166 `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL` 9167 @*/ 9168 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg) 9169 { 9170 PetscFunctionBegin; 9171 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9172 PetscValidBoolPointer(flg, 3); 9173 9174 if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE; 9175 else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE; 9176 else { 9177 PetscUseTypeMethod(A, issymmetric, tol, flg); 9178 if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg)); 9179 } 9180 PetscFunctionReturn(PETSC_SUCCESS); 9181 } 9182 9183 /*@ 9184 MatIsHermitian - Test whether a matrix is Hermitian 9185 9186 Collective 9187 9188 Input Parameters: 9189 + A - the matrix to test 9190 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian) 9191 9192 Output Parameter: 9193 . flg - the result 9194 9195 Level: intermediate 9196 9197 Notes: 9198 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9199 9200 If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()` 9201 9202 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9203 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`) 9204 9205 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, 9206 `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL` 9207 @*/ 9208 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg) 9209 { 9210 PetscFunctionBegin; 9211 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9212 PetscValidBoolPointer(flg, 3); 9213 9214 if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE; 9215 else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE; 9216 else { 9217 PetscUseTypeMethod(A, ishermitian, tol, flg); 9218 if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg)); 9219 } 9220 PetscFunctionReturn(PETSC_SUCCESS); 9221 } 9222 9223 /*@ 9224 MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state 9225 9226 Not Collective 9227 9228 Input Parameter: 9229 . A - the matrix to check 9230 9231 Output Parameters: 9232 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid) 9233 - flg - the result (only valid if set is `PETSC_TRUE`) 9234 9235 Level: advanced 9236 9237 Notes: 9238 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()` 9239 if you want it explicitly checked 9240 9241 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9242 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9243 9244 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9245 @*/ 9246 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9247 { 9248 PetscFunctionBegin; 9249 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9250 PetscValidBoolPointer(set, 2); 9251 PetscValidBoolPointer(flg, 3); 9252 if (A->symmetric != PETSC_BOOL3_UNKNOWN) { 9253 *set = PETSC_TRUE; 9254 *flg = PetscBool3ToBool(A->symmetric); 9255 } else { 9256 *set = PETSC_FALSE; 9257 } 9258 PetscFunctionReturn(PETSC_SUCCESS); 9259 } 9260 9261 /*@ 9262 MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state 9263 9264 Not Collective 9265 9266 Input Parameter: 9267 . A - the matrix to check 9268 9269 Output Parameters: 9270 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid) 9271 - flg - the result (only valid if set is `PETSC_TRUE`) 9272 9273 Level: advanced 9274 9275 Notes: 9276 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). 9277 9278 One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD 9279 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`) 9280 9281 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9282 @*/ 9283 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg) 9284 { 9285 PetscFunctionBegin; 9286 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9287 PetscValidBoolPointer(set, 2); 9288 PetscValidBoolPointer(flg, 3); 9289 if (A->spd != PETSC_BOOL3_UNKNOWN) { 9290 *set = PETSC_TRUE; 9291 *flg = PetscBool3ToBool(A->spd); 9292 } else { 9293 *set = PETSC_FALSE; 9294 } 9295 PetscFunctionReturn(PETSC_SUCCESS); 9296 } 9297 9298 /*@ 9299 MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state 9300 9301 Not Collective 9302 9303 Input Parameter: 9304 . A - the matrix to check 9305 9306 Output Parameters: 9307 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid) 9308 - flg - the result (only valid if set is `PETSC_TRUE`) 9309 9310 Level: advanced 9311 9312 Notes: 9313 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()` 9314 if you want it explicitly checked 9315 9316 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9317 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9318 9319 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()` 9320 @*/ 9321 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg) 9322 { 9323 PetscFunctionBegin; 9324 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9325 PetscValidBoolPointer(set, 2); 9326 PetscValidBoolPointer(flg, 3); 9327 if (A->hermitian != PETSC_BOOL3_UNKNOWN) { 9328 *set = PETSC_TRUE; 9329 *flg = PetscBool3ToBool(A->hermitian); 9330 } else { 9331 *set = PETSC_FALSE; 9332 } 9333 PetscFunctionReturn(PETSC_SUCCESS); 9334 } 9335 9336 /*@ 9337 MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric 9338 9339 Collective 9340 9341 Input Parameter: 9342 . A - the matrix to test 9343 9344 Output Parameter: 9345 . flg - the result 9346 9347 Level: intermediate 9348 9349 Notes: 9350 If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()` 9351 9352 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 9353 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9354 9355 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()` 9356 @*/ 9357 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg) 9358 { 9359 PetscFunctionBegin; 9360 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9361 PetscValidBoolPointer(flg, 2); 9362 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9363 *flg = PetscBool3ToBool(A->structurally_symmetric); 9364 } else { 9365 PetscUseTypeMethod(A, isstructurallysymmetric, flg); 9366 PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg)); 9367 } 9368 PetscFunctionReturn(PETSC_SUCCESS); 9369 } 9370 9371 /*@ 9372 MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state 9373 9374 Not Collective 9375 9376 Input Parameter: 9377 . A - the matrix to check 9378 9379 Output Parameters: 9380 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid) 9381 - flg - the result (only valid if set is PETSC_TRUE) 9382 9383 Level: advanced 9384 9385 Notes: 9386 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 9387 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9388 9389 Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation) 9390 9391 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9392 @*/ 9393 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9394 { 9395 PetscFunctionBegin; 9396 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9397 PetscValidBoolPointer(set, 2); 9398 PetscValidBoolPointer(flg, 3); 9399 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9400 *set = PETSC_TRUE; 9401 *flg = PetscBool3ToBool(A->structurally_symmetric); 9402 } else { 9403 *set = PETSC_FALSE; 9404 } 9405 PetscFunctionReturn(PETSC_SUCCESS); 9406 } 9407 9408 /*@ 9409 MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need 9410 to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process 9411 9412 Not Collective 9413 9414 Input Parameter: 9415 . mat - the matrix 9416 9417 Output Parameters: 9418 + nstash - the size of the stash 9419 . reallocs - the number of additional mallocs incurred. 9420 . bnstash - the size of the block stash 9421 - breallocs - the number of additional mallocs incurred.in the block stash 9422 9423 Level: advanced 9424 9425 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()` 9426 @*/ 9427 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs) 9428 { 9429 PetscFunctionBegin; 9430 PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs)); 9431 PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs)); 9432 PetscFunctionReturn(PETSC_SUCCESS); 9433 } 9434 9435 /*@C 9436 MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same 9437 parallel layout, `PetscLayout` for rows and columns 9438 9439 Collective 9440 9441 Input Parameter: 9442 . mat - the matrix 9443 9444 Output Parameters: 9445 + right - (optional) vector that the matrix can be multiplied against 9446 - left - (optional) vector that the matrix vector product can be stored in 9447 9448 Level: advanced 9449 9450 Notes: 9451 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()`. 9452 9453 These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed 9454 9455 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()` 9456 @*/ 9457 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left) 9458 { 9459 PetscFunctionBegin; 9460 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9461 PetscValidType(mat, 1); 9462 if (mat->ops->getvecs) { 9463 PetscUseTypeMethod(mat, getvecs, right, left); 9464 } else { 9465 if (right) { 9466 PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup"); 9467 PetscCall(VecCreateWithLayout_Private(mat->cmap, right)); 9468 PetscCall(VecSetType(*right, mat->defaultvectype)); 9469 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9470 if (mat->boundtocpu && mat->bindingpropagates) { 9471 PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE)); 9472 PetscCall(VecBindToCPU(*right, PETSC_TRUE)); 9473 } 9474 #endif 9475 } 9476 if (left) { 9477 PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup"); 9478 PetscCall(VecCreateWithLayout_Private(mat->rmap, left)); 9479 PetscCall(VecSetType(*left, mat->defaultvectype)); 9480 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9481 if (mat->boundtocpu && mat->bindingpropagates) { 9482 PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE)); 9483 PetscCall(VecBindToCPU(*left, PETSC_TRUE)); 9484 } 9485 #endif 9486 } 9487 } 9488 PetscFunctionReturn(PETSC_SUCCESS); 9489 } 9490 9491 /*@C 9492 MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure 9493 with default values. 9494 9495 Not Collective 9496 9497 Input Parameter: 9498 . info - the `MatFactorInfo` data structure 9499 9500 Level: developer 9501 9502 Notes: 9503 The solvers are generally used through the `KSP` and `PC` objects, for example 9504 `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC` 9505 9506 Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed 9507 9508 Developer Notes: 9509 The Fortran interface is not autogenerated as the 9510 interface definition cannot be generated correctly [due to `MatFactorInfo`] 9511 9512 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo` 9513 @*/ 9514 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info) 9515 { 9516 PetscFunctionBegin; 9517 PetscCall(PetscMemzero(info, sizeof(MatFactorInfo))); 9518 PetscFunctionReturn(PETSC_SUCCESS); 9519 } 9520 9521 /*@ 9522 MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed 9523 9524 Collective 9525 9526 Input Parameters: 9527 + mat - the factored matrix 9528 - is - the index set defining the Schur indices (0-based) 9529 9530 Level: advanced 9531 9532 Notes: 9533 Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system. 9534 9535 You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call. 9536 9537 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9538 9539 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`, 9540 `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9541 @*/ 9542 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is) 9543 { 9544 PetscErrorCode (*f)(Mat, IS); 9545 9546 PetscFunctionBegin; 9547 PetscValidType(mat, 1); 9548 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9549 PetscValidType(is, 2); 9550 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 9551 PetscCheckSameComm(mat, 1, is, 2); 9552 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 9553 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f)); 9554 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO"); 9555 PetscCall(MatDestroy(&mat->schur)); 9556 PetscCall((*f)(mat, is)); 9557 PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created"); 9558 PetscFunctionReturn(PETSC_SUCCESS); 9559 } 9560 9561 /*@ 9562 MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step 9563 9564 Logically Collective 9565 9566 Input Parameters: 9567 + F - the factored matrix obtained by calling `MatGetFactor()` 9568 . S - location where to return the Schur complement, can be `NULL` 9569 - status - the status of the Schur complement matrix, can be `NULL` 9570 9571 Level: advanced 9572 9573 Notes: 9574 You must call `MatFactorSetSchurIS()` before calling this routine. 9575 9576 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9577 9578 The routine provides a copy of the Schur matrix stored within the solver data structures. 9579 The caller must destroy the object when it is no longer needed. 9580 If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse. 9581 9582 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) 9583 9584 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9585 9586 Developer Notes: 9587 The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc 9588 matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix. 9589 9590 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9591 @*/ 9592 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9593 { 9594 PetscFunctionBegin; 9595 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9596 if (S) PetscValidPointer(S, 2); 9597 if (status) PetscValidPointer(status, 3); 9598 if (S) { 9599 PetscErrorCode (*f)(Mat, Mat *); 9600 9601 PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f)); 9602 if (f) { 9603 PetscCall((*f)(F, S)); 9604 } else { 9605 PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S)); 9606 } 9607 } 9608 if (status) *status = F->schur_status; 9609 PetscFunctionReturn(PETSC_SUCCESS); 9610 } 9611 9612 /*@ 9613 MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix 9614 9615 Logically Collective 9616 9617 Input Parameters: 9618 + F - the factored matrix obtained by calling `MatGetFactor()` 9619 . S - location where to return the Schur complement, can be `NULL` 9620 - status - the status of the Schur complement matrix, can be `NULL` 9621 9622 Level: advanced 9623 9624 Notes: 9625 You must call `MatFactorSetSchurIS()` before calling this routine. 9626 9627 Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS` 9628 9629 The routine returns a the Schur Complement stored within the data structures of the solver. 9630 9631 If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement. 9632 9633 The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed. 9634 9635 Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix 9636 9637 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9638 9639 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9640 @*/ 9641 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9642 { 9643 PetscFunctionBegin; 9644 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9645 if (S) PetscValidPointer(S, 2); 9646 if (status) PetscValidPointer(status, 3); 9647 if (S) *S = F->schur; 9648 if (status) *status = F->schur_status; 9649 PetscFunctionReturn(PETSC_SUCCESS); 9650 } 9651 9652 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F) 9653 { 9654 Mat S = F->schur; 9655 9656 PetscFunctionBegin; 9657 switch (F->schur_status) { 9658 case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through 9659 case MAT_FACTOR_SCHUR_INVERTED: 9660 if (S) { 9661 S->ops->solve = NULL; 9662 S->ops->matsolve = NULL; 9663 S->ops->solvetranspose = NULL; 9664 S->ops->matsolvetranspose = NULL; 9665 S->ops->solveadd = NULL; 9666 S->ops->solvetransposeadd = NULL; 9667 S->factortype = MAT_FACTOR_NONE; 9668 PetscCall(PetscFree(S->solvertype)); 9669 } 9670 case MAT_FACTOR_SCHUR_FACTORED: // fall-through 9671 break; 9672 default: 9673 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9674 } 9675 PetscFunctionReturn(PETSC_SUCCESS); 9676 } 9677 9678 /*@ 9679 MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()` 9680 9681 Logically Collective 9682 9683 Input Parameters: 9684 + F - the factored matrix obtained by calling `MatGetFactor()` 9685 . S - location where the Schur complement is stored 9686 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`) 9687 9688 Level: advanced 9689 9690 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9691 @*/ 9692 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status) 9693 { 9694 PetscFunctionBegin; 9695 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9696 if (S) { 9697 PetscValidHeaderSpecific(*S, MAT_CLASSID, 2); 9698 *S = NULL; 9699 } 9700 F->schur_status = status; 9701 PetscCall(MatFactorUpdateSchurStatus_Private(F)); 9702 PetscFunctionReturn(PETSC_SUCCESS); 9703 } 9704 9705 /*@ 9706 MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step 9707 9708 Logically Collective 9709 9710 Input Parameters: 9711 + F - the factored matrix obtained by calling `MatGetFactor()` 9712 . rhs - location where the right hand side of the Schur complement system is stored 9713 - sol - location where the solution of the Schur complement system has to be returned 9714 9715 Level: advanced 9716 9717 Notes: 9718 The sizes of the vectors should match the size of the Schur complement 9719 9720 Must be called after `MatFactorSetSchurIS()` 9721 9722 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()` 9723 @*/ 9724 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol) 9725 { 9726 PetscFunctionBegin; 9727 PetscValidType(F, 1); 9728 PetscValidType(rhs, 2); 9729 PetscValidType(sol, 3); 9730 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9731 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9732 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9733 PetscCheckSameComm(F, 1, rhs, 2); 9734 PetscCheckSameComm(F, 1, sol, 3); 9735 PetscCall(MatFactorFactorizeSchurComplement(F)); 9736 switch (F->schur_status) { 9737 case MAT_FACTOR_SCHUR_FACTORED: 9738 PetscCall(MatSolveTranspose(F->schur, rhs, sol)); 9739 break; 9740 case MAT_FACTOR_SCHUR_INVERTED: 9741 PetscCall(MatMultTranspose(F->schur, rhs, sol)); 9742 break; 9743 default: 9744 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9745 } 9746 PetscFunctionReturn(PETSC_SUCCESS); 9747 } 9748 9749 /*@ 9750 MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step 9751 9752 Logically Collective 9753 9754 Input Parameters: 9755 + F - the factored matrix obtained by calling `MatGetFactor()` 9756 . rhs - location where the right hand side of the Schur complement system is stored 9757 - sol - location where the solution of the Schur complement system has to be returned 9758 9759 Level: advanced 9760 9761 Notes: 9762 The sizes of the vectors should match the size of the Schur complement 9763 9764 Must be called after `MatFactorSetSchurIS()` 9765 9766 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()` 9767 @*/ 9768 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol) 9769 { 9770 PetscFunctionBegin; 9771 PetscValidType(F, 1); 9772 PetscValidType(rhs, 2); 9773 PetscValidType(sol, 3); 9774 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9775 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9776 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9777 PetscCheckSameComm(F, 1, rhs, 2); 9778 PetscCheckSameComm(F, 1, sol, 3); 9779 PetscCall(MatFactorFactorizeSchurComplement(F)); 9780 switch (F->schur_status) { 9781 case MAT_FACTOR_SCHUR_FACTORED: 9782 PetscCall(MatSolve(F->schur, rhs, sol)); 9783 break; 9784 case MAT_FACTOR_SCHUR_INVERTED: 9785 PetscCall(MatMult(F->schur, rhs, sol)); 9786 break; 9787 default: 9788 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9789 } 9790 PetscFunctionReturn(PETSC_SUCCESS); 9791 } 9792 9793 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat); 9794 #if PetscDefined(HAVE_CUDA) 9795 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat); 9796 #endif 9797 9798 /* Schur status updated in the interface */ 9799 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F) 9800 { 9801 Mat S = F->schur; 9802 9803 PetscFunctionBegin; 9804 if (S) { 9805 PetscMPIInt size; 9806 PetscBool isdense, isdensecuda; 9807 9808 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size)); 9809 PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented"); 9810 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense)); 9811 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda)); 9812 PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name); 9813 PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0)); 9814 if (isdense) { 9815 PetscCall(MatSeqDenseInvertFactors_Private(S)); 9816 } else if (isdensecuda) { 9817 #if defined(PETSC_HAVE_CUDA) 9818 PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S)); 9819 #endif 9820 } 9821 // HIP?????????????? 9822 PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0)); 9823 } 9824 PetscFunctionReturn(PETSC_SUCCESS); 9825 } 9826 9827 /*@ 9828 MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step 9829 9830 Logically Collective 9831 9832 Input Parameter: 9833 . F - the factored matrix obtained by calling `MatGetFactor()` 9834 9835 Level: advanced 9836 9837 Notes: 9838 Must be called after `MatFactorSetSchurIS()`. 9839 9840 Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it. 9841 9842 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()` 9843 @*/ 9844 PetscErrorCode MatFactorInvertSchurComplement(Mat F) 9845 { 9846 PetscFunctionBegin; 9847 PetscValidType(F, 1); 9848 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9849 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS); 9850 PetscCall(MatFactorFactorizeSchurComplement(F)); 9851 PetscCall(MatFactorInvertSchurComplement_Private(F)); 9852 F->schur_status = MAT_FACTOR_SCHUR_INVERTED; 9853 PetscFunctionReturn(PETSC_SUCCESS); 9854 } 9855 9856 /*@ 9857 MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step 9858 9859 Logically Collective 9860 9861 Input Parameter: 9862 . F - the factored matrix obtained by calling `MatGetFactor()` 9863 9864 Level: advanced 9865 9866 Note: 9867 Must be called after `MatFactorSetSchurIS()` 9868 9869 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()` 9870 @*/ 9871 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F) 9872 { 9873 MatFactorInfo info; 9874 9875 PetscFunctionBegin; 9876 PetscValidType(F, 1); 9877 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9878 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS); 9879 PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0)); 9880 PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo))); 9881 if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */ 9882 PetscCall(MatCholeskyFactor(F->schur, NULL, &info)); 9883 } else { 9884 PetscCall(MatLUFactor(F->schur, NULL, NULL, &info)); 9885 } 9886 PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0)); 9887 F->schur_status = MAT_FACTOR_SCHUR_FACTORED; 9888 PetscFunctionReturn(PETSC_SUCCESS); 9889 } 9890 9891 /*@ 9892 MatPtAP - Creates the matrix product C = P^T * A * P 9893 9894 Neighbor-wise Collective 9895 9896 Input Parameters: 9897 + A - the matrix 9898 . P - the projection matrix 9899 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9900 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate 9901 if the result is a dense matrix this is irrelevant 9902 9903 Output Parameter: 9904 . C - the product matrix 9905 9906 Level: intermediate 9907 9908 Notes: 9909 C will be created and must be destroyed by the user with `MatDestroy()`. 9910 9911 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9912 9913 Developer Notes: 9914 For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`. 9915 9916 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()` 9917 @*/ 9918 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C) 9919 { 9920 PetscFunctionBegin; 9921 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 9922 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9923 9924 if (scall == MAT_INITIAL_MATRIX) { 9925 PetscCall(MatProductCreate(A, P, NULL, C)); 9926 PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP)); 9927 PetscCall(MatProductSetAlgorithm(*C, "default")); 9928 PetscCall(MatProductSetFill(*C, fill)); 9929 9930 (*C)->product->api_user = PETSC_TRUE; 9931 PetscCall(MatProductSetFromOptions(*C)); 9932 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); 9933 PetscCall(MatProductSymbolic(*C)); 9934 } else { /* scall == MAT_REUSE_MATRIX */ 9935 PetscCall(MatProductReplaceMats(A, P, NULL, *C)); 9936 } 9937 9938 PetscCall(MatProductNumeric(*C)); 9939 (*C)->symmetric = A->symmetric; 9940 (*C)->spd = A->spd; 9941 PetscFunctionReturn(PETSC_SUCCESS); 9942 } 9943 9944 /*@ 9945 MatRARt - Creates the matrix product C = R * A * R^T 9946 9947 Neighbor-wise Collective 9948 9949 Input Parameters: 9950 + A - the matrix 9951 . R - the projection matrix 9952 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9953 - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate 9954 if the result is a dense matrix this is irrelevant 9955 9956 Output Parameter: 9957 . C - the product matrix 9958 9959 Level: intermediate 9960 9961 Notes: 9962 C will be created and must be destroyed by the user with `MatDestroy()`. 9963 9964 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9965 9966 This routine is currently only implemented for pairs of `MATAIJ` matrices and classes 9967 which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes, 9968 parallel MatRARt is implemented via explicit transpose of R, which could be very expensive. 9969 We recommend using MatPtAP(). 9970 9971 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()` 9972 @*/ 9973 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C) 9974 { 9975 PetscFunctionBegin; 9976 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 9977 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9978 9979 if (scall == MAT_INITIAL_MATRIX) { 9980 PetscCall(MatProductCreate(A, R, NULL, C)); 9981 PetscCall(MatProductSetType(*C, MATPRODUCT_RARt)); 9982 PetscCall(MatProductSetAlgorithm(*C, "default")); 9983 PetscCall(MatProductSetFill(*C, fill)); 9984 9985 (*C)->product->api_user = PETSC_TRUE; 9986 PetscCall(MatProductSetFromOptions(*C)); 9987 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); 9988 PetscCall(MatProductSymbolic(*C)); 9989 } else { /* scall == MAT_REUSE_MATRIX */ 9990 PetscCall(MatProductReplaceMats(A, R, NULL, *C)); 9991 } 9992 9993 PetscCall(MatProductNumeric(*C)); 9994 if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 9995 PetscFunctionReturn(PETSC_SUCCESS); 9996 } 9997 9998 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C) 9999 { 10000 PetscFunctionBegin; 10001 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10002 10003 if (scall == MAT_INITIAL_MATRIX) { 10004 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype])); 10005 PetscCall(MatProductCreate(A, B, NULL, C)); 10006 PetscCall(MatProductSetType(*C, ptype)); 10007 PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT)); 10008 PetscCall(MatProductSetFill(*C, fill)); 10009 10010 (*C)->product->api_user = PETSC_TRUE; 10011 PetscCall(MatProductSetFromOptions(*C)); 10012 PetscCall(MatProductSymbolic(*C)); 10013 } else { /* scall == MAT_REUSE_MATRIX */ 10014 Mat_Product *product = (*C)->product; 10015 PetscBool isdense; 10016 10017 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, "")); 10018 if (isdense && product && product->type != ptype) { 10019 PetscCall(MatProductClear(*C)); 10020 product = NULL; 10021 } 10022 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype])); 10023 if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */ 10024 PetscCheck(isdense, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first"); 10025 PetscCall(MatProductCreate_Private(A, B, NULL, *C)); 10026 product = (*C)->product; 10027 product->fill = fill; 10028 product->api_user = PETSC_TRUE; 10029 product->clear = PETSC_TRUE; 10030 10031 PetscCall(MatProductSetType(*C, ptype)); 10032 PetscCall(MatProductSetFromOptions(*C)); 10033 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); 10034 PetscCall(MatProductSymbolic(*C)); 10035 } else { /* user may change input matrices A or B when REUSE */ 10036 PetscCall(MatProductReplaceMats(A, B, NULL, *C)); 10037 } 10038 } 10039 PetscCall(MatProductNumeric(*C)); 10040 PetscFunctionReturn(PETSC_SUCCESS); 10041 } 10042 10043 /*@ 10044 MatMatMult - Performs matrix-matrix multiplication C=A*B. 10045 10046 Neighbor-wise Collective 10047 10048 Input Parameters: 10049 + A - the left matrix 10050 . B - the right matrix 10051 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10052 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate 10053 if the result is a dense matrix this is irrelevant 10054 10055 Output Parameter: 10056 . C - the product matrix 10057 10058 Notes: 10059 Unless scall is `MAT_REUSE_MATRIX` C will be created. 10060 10061 `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 10062 call to this function with `MAT_INITIAL_MATRIX`. 10063 10064 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed. 10065 10066 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`, 10067 rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse. 10068 10069 Example of Usage: 10070 .vb 10071 MatProductCreate(A,B,NULL,&C); 10072 MatProductSetType(C,MATPRODUCT_AB); 10073 MatProductSymbolic(C); 10074 MatProductNumeric(C); // compute C=A * B 10075 MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1 10076 MatProductNumeric(C); 10077 MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1 10078 MatProductNumeric(C); 10079 .ve 10080 10081 Level: intermediate 10082 10083 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()` 10084 @*/ 10085 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10086 { 10087 PetscFunctionBegin; 10088 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C)); 10089 PetscFunctionReturn(PETSC_SUCCESS); 10090 } 10091 10092 /*@ 10093 MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T. 10094 10095 Neighbor-wise Collective 10096 10097 Input Parameters: 10098 + A - the left matrix 10099 . B - the right matrix 10100 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10101 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 10102 10103 Output Parameter: 10104 . C - the product matrix 10105 10106 Level: intermediate 10107 10108 Notes: 10109 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10110 10111 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call 10112 10113 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10114 actually needed. 10115 10116 This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class, 10117 and for pairs of `MATMPIDENSE` matrices. 10118 10119 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt` 10120 10121 Options Database Keys: 10122 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the 10123 first redundantly copies the transposed B matrix on each process and requires O(log P) communication complexity; 10124 the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity. 10125 10126 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType` 10127 @*/ 10128 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10129 { 10130 PetscFunctionBegin; 10131 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C)); 10132 if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10133 PetscFunctionReturn(PETSC_SUCCESS); 10134 } 10135 10136 /*@ 10137 MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B. 10138 10139 Neighbor-wise Collective 10140 10141 Input Parameters: 10142 + A - the left matrix 10143 . B - the right matrix 10144 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10145 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 10146 10147 Output Parameter: 10148 . C - the product matrix 10149 10150 Level: intermediate 10151 10152 Notes: 10153 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10154 10155 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call. 10156 10157 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB` 10158 10159 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10160 actually needed. 10161 10162 This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes 10163 which inherit from `MATSEQAIJ`. C will be of the same type as the input matrices. 10164 10165 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()` 10166 @*/ 10167 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10168 { 10169 PetscFunctionBegin; 10170 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C)); 10171 PetscFunctionReturn(PETSC_SUCCESS); 10172 } 10173 10174 /*@ 10175 MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C. 10176 10177 Neighbor-wise Collective 10178 10179 Input Parameters: 10180 + A - the left matrix 10181 . B - the middle matrix 10182 . C - the right matrix 10183 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10184 - 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 10185 if the result is a dense matrix this is irrelevant 10186 10187 Output Parameter: 10188 . D - the product matrix 10189 10190 Level: intermediate 10191 10192 Notes: 10193 Unless scall is `MAT_REUSE_MATRIX` D will be created. 10194 10195 `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call 10196 10197 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC` 10198 10199 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10200 actually needed. 10201 10202 If you have many matrices with the same non-zero structure to multiply, you 10203 should use `MAT_REUSE_MATRIX` in all calls but the first 10204 10205 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()` 10206 @*/ 10207 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D) 10208 { 10209 PetscFunctionBegin; 10210 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6); 10211 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10212 10213 if (scall == MAT_INITIAL_MATRIX) { 10214 PetscCall(MatProductCreate(A, B, C, D)); 10215 PetscCall(MatProductSetType(*D, MATPRODUCT_ABC)); 10216 PetscCall(MatProductSetAlgorithm(*D, "default")); 10217 PetscCall(MatProductSetFill(*D, fill)); 10218 10219 (*D)->product->api_user = PETSC_TRUE; 10220 PetscCall(MatProductSetFromOptions(*D)); 10221 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, 10222 ((PetscObject)C)->type_name); 10223 PetscCall(MatProductSymbolic(*D)); 10224 } else { /* user may change input matrices when REUSE */ 10225 PetscCall(MatProductReplaceMats(A, B, C, *D)); 10226 } 10227 PetscCall(MatProductNumeric(*D)); 10228 PetscFunctionReturn(PETSC_SUCCESS); 10229 } 10230 10231 /*@ 10232 MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators. 10233 10234 Collective 10235 10236 Input Parameters: 10237 + mat - the matrix 10238 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices) 10239 . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used) 10240 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10241 10242 Output Parameter: 10243 . matredundant - redundant matrix 10244 10245 Level: advanced 10246 10247 Notes: 10248 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 10249 original matrix has not changed from that last call to MatCreateRedundantMatrix(). 10250 10251 This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before 10252 calling it. 10253 10254 `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be. 10255 10256 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm` 10257 @*/ 10258 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant) 10259 { 10260 MPI_Comm comm; 10261 PetscMPIInt size; 10262 PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs; 10263 Mat_Redundant *redund = NULL; 10264 PetscSubcomm psubcomm = NULL; 10265 MPI_Comm subcomm_in = subcomm; 10266 Mat *matseq; 10267 IS isrow, iscol; 10268 PetscBool newsubcomm = PETSC_FALSE; 10269 10270 PetscFunctionBegin; 10271 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10272 if (nsubcomm && reuse == MAT_REUSE_MATRIX) { 10273 PetscValidPointer(*matredundant, 5); 10274 PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5); 10275 } 10276 10277 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10278 if (size == 1 || nsubcomm == 1) { 10279 if (reuse == MAT_INITIAL_MATRIX) { 10280 PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant)); 10281 } else { 10282 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"); 10283 PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN)); 10284 } 10285 PetscFunctionReturn(PETSC_SUCCESS); 10286 } 10287 10288 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10289 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10290 MatCheckPreallocated(mat, 1); 10291 10292 PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0)); 10293 if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */ 10294 /* create psubcomm, then get subcomm */ 10295 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10296 PetscCallMPI(MPI_Comm_size(comm, &size)); 10297 PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size); 10298 10299 PetscCall(PetscSubcommCreate(comm, &psubcomm)); 10300 PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm)); 10301 PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS)); 10302 PetscCall(PetscSubcommSetFromOptions(psubcomm)); 10303 PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL)); 10304 newsubcomm = PETSC_TRUE; 10305 PetscCall(PetscSubcommDestroy(&psubcomm)); 10306 } 10307 10308 /* get isrow, iscol and a local sequential matrix matseq[0] */ 10309 if (reuse == MAT_INITIAL_MATRIX) { 10310 mloc_sub = PETSC_DECIDE; 10311 nloc_sub = PETSC_DECIDE; 10312 if (bs < 1) { 10313 PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M)); 10314 PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N)); 10315 } else { 10316 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M)); 10317 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N)); 10318 } 10319 PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm)); 10320 rstart = rend - mloc_sub; 10321 PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow)); 10322 PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol)); 10323 } else { /* reuse == MAT_REUSE_MATRIX */ 10324 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"); 10325 /* retrieve subcomm */ 10326 PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm)); 10327 redund = (*matredundant)->redundant; 10328 isrow = redund->isrow; 10329 iscol = redund->iscol; 10330 matseq = redund->matseq; 10331 } 10332 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq)); 10333 10334 /* get matredundant over subcomm */ 10335 if (reuse == MAT_INITIAL_MATRIX) { 10336 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant)); 10337 10338 /* create a supporting struct and attach it to C for reuse */ 10339 PetscCall(PetscNew(&redund)); 10340 (*matredundant)->redundant = redund; 10341 redund->isrow = isrow; 10342 redund->iscol = iscol; 10343 redund->matseq = matseq; 10344 if (newsubcomm) { 10345 redund->subcomm = subcomm; 10346 } else { 10347 redund->subcomm = MPI_COMM_NULL; 10348 } 10349 } else { 10350 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant)); 10351 } 10352 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 10353 if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) { 10354 PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE)); 10355 PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE)); 10356 } 10357 #endif 10358 PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0)); 10359 PetscFunctionReturn(PETSC_SUCCESS); 10360 } 10361 10362 /*@C 10363 MatGetMultiProcBlock - Create multiple 'parallel submatrices' from 10364 a given `Mat`. Each submatrix can span multiple procs. 10365 10366 Collective 10367 10368 Input Parameters: 10369 + mat - the matrix 10370 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))` 10371 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10372 10373 Output Parameter: 10374 . subMat - parallel sub-matrices each spanning a given `subcomm` 10375 10376 Level: advanced 10377 10378 Notes: 10379 The submatrix partition across processors is dictated by `subComm` a 10380 communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm` 10381 is not restricted to be grouped with consecutive original ranks. 10382 10383 Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices 10384 map directly to the layout of the original matrix [wrt the local 10385 row,col partitioning]. So the original 'DiagonalMat' naturally maps 10386 into the 'DiagonalMat' of the `subMat`, hence it is used directly from 10387 the `subMat`. However the offDiagMat looses some columns - and this is 10388 reconstructed with `MatSetValues()` 10389 10390 This is used by `PCBJACOBI` when a single block spans multiple MPI processes. 10391 10392 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI` 10393 @*/ 10394 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) 10395 { 10396 PetscMPIInt commsize, subCommSize; 10397 10398 PetscFunctionBegin; 10399 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize)); 10400 PetscCallMPI(MPI_Comm_size(subComm, &subCommSize)); 10401 PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize); 10402 10403 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"); 10404 PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10405 PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat); 10406 PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10407 PetscFunctionReturn(PETSC_SUCCESS); 10408 } 10409 10410 /*@ 10411 MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering 10412 10413 Not Collective 10414 10415 Input Parameters: 10416 + mat - matrix to extract local submatrix from 10417 . isrow - local row indices for submatrix 10418 - iscol - local column indices for submatrix 10419 10420 Output Parameter: 10421 . submat - the submatrix 10422 10423 Level: intermediate 10424 10425 Notes: 10426 `submat` should be disposed of with `MatRestoreLocalSubMatrix()`. 10427 10428 Depending on the format of `mat`, the returned submat may not implement `MatMult()`. Its communicator may be 10429 the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of `mat`'s. 10430 10431 `submat` always implements `MatSetValuesLocal()`. If `isrow` and `iscol` have the same block size, then 10432 `MatSetValuesBlockedLocal()` will also be implemented. 10433 10434 `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`. 10435 Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided. 10436 10437 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()` 10438 @*/ 10439 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10440 { 10441 PetscFunctionBegin; 10442 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10443 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10444 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10445 PetscCheckSameComm(isrow, 2, iscol, 3); 10446 PetscValidPointer(submat, 4); 10447 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call"); 10448 10449 if (mat->ops->getlocalsubmatrix) { 10450 PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat); 10451 } else { 10452 PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat)); 10453 } 10454 PetscFunctionReturn(PETSC_SUCCESS); 10455 } 10456 10457 /*@ 10458 MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()` 10459 10460 Not Collective 10461 10462 Input Parameters: 10463 + mat - matrix to extract local submatrix from 10464 . isrow - local row indices for submatrix 10465 . iscol - local column indices for submatrix 10466 - submat - the submatrix 10467 10468 Level: intermediate 10469 10470 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()` 10471 @*/ 10472 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10473 { 10474 PetscFunctionBegin; 10475 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10476 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10477 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10478 PetscCheckSameComm(isrow, 2, iscol, 3); 10479 PetscValidPointer(submat, 4); 10480 if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4); 10481 10482 if (mat->ops->restorelocalsubmatrix) { 10483 PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat); 10484 } else { 10485 PetscCall(MatDestroy(submat)); 10486 } 10487 *submat = NULL; 10488 PetscFunctionReturn(PETSC_SUCCESS); 10489 } 10490 10491 /*@ 10492 MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix 10493 10494 Collective 10495 10496 Input Parameter: 10497 . mat - the matrix 10498 10499 Output Parameter: 10500 . is - if any rows have zero diagonals this contains the list of them 10501 10502 Level: developer 10503 10504 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10505 @*/ 10506 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is) 10507 { 10508 PetscFunctionBegin; 10509 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10510 PetscValidType(mat, 1); 10511 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10512 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10513 10514 if (!mat->ops->findzerodiagonals) { 10515 Vec diag; 10516 const PetscScalar *a; 10517 PetscInt *rows; 10518 PetscInt rStart, rEnd, r, nrow = 0; 10519 10520 PetscCall(MatCreateVecs(mat, &diag, NULL)); 10521 PetscCall(MatGetDiagonal(mat, diag)); 10522 PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd)); 10523 PetscCall(VecGetArrayRead(diag, &a)); 10524 for (r = 0; r < rEnd - rStart; ++r) 10525 if (a[r] == 0.0) ++nrow; 10526 PetscCall(PetscMalloc1(nrow, &rows)); 10527 nrow = 0; 10528 for (r = 0; r < rEnd - rStart; ++r) 10529 if (a[r] == 0.0) rows[nrow++] = r + rStart; 10530 PetscCall(VecRestoreArrayRead(diag, &a)); 10531 PetscCall(VecDestroy(&diag)); 10532 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is)); 10533 } else { 10534 PetscUseTypeMethod(mat, findzerodiagonals, is); 10535 } 10536 PetscFunctionReturn(PETSC_SUCCESS); 10537 } 10538 10539 /*@ 10540 MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size) 10541 10542 Collective 10543 10544 Input Parameter: 10545 . mat - the matrix 10546 10547 Output Parameter: 10548 . is - contains the list of rows with off block diagonal entries 10549 10550 Level: developer 10551 10552 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10553 @*/ 10554 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is) 10555 { 10556 PetscFunctionBegin; 10557 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10558 PetscValidType(mat, 1); 10559 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10560 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10561 10562 PetscUseTypeMethod(mat, findoffblockdiagonalentries, is); 10563 PetscFunctionReturn(PETSC_SUCCESS); 10564 } 10565 10566 /*@C 10567 MatInvertBlockDiagonal - Inverts the block diagonal entries. 10568 10569 Collective; No Fortran Support 10570 10571 Input Parameter: 10572 . mat - the matrix 10573 10574 Output Parameter: 10575 . values - the block inverses in column major order (FORTRAN-like) 10576 10577 Level: advanced 10578 10579 Notes: 10580 The size of the blocks is determined by the block size of the matrix. 10581 10582 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10583 10584 The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size 10585 10586 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()` 10587 @*/ 10588 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values) 10589 { 10590 PetscFunctionBegin; 10591 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10592 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10593 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10594 PetscUseTypeMethod(mat, invertblockdiagonal, values); 10595 PetscFunctionReturn(PETSC_SUCCESS); 10596 } 10597 10598 /*@C 10599 MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries. 10600 10601 Collective; No Fortran Support 10602 10603 Input Parameters: 10604 + mat - the matrix 10605 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()` 10606 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()` 10607 10608 Output Parameter: 10609 . values - the block inverses in column major order (FORTRAN-like) 10610 10611 Level: advanced 10612 10613 Notes: 10614 Use `MatInvertBlockDiagonal()` if all blocks have the same size 10615 10616 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10617 10618 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()` 10619 @*/ 10620 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values) 10621 { 10622 PetscFunctionBegin; 10623 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10624 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10625 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10626 PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values); 10627 PetscFunctionReturn(PETSC_SUCCESS); 10628 } 10629 10630 /*@ 10631 MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A 10632 10633 Collective 10634 10635 Input Parameters: 10636 + A - the matrix 10637 - C - matrix with inverted block diagonal of `A`. This matrix should be created and may have its type set. 10638 10639 Level: advanced 10640 10641 Note: 10642 The blocksize of the matrix is used to determine the blocks on the diagonal of `C` 10643 10644 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()` 10645 @*/ 10646 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C) 10647 { 10648 const PetscScalar *vals; 10649 PetscInt *dnnz; 10650 PetscInt m, rstart, rend, bs, i, j; 10651 10652 PetscFunctionBegin; 10653 PetscCall(MatInvertBlockDiagonal(A, &vals)); 10654 PetscCall(MatGetBlockSize(A, &bs)); 10655 PetscCall(MatGetLocalSize(A, &m, NULL)); 10656 PetscCall(MatSetLayouts(C, A->rmap, A->cmap)); 10657 PetscCall(PetscMalloc1(m / bs, &dnnz)); 10658 for (j = 0; j < m / bs; j++) dnnz[j] = 1; 10659 PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL)); 10660 PetscCall(PetscFree(dnnz)); 10661 PetscCall(MatGetOwnershipRange(C, &rstart, &rend)); 10662 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE)); 10663 for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES)); 10664 PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 10665 PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 10666 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE)); 10667 PetscFunctionReturn(PETSC_SUCCESS); 10668 } 10669 10670 /*@C 10671 MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created 10672 via `MatTransposeColoringCreate()`. 10673 10674 Collective 10675 10676 Input Parameter: 10677 . c - coloring context 10678 10679 Level: intermediate 10680 10681 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()` 10682 @*/ 10683 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c) 10684 { 10685 MatTransposeColoring matcolor = *c; 10686 10687 PetscFunctionBegin; 10688 if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS); 10689 if (--((PetscObject)matcolor)->refct > 0) { 10690 matcolor = NULL; 10691 PetscFunctionReturn(PETSC_SUCCESS); 10692 } 10693 10694 PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow)); 10695 PetscCall(PetscFree(matcolor->rows)); 10696 PetscCall(PetscFree(matcolor->den2sp)); 10697 PetscCall(PetscFree(matcolor->colorforcol)); 10698 PetscCall(PetscFree(matcolor->columns)); 10699 if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart)); 10700 PetscCall(PetscHeaderDestroy(c)); 10701 PetscFunctionReturn(PETSC_SUCCESS); 10702 } 10703 10704 /*@C 10705 MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which 10706 a `MatTransposeColoring` context has been created, computes a dense B^T by applying 10707 `MatTransposeColoring` to sparse B. 10708 10709 Collective 10710 10711 Input Parameters: 10712 + coloring - coloring context created with `MatTransposeColoringCreate()` 10713 - B - sparse matrix 10714 10715 Output Parameter: 10716 . Btdense - dense matrix B^T 10717 10718 Level: developer 10719 10720 Note: 10721 These are used internally for some implementations of `MatRARt()` 10722 10723 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()` 10724 @*/ 10725 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense) 10726 { 10727 PetscFunctionBegin; 10728 PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10729 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 10730 PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3); 10731 10732 PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense)); 10733 PetscFunctionReturn(PETSC_SUCCESS); 10734 } 10735 10736 /*@C 10737 MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which 10738 a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense 10739 in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix 10740 `Csp` from `Cden`. 10741 10742 Collective 10743 10744 Input Parameters: 10745 + matcoloring - coloring context created with `MatTransposeColoringCreate()` 10746 - Cden - matrix product of a sparse matrix and a dense matrix Btdense 10747 10748 Output Parameter: 10749 . Csp - sparse matrix 10750 10751 Level: developer 10752 10753 Note: 10754 These are used internally for some implementations of `MatRARt()` 10755 10756 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()` 10757 @*/ 10758 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp) 10759 { 10760 PetscFunctionBegin; 10761 PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10762 PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2); 10763 PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3); 10764 10765 PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp)); 10766 PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY)); 10767 PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY)); 10768 PetscFunctionReturn(PETSC_SUCCESS); 10769 } 10770 10771 /*@C 10772 MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T. 10773 10774 Collective 10775 10776 Input Parameters: 10777 + mat - the matrix product C 10778 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()` 10779 10780 Output Parameter: 10781 . color - the new coloring context 10782 10783 Level: intermediate 10784 10785 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`, 10786 `MatTransColoringApplyDenToSp()` 10787 @*/ 10788 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color) 10789 { 10790 MatTransposeColoring c; 10791 MPI_Comm comm; 10792 10793 PetscFunctionBegin; 10794 PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10795 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10796 PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL)); 10797 10798 c->ctype = iscoloring->ctype; 10799 PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c); 10800 10801 *color = c; 10802 PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10803 PetscFunctionReturn(PETSC_SUCCESS); 10804 } 10805 10806 /*@ 10807 MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the 10808 matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the 10809 same, otherwise it will be larger 10810 10811 Not Collective 10812 10813 Input Parameter: 10814 . mat - the matrix 10815 10816 Output Parameter: 10817 . state - the current state 10818 10819 Level: intermediate 10820 10821 Notes: 10822 You can only compare states from two different calls to the SAME matrix, you cannot compare calls between 10823 different matrices 10824 10825 Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix 10826 10827 Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers. 10828 10829 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()` 10830 @*/ 10831 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state) 10832 { 10833 PetscFunctionBegin; 10834 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10835 *state = mat->nonzerostate; 10836 PetscFunctionReturn(PETSC_SUCCESS); 10837 } 10838 10839 /*@ 10840 MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential 10841 matrices from each processor 10842 10843 Collective 10844 10845 Input Parameters: 10846 + comm - the communicators the parallel matrix will live on 10847 . seqmat - the input sequential matrices 10848 . n - number of local columns (or `PETSC_DECIDE`) 10849 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10850 10851 Output Parameter: 10852 . mpimat - the parallel matrix generated 10853 10854 Level: developer 10855 10856 Note: 10857 The number of columns of the matrix in EACH processor MUST be the same. 10858 10859 .seealso: [](ch_matrices), `Mat` 10860 @*/ 10861 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat) 10862 { 10863 PetscMPIInt size; 10864 10865 PetscFunctionBegin; 10866 PetscCallMPI(MPI_Comm_size(comm, &size)); 10867 if (size == 1) { 10868 if (reuse == MAT_INITIAL_MATRIX) { 10869 PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat)); 10870 } else { 10871 PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN)); 10872 } 10873 PetscFunctionReturn(PETSC_SUCCESS); 10874 } 10875 10876 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"); 10877 10878 PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0)); 10879 PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat)); 10880 PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0)); 10881 PetscFunctionReturn(PETSC_SUCCESS); 10882 } 10883 10884 /*@ 10885 MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI ranks' ownership ranges. 10886 10887 Collective 10888 10889 Input Parameters: 10890 + A - the matrix to create subdomains from 10891 - N - requested number of subdomains 10892 10893 Output Parameters: 10894 + n - number of subdomains resulting on this MPI process 10895 - iss - `IS` list with indices of subdomains on this MPI process 10896 10897 Level: advanced 10898 10899 Note: 10900 The number of subdomains must be smaller than the communicator size 10901 10902 .seealso: [](ch_matrices), `Mat`, `IS` 10903 @*/ 10904 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[]) 10905 { 10906 MPI_Comm comm, subcomm; 10907 PetscMPIInt size, rank, color; 10908 PetscInt rstart, rend, k; 10909 10910 PetscFunctionBegin; 10911 PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 10912 PetscCallMPI(MPI_Comm_size(comm, &size)); 10913 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 10914 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); 10915 *n = 1; 10916 k = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */ 10917 color = rank / k; 10918 PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm)); 10919 PetscCall(PetscMalloc1(1, iss)); 10920 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 10921 PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0])); 10922 PetscCallMPI(MPI_Comm_free(&subcomm)); 10923 PetscFunctionReturn(PETSC_SUCCESS); 10924 } 10925 10926 /*@ 10927 MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection. 10928 10929 If the interpolation and restriction operators are the same, uses `MatPtAP()`. 10930 If they are not the same, uses `MatMatMatMult()`. 10931 10932 Once the coarse grid problem is constructed, correct for interpolation operators 10933 that are not of full rank, which can legitimately happen in the case of non-nested 10934 geometric multigrid. 10935 10936 Input Parameters: 10937 + restrct - restriction operator 10938 . dA - fine grid matrix 10939 . interpolate - interpolation operator 10940 . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10941 - fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate 10942 10943 Output Parameter: 10944 . A - the Galerkin coarse matrix 10945 10946 Options Database Key: 10947 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used 10948 10949 Level: developer 10950 10951 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()` 10952 @*/ 10953 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A) 10954 { 10955 IS zerorows; 10956 Vec diag; 10957 10958 PetscFunctionBegin; 10959 PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10960 /* Construct the coarse grid matrix */ 10961 if (interpolate == restrct) { 10962 PetscCall(MatPtAP(dA, interpolate, reuse, fill, A)); 10963 } else { 10964 PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A)); 10965 } 10966 10967 /* If the interpolation matrix is not of full rank, A will have zero rows. 10968 This can legitimately happen in the case of non-nested geometric multigrid. 10969 In that event, we set the rows of the matrix to the rows of the identity, 10970 ignoring the equations (as the RHS will also be zero). */ 10971 10972 PetscCall(MatFindZeroRows(*A, &zerorows)); 10973 10974 if (zerorows != NULL) { /* if there are any zero rows */ 10975 PetscCall(MatCreateVecs(*A, &diag, NULL)); 10976 PetscCall(MatGetDiagonal(*A, diag)); 10977 PetscCall(VecISSet(diag, zerorows, 1.0)); 10978 PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES)); 10979 PetscCall(VecDestroy(&diag)); 10980 PetscCall(ISDestroy(&zerorows)); 10981 } 10982 PetscFunctionReturn(PETSC_SUCCESS); 10983 } 10984 10985 /*@C 10986 MatSetOperation - Allows user to set a matrix operation for any matrix type 10987 10988 Logically Collective 10989 10990 Input Parameters: 10991 + mat - the matrix 10992 . op - the name of the operation 10993 - f - the function that provides the operation 10994 10995 Level: developer 10996 10997 Example Usage: 10998 .vb 10999 extern PetscErrorCode usermult(Mat, Vec, Vec); 11000 11001 PetscCall(MatCreateXXX(comm, ..., &A)); 11002 PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFunction)usermult)); 11003 .ve 11004 11005 Notes: 11006 See the file `include/petscmat.h` for a complete list of matrix 11007 operations, which all have the form MATOP_<OPERATION>, where 11008 <OPERATION> is the name (in all capital letters) of the 11009 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11010 11011 All user-provided functions (except for `MATOP_DESTROY`) should have the same calling 11012 sequence as the usual matrix interface routines, since they 11013 are intended to be accessed via the usual matrix interface 11014 routines, e.g., 11015 .vb 11016 MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec) 11017 .ve 11018 11019 In particular each function MUST return `PETSC_SUCCESS` on success and 11020 nonzero on failure. 11021 11022 This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type. 11023 11024 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()` 11025 @*/ 11026 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void)) 11027 { 11028 PetscFunctionBegin; 11029 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11030 if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view; 11031 (((void (**)(void))mat->ops)[op]) = f; 11032 PetscFunctionReturn(PETSC_SUCCESS); 11033 } 11034 11035 /*@C 11036 MatGetOperation - Gets a matrix operation for any matrix type. 11037 11038 Not Collective 11039 11040 Input Parameters: 11041 + mat - the matrix 11042 - op - the name of the operation 11043 11044 Output Parameter: 11045 . f - the function that provides the operation 11046 11047 Level: developer 11048 11049 Example Usage: 11050 .vb 11051 PetscErrorCode (*usermult)(Mat, Vec, Vec); 11052 11053 MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult); 11054 .ve 11055 11056 Notes: 11057 See the file include/petscmat.h for a complete list of matrix 11058 operations, which all have the form MATOP_<OPERATION>, where 11059 <OPERATION> is the name (in all capital letters) of the 11060 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11061 11062 This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type. 11063 11064 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()` 11065 @*/ 11066 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void)) 11067 { 11068 PetscFunctionBegin; 11069 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11070 *f = (((void (**)(void))mat->ops)[op]); 11071 PetscFunctionReturn(PETSC_SUCCESS); 11072 } 11073 11074 /*@ 11075 MatHasOperation - Determines whether the given matrix supports the particular operation. 11076 11077 Not Collective 11078 11079 Input Parameters: 11080 + mat - the matrix 11081 - op - the operation, for example, `MATOP_GET_DIAGONAL` 11082 11083 Output Parameter: 11084 . has - either `PETSC_TRUE` or `PETSC_FALSE` 11085 11086 Level: advanced 11087 11088 Note: 11089 See `MatSetOperation()` for additional discussion on naming convention and usage of `op`. 11090 11091 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()` 11092 @*/ 11093 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has) 11094 { 11095 PetscFunctionBegin; 11096 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11097 PetscValidBoolPointer(has, 3); 11098 if (mat->ops->hasoperation) { 11099 PetscUseTypeMethod(mat, hasoperation, op, has); 11100 } else { 11101 if (((void **)mat->ops)[op]) *has = PETSC_TRUE; 11102 else { 11103 *has = PETSC_FALSE; 11104 if (op == MATOP_CREATE_SUBMATRIX) { 11105 PetscMPIInt size; 11106 11107 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 11108 if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has)); 11109 } 11110 } 11111 } 11112 PetscFunctionReturn(PETSC_SUCCESS); 11113 } 11114 11115 /*@ 11116 MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent 11117 11118 Collective 11119 11120 Input Parameter: 11121 . mat - the matrix 11122 11123 Output Parameter: 11124 . cong - either `PETSC_TRUE` or `PETSC_FALSE` 11125 11126 Level: beginner 11127 11128 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout` 11129 @*/ 11130 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong) 11131 { 11132 PetscFunctionBegin; 11133 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11134 PetscValidType(mat, 1); 11135 PetscValidBoolPointer(cong, 2); 11136 if (!mat->rmap || !mat->cmap) { 11137 *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE; 11138 PetscFunctionReturn(PETSC_SUCCESS); 11139 } 11140 if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */ 11141 PetscCall(PetscLayoutSetUp(mat->rmap)); 11142 PetscCall(PetscLayoutSetUp(mat->cmap)); 11143 PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong)); 11144 if (*cong) mat->congruentlayouts = 1; 11145 else mat->congruentlayouts = 0; 11146 } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE; 11147 PetscFunctionReturn(PETSC_SUCCESS); 11148 } 11149 11150 PetscErrorCode MatSetInf(Mat A) 11151 { 11152 PetscFunctionBegin; 11153 PetscUseTypeMethod(A, setinf); 11154 PetscFunctionReturn(PETSC_SUCCESS); 11155 } 11156 11157 /*@C 11158 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 11159 and possibly removes small values from the graph structure. 11160 11161 Collective 11162 11163 Input Parameters: 11164 + A - the matrix 11165 . sym - `PETSC_TRUE` indicates that the graph should be symmetrized 11166 . scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry 11167 - filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value 11168 11169 Output Parameter: 11170 . graph - the resulting graph 11171 11172 Level: advanced 11173 11174 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG` 11175 @*/ 11176 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph) 11177 { 11178 PetscFunctionBegin; 11179 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11180 PetscValidType(A, 1); 11181 PetscValidLogicalCollectiveBool(A, scale, 3); 11182 PetscValidPointer(graph, 5); 11183 PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph); 11184 PetscFunctionReturn(PETSC_SUCCESS); 11185 } 11186 11187 /*@ 11188 MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place, 11189 meaning the same memory is used for the matrix, and no new memory is allocated. 11190 11191 Collective 11192 11193 Input Parameters: 11194 + A - the matrix 11195 - keep - if for a given row of `A`, the diagonal coefficient is zero, indicates whether it should be left in the structure or eliminated as well 11196 11197 Level: intermediate 11198 11199 Developer Notes: 11200 The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end 11201 of the arrays in the data structure are unneeded. 11202 11203 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatChop()` 11204 @*/ 11205 PetscErrorCode MatEliminateZeros(Mat A, PetscBool keep) 11206 { 11207 PetscFunctionBegin; 11208 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11209 PetscUseTypeMethod(A, eliminatezeros, keep); 11210 PetscFunctionReturn(PETSC_SUCCESS); 11211 } 11212