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_Mults, 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_Getsymtranspose, MAT_Getsymtransreduced, MAT_GetBrowsOfAcols; 34 PetscLogEvent MAT_GetBrowsOfAocols, MAT_Getlocalmat, MAT_Getlocalmatcondensed, MAT_Seqstompi, MAT_Seqstompinum, MAT_Seqstompisym; 35 PetscLogEvent MAT_Applypapt, MAT_Applypapt_numeric, MAT_Applypapt_symbolic, MAT_GetSequentialNonzeroStructure; 36 PetscLogEvent MAT_GetMultiProcBlock; 37 PetscLogEvent MAT_CUSPARSECopyToGPU, MAT_CUSPARSECopyFromGPU, MAT_CUSPARSEGenerateTranspose, MAT_CUSPARSESolveAnalysis; 38 PetscLogEvent MAT_HIPSPARSECopyToGPU, MAT_HIPSPARSECopyFromGPU, MAT_HIPSPARSEGenerateTranspose, MAT_HIPSPARSESolveAnalysis; 39 PetscLogEvent MAT_PreallCOO, MAT_SetVCOO; 40 PetscLogEvent MAT_SetValuesBatch; 41 PetscLogEvent MAT_ViennaCLCopyToGPU; 42 PetscLogEvent MAT_CUDACopyToGPU; 43 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU; 44 PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom; 45 PetscLogEvent MAT_FactorFactS, MAT_FactorInvS; 46 PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights; 47 PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR; 48 49 const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL}; 50 51 /*@ 52 MatSetRandom - Sets all components of a matrix to random numbers. 53 54 Logically Collective 55 56 Input Parameters: 57 + x - the matrix 58 - rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or `NULL` and 59 it will create one internally. 60 61 Example: 62 .vb 63 PetscRandomCreate(PETSC_COMM_WORLD,&rctx); 64 MatSetRandom(x,rctx); 65 PetscRandomDestroy(rctx); 66 .ve 67 68 Level: intermediate 69 70 Notes: 71 For sparse matrices that have been preallocated but not been assembled it randomly selects appropriate locations, 72 73 for sparse matrices that already have locations it fills the locations with random numbers. 74 75 It generates an error if used on sparse matrices that have not been preallocated. 76 77 .seealso: [](chapter_matrices), `Mat`, `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomCreate()`, `PetscRandomDestroy()` 78 @*/ 79 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx) 80 { 81 PetscRandom randObj = NULL; 82 83 PetscFunctionBegin; 84 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 85 if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2); 86 PetscValidType(x, 1); 87 MatCheckPreallocated(x, 1); 88 89 if (!rctx) { 90 MPI_Comm comm; 91 PetscCall(PetscObjectGetComm((PetscObject)x, &comm)); 92 PetscCall(PetscRandomCreate(comm, &randObj)); 93 PetscCall(PetscRandomSetType(randObj, x->defaultrandtype)); 94 PetscCall(PetscRandomSetFromOptions(randObj)); 95 rctx = randObj; 96 } 97 PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0)); 98 PetscUseTypeMethod(x, setrandom, rctx); 99 PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0)); 100 101 PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY)); 102 PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY)); 103 PetscCall(PetscRandomDestroy(&randObj)); 104 PetscFunctionReturn(PETSC_SUCCESS); 105 } 106 107 /*@ 108 MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in 109 110 Logically Collective 111 112 Input Parameter: 113 . mat - the factored matrix 114 115 Output Parameters: 116 + pivot - the pivot value computed 117 - row - the row that the zero pivot occurred. This row value must be interpreted carefully due to row reorderings and which processes 118 the share the matrix 119 120 Level: advanced 121 122 Notes: 123 This routine does not work for factorizations done with external packages. 124 125 This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT` 126 127 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 128 129 .seealso: [](chapter_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, 130 `MAT_FACTOR_NUMERIC_ZEROPIVOT` 131 @*/ 132 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row) 133 { 134 PetscFunctionBegin; 135 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 136 PetscValidRealPointer(pivot, 2); 137 PetscValidIntPointer(row, 3); 138 *pivot = mat->factorerror_zeropivot_value; 139 *row = mat->factorerror_zeropivot_row; 140 PetscFunctionReturn(PETSC_SUCCESS); 141 } 142 143 /*@ 144 MatFactorGetError - gets the error code from a factorization 145 146 Logically Collective 147 148 Input Parameter: 149 . mat - the factored matrix 150 151 Output Parameter: 152 . err - the error code 153 154 Level: advanced 155 156 Note: 157 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 158 159 .seealso: [](chapter_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, 160 `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, `MatFactorError` 161 @*/ 162 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err) 163 { 164 PetscFunctionBegin; 165 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 166 PetscValidPointer(err, 2); 167 *err = mat->factorerrortype; 168 PetscFunctionReturn(PETSC_SUCCESS); 169 } 170 171 /*@ 172 MatFactorClearError - clears the error code in a factorization 173 174 Logically Collective 175 176 Input Parameter: 177 . mat - the factored matrix 178 179 Level: developer 180 181 Note: 182 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 183 184 .seealso: [](chapter_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`, 185 `MatGetErrorCode()`, `MatFactorError` 186 @*/ 187 PetscErrorCode MatFactorClearError(Mat mat) 188 { 189 PetscFunctionBegin; 190 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 191 mat->factorerrortype = MAT_FACTOR_NOERROR; 192 mat->factorerror_zeropivot_value = 0.0; 193 mat->factorerror_zeropivot_row = 0; 194 PetscFunctionReturn(PETSC_SUCCESS); 195 } 196 197 PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero) 198 { 199 Vec r, l; 200 const PetscScalar *al; 201 PetscInt i, nz, gnz, N, n; 202 203 PetscFunctionBegin; 204 PetscCall(MatCreateVecs(mat, &r, &l)); 205 if (!cols) { /* nonzero rows */ 206 PetscCall(MatGetSize(mat, &N, NULL)); 207 PetscCall(MatGetLocalSize(mat, &n, NULL)); 208 PetscCall(VecSet(l, 0.0)); 209 PetscCall(VecSetRandom(r, NULL)); 210 PetscCall(MatMult(mat, r, l)); 211 PetscCall(VecGetArrayRead(l, &al)); 212 } else { /* nonzero columns */ 213 PetscCall(MatGetSize(mat, NULL, &N)); 214 PetscCall(MatGetLocalSize(mat, NULL, &n)); 215 PetscCall(VecSet(r, 0.0)); 216 PetscCall(VecSetRandom(l, NULL)); 217 PetscCall(MatMultTranspose(mat, l, r)); 218 PetscCall(VecGetArrayRead(r, &al)); 219 } 220 if (tol <= 0.0) { 221 for (i = 0, nz = 0; i < n; i++) 222 if (al[i] != 0.0) nz++; 223 } else { 224 for (i = 0, nz = 0; i < n; i++) 225 if (PetscAbsScalar(al[i]) > tol) nz++; 226 } 227 PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 228 if (gnz != N) { 229 PetscInt *nzr; 230 PetscCall(PetscMalloc1(nz, &nzr)); 231 if (nz) { 232 if (tol < 0) { 233 for (i = 0, nz = 0; i < n; i++) 234 if (al[i] != 0.0) nzr[nz++] = i; 235 } else { 236 for (i = 0, nz = 0; i < n; i++) 237 if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i; 238 } 239 } 240 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero)); 241 } else *nonzero = NULL; 242 if (!cols) { /* nonzero rows */ 243 PetscCall(VecRestoreArrayRead(l, &al)); 244 } else { 245 PetscCall(VecRestoreArrayRead(r, &al)); 246 } 247 PetscCall(VecDestroy(&l)); 248 PetscCall(VecDestroy(&r)); 249 PetscFunctionReturn(PETSC_SUCCESS); 250 } 251 252 /*@ 253 MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix 254 255 Input Parameter: 256 . A - the matrix 257 258 Output Parameter: 259 . keptrows - the rows that are not completely zero 260 261 Level: intermediate 262 263 Note: 264 `keptrows` is set to `NULL` if all rows are nonzero. 265 266 .seealso: [](chapter_matrices), `Mat`, `MatFindZeroRows()` 267 @*/ 268 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows) 269 { 270 PetscFunctionBegin; 271 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 272 PetscValidType(mat, 1); 273 PetscValidPointer(keptrows, 2); 274 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 275 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 276 if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows); 277 else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows)); 278 PetscFunctionReturn(PETSC_SUCCESS); 279 } 280 281 /*@ 282 MatFindZeroRows - Locate all rows that are completely zero in the matrix 283 284 Input Parameter: 285 . A - the matrix 286 287 Output Parameter: 288 . zerorows - the rows that are completely zero 289 290 Level: intermediate 291 292 Note: 293 `zerorows` is set to `NULL` if no rows are zero. 294 295 .seealso: [](chapter_matrices), `Mat`, `MatFindNonzeroRows()` 296 @*/ 297 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows) 298 { 299 IS keptrows; 300 PetscInt m, n; 301 302 PetscFunctionBegin; 303 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 304 PetscValidType(mat, 1); 305 PetscValidPointer(zerorows, 2); 306 PetscCall(MatFindNonzeroRows(mat, &keptrows)); 307 /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows. 308 In keeping with this convention, we set zerorows to NULL if there are no zero 309 rows. */ 310 if (keptrows == NULL) { 311 *zerorows = NULL; 312 } else { 313 PetscCall(MatGetOwnershipRange(mat, &m, &n)); 314 PetscCall(ISComplement(keptrows, m, n, zerorows)); 315 PetscCall(ISDestroy(&keptrows)); 316 } 317 PetscFunctionReturn(PETSC_SUCCESS); 318 } 319 320 /*@ 321 MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling 322 323 Not Collective 324 325 Input Parameter: 326 . A - the matrix 327 328 Output Parameter: 329 . a - the diagonal part (which is a SEQUENTIAL matrix) 330 331 Level: advanced 332 333 Notes: 334 See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix. 335 336 Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation. 337 338 .seealso: [](chapter_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ` 339 @*/ 340 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a) 341 { 342 PetscFunctionBegin; 343 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 344 PetscValidType(A, 1); 345 PetscValidPointer(a, 2); 346 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 347 if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a); 348 else { 349 PetscMPIInt size; 350 351 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 352 PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name); 353 *a = A; 354 } 355 PetscFunctionReturn(PETSC_SUCCESS); 356 } 357 358 /*@ 359 MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries. 360 361 Collective 362 363 Input Parameter: 364 . mat - the matrix 365 366 Output Parameter: 367 . trace - the sum of the diagonal entries 368 369 Level: advanced 370 371 .seealso: [](chapter_matrices), `Mat` 372 @*/ 373 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace) 374 { 375 Vec diag; 376 377 PetscFunctionBegin; 378 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 379 PetscValidScalarPointer(trace, 2); 380 PetscCall(MatCreateVecs(mat, &diag, NULL)); 381 PetscCall(MatGetDiagonal(mat, diag)); 382 PetscCall(VecSum(diag, trace)); 383 PetscCall(VecDestroy(&diag)); 384 PetscFunctionReturn(PETSC_SUCCESS); 385 } 386 387 /*@ 388 MatRealPart - Zeros out the imaginary part of the matrix 389 390 Logically Collective 391 392 Input Parameter: 393 . mat - the matrix 394 395 Level: advanced 396 397 .seealso: [](chapter_matrices), `Mat`, `MatImaginaryPart()` 398 @*/ 399 PetscErrorCode MatRealPart(Mat mat) 400 { 401 PetscFunctionBegin; 402 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 403 PetscValidType(mat, 1); 404 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 405 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 406 MatCheckPreallocated(mat, 1); 407 PetscUseTypeMethod(mat, realpart); 408 PetscFunctionReturn(PETSC_SUCCESS); 409 } 410 411 /*@C 412 MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix 413 414 Collective 415 416 Input Parameter: 417 . mat - the matrix 418 419 Output Parameters: 420 + nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each block) 421 - ghosts - the global indices of the ghost points 422 423 Level: advanced 424 425 Note: 426 `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()` 427 428 .seealso: [](chapter_matrices), `Mat`, `VecCreateGhost()` 429 @*/ 430 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[]) 431 { 432 PetscFunctionBegin; 433 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 434 PetscValidType(mat, 1); 435 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 436 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 437 if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts); 438 else { 439 if (nghosts) *nghosts = 0; 440 if (ghosts) *ghosts = NULL; 441 } 442 PetscFunctionReturn(PETSC_SUCCESS); 443 } 444 445 /*@ 446 MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part 447 448 Logically Collective 449 450 Input Parameter: 451 . mat - the matrix 452 453 Level: advanced 454 455 .seealso: [](chapter_matrices), `Mat`, `MatRealPart()` 456 @*/ 457 PetscErrorCode MatImaginaryPart(Mat mat) 458 { 459 PetscFunctionBegin; 460 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 461 PetscValidType(mat, 1); 462 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 463 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 464 MatCheckPreallocated(mat, 1); 465 PetscUseTypeMethod(mat, imaginarypart); 466 PetscFunctionReturn(PETSC_SUCCESS); 467 } 468 469 /*@ 470 MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices) 471 472 Not Collective 473 474 Input Parameter: 475 . mat - the matrix 476 477 Output Parameters: 478 + missing - is any diagonal missing 479 - dd - first diagonal entry that is missing (optional) on this process 480 481 Level: advanced 482 483 .seealso: [](chapter_matrices), `Mat` 484 @*/ 485 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd) 486 { 487 PetscFunctionBegin; 488 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 489 PetscValidType(mat, 1); 490 PetscValidBoolPointer(missing, 2); 491 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name); 492 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 493 PetscUseTypeMethod(mat, missingdiagonal, missing, dd); 494 PetscFunctionReturn(PETSC_SUCCESS); 495 } 496 497 /*@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 Note: 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: [](chapter_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: [](chapter_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: [](chapter_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: [](chapter_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: [](chapter_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: [](chapter_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: [](chapter_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: [](chapter_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: [](chapter_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 Note: 861 The user should pass in a string `prefix` of 862 sufficient length to hold the prefix. 863 864 .seealso: [](chapter_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: [](chapter_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 PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A)); 900 PetscFunctionReturn(PETSC_SUCCESS); 901 } 902 903 /*@ 904 MatSetUp - Sets up the internal matrix data structures for later use. 905 906 Collective 907 908 Input Parameter: 909 . A - the matrix 910 911 Level: intermediate 912 913 Notes: 914 If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of 915 setting values in the matrix. 916 917 If a suitable preallocation routine is used, this function does not need to be called. 918 919 This routine is called internally by other matrix functions when needed so rarely needs to be called by users 920 921 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()` 922 @*/ 923 PetscErrorCode MatSetUp(Mat A) 924 { 925 PetscFunctionBegin; 926 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 927 if (!((PetscObject)A)->type_name) { 928 PetscMPIInt size; 929 930 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 931 PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ)); 932 } 933 if (!A->preallocated) PetscTryTypeMethod(A, setup); 934 PetscCall(PetscLayoutSetUp(A->rmap)); 935 PetscCall(PetscLayoutSetUp(A->cmap)); 936 A->preallocated = PETSC_TRUE; 937 PetscFunctionReturn(PETSC_SUCCESS); 938 } 939 940 #if defined(PETSC_HAVE_SAWS) 941 #include <petscviewersaws.h> 942 #endif 943 944 /*@C 945 MatViewFromOptions - View properties of the matrix based on options set in the options database 946 947 Collective 948 949 Input Parameters: 950 + A - the matrix 951 . obj - optional additional object that provides the options prefix to use 952 - name - command line option 953 954 Options Database Key: 955 . -mat_view [viewertype]:... - the viewer and its options 956 957 Level: intermediate 958 959 Notes: 960 .vb 961 If no value is provided ascii:stdout is used 962 ascii[:[filename][:[format][:append]]] defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab, 963 for example ascii::ascii_info prints just the information about the object not all details 964 unless :append is given filename opens in write mode, overwriting what was already there 965 binary[:[filename][:[format][:append]]] defaults to the file binaryoutput 966 draw[:drawtype[:filename]] for example, draw:tikz, draw:tikz:figure.tex or draw:x 967 socket[:port] defaults to the standard output port 968 saws[:communicatorname] publishes object to the Scientific Application Webserver (SAWs) 969 .ve 970 971 .seealso: [](chapter_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()` 972 @*/ 973 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[]) 974 { 975 PetscFunctionBegin; 976 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 977 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 978 PetscFunctionReturn(PETSC_SUCCESS); 979 } 980 981 /*@C 982 MatView - display information about a matrix in a variety ways 983 984 Collective 985 986 Input Parameters: 987 + mat - the matrix 988 - viewer - visualization context 989 990 Options Database Keys: 991 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 992 . -mat_view ::ascii_info_detail - Prints more detailed info 993 . -mat_view - Prints matrix in ASCII format 994 . -mat_view ::ascii_matlab - Prints matrix in Matlab format 995 . -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 996 . -display <name> - Sets display name (default is host) 997 . -draw_pause <sec> - Sets number of seconds to pause after display 998 . -mat_view socket - Sends matrix to socket, can be accessed from Matlab (see Users-Manual: ch_matlab for details) 999 . -viewer_socket_machine <machine> - 1000 . -viewer_socket_port <port> - 1001 . -mat_view binary - save matrix to file in binary format 1002 - -viewer_binary_filename <name> - 1003 1004 Level: beginner 1005 1006 Notes: 1007 The available visualization contexts include 1008 + `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices 1009 . `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD` 1010 . `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm 1011 - `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure 1012 1013 The user can open alternative visualization contexts with 1014 + `PetscViewerASCIIOpen()` - Outputs matrix to a specified file 1015 . `PetscViewerBinaryOpen()` - Outputs matrix in binary to a 1016 specified file; corresponding input uses MatLoad() 1017 . `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to 1018 an X window display 1019 - `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer. 1020 Currently only the sequential dense and AIJ 1021 matrix types support the Socket viewer. 1022 1023 The user can call `PetscViewerPushFormat()` to specify the output 1024 format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`, 1025 `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`). Available formats include 1026 + `PETSC_VIEWER_DEFAULT` - default, prints matrix contents 1027 . `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in Matlab format 1028 . `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros 1029 . `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse 1030 format common among all matrix types 1031 . `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific 1032 format (which is in many cases the same as the default) 1033 . `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix 1034 size and structure (not the matrix entries) 1035 - `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about 1036 the matrix structure 1037 1038 The ASCII viewers are only recommended for small matrices on at most a moderate number of processes, 1039 the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format. 1040 1041 In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer). 1042 1043 See the manual page for `MatLoad()` for the exact format of the binary file when the binary 1044 viewer is used. 1045 1046 See share/petsc/matlab/PetscBinaryRead.m for a Matlab code that can read in the binary file when the binary 1047 viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python. 1048 1049 One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure, 1050 and then use the following mouse functions. 1051 .vb 1052 left mouse: zoom in 1053 middle mouse: zoom out 1054 right mouse: continue with the simulation 1055 .ve 1056 1057 .seealso: [](chapter_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`, 1058 `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()` 1059 @*/ 1060 PetscErrorCode MatView(Mat mat, PetscViewer viewer) 1061 { 1062 PetscInt rows, cols, rbs, cbs; 1063 PetscBool isascii, isstring, issaws; 1064 PetscViewerFormat format; 1065 PetscMPIInt size; 1066 1067 PetscFunctionBegin; 1068 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1069 PetscValidType(mat, 1); 1070 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer)); 1071 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1072 PetscCheckSameComm(mat, 1, viewer, 2); 1073 1074 PetscCall(PetscViewerGetFormat(viewer, &format)); 1075 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 1076 if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS); 1077 1078 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 1079 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 1080 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws)); 1081 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"); 1082 1083 PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0)); 1084 if (isascii) { 1085 if (!mat->preallocated) { 1086 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n")); 1087 PetscFunctionReturn(PETSC_SUCCESS); 1088 } 1089 if (!mat->assembled) { 1090 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n")); 1091 PetscFunctionReturn(PETSC_SUCCESS); 1092 } 1093 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer)); 1094 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1095 MatNullSpace nullsp, transnullsp; 1096 1097 PetscCall(PetscViewerASCIIPushTab(viewer)); 1098 PetscCall(MatGetSize(mat, &rows, &cols)); 1099 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1100 if (rbs != 1 || cbs != 1) { 1101 if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs)); 1102 else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs)); 1103 } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols)); 1104 if (mat->factortype) { 1105 MatSolverType solver; 1106 PetscCall(MatFactorGetSolverType(mat, &solver)); 1107 PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver)); 1108 } 1109 if (mat->ops->getinfo) { 1110 MatInfo info; 1111 PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info)); 1112 PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated)); 1113 if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs)); 1114 } 1115 PetscCall(MatGetNullSpace(mat, &nullsp)); 1116 PetscCall(MatGetTransposeNullSpace(mat, &transnullsp)); 1117 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached null space\n")); 1118 if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached transposed null space\n")); 1119 PetscCall(MatGetNearNullSpace(mat, &nullsp)); 1120 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached near null space\n")); 1121 PetscCall(PetscViewerASCIIPushTab(viewer)); 1122 PetscCall(MatProductView(mat, viewer)); 1123 PetscCall(PetscViewerASCIIPopTab(viewer)); 1124 } 1125 } else if (issaws) { 1126 #if defined(PETSC_HAVE_SAWS) 1127 PetscMPIInt rank; 1128 1129 PetscCall(PetscObjectName((PetscObject)mat)); 1130 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 1131 if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer)); 1132 #endif 1133 } else if (isstring) { 1134 const char *type; 1135 PetscCall(MatGetType(mat, &type)); 1136 PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type)); 1137 PetscTryTypeMethod(mat, view, viewer); 1138 } 1139 if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) { 1140 PetscCall(PetscViewerASCIIPushTab(viewer)); 1141 PetscUseTypeMethod(mat, viewnative, viewer); 1142 PetscCall(PetscViewerASCIIPopTab(viewer)); 1143 } else if (mat->ops->view) { 1144 PetscCall(PetscViewerASCIIPushTab(viewer)); 1145 PetscUseTypeMethod(mat, view, viewer); 1146 PetscCall(PetscViewerASCIIPopTab(viewer)); 1147 } 1148 if (isascii) { 1149 PetscCall(PetscViewerGetFormat(viewer, &format)); 1150 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer)); 1151 } 1152 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1153 PetscFunctionReturn(PETSC_SUCCESS); 1154 } 1155 1156 #if defined(PETSC_USE_DEBUG) 1157 #include <../src/sys/totalview/tv_data_display.h> 1158 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat) 1159 { 1160 TV_add_row("Local rows", "int", &mat->rmap->n); 1161 TV_add_row("Local columns", "int", &mat->cmap->n); 1162 TV_add_row("Global rows", "int", &mat->rmap->N); 1163 TV_add_row("Global columns", "int", &mat->cmap->N); 1164 TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name); 1165 return TV_format_OK; 1166 } 1167 #endif 1168 1169 /*@C 1170 MatLoad - Loads a matrix that has been stored in binary/HDF5 format 1171 with `MatView()`. The matrix format is determined from the options database. 1172 Generates a parallel MPI matrix if the communicator has more than one 1173 processor. The default matrix type is `MATAIJ`. 1174 1175 Collective 1176 1177 Input Parameters: 1178 + mat - the newly loaded matrix, this needs to have been created with `MatCreate()` 1179 or some related function before a call to `MatLoad()` 1180 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer 1181 1182 Options Database Keys: 1183 Used with block matrix formats (`MATSEQBAIJ`, ...) to specify 1184 block size 1185 . -matload_block_size <bs> - set block size 1186 1187 Level: beginner 1188 1189 Notes: 1190 If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the 1191 `Mat` before calling this routine if you wish to set it from the options database. 1192 1193 `MatLoad()` automatically loads into the options database any options 1194 given in the file filename.info where filename is the name of the file 1195 that was passed to the `PetscViewerBinaryOpen()`. The options in the info 1196 file will be ignored if you use the -viewer_binary_skip_info option. 1197 1198 If the type or size of mat is not set before a call to `MatLoad()`, PETSc 1199 sets the default matrix type AIJ and sets the local and global sizes. 1200 If type and/or size is already set, then the same are used. 1201 1202 In parallel, each processor can load a subset of rows (or the 1203 entire matrix). This routine is especially useful when a large 1204 matrix is stored on disk and only part of it is desired on each 1205 processor. For example, a parallel solver may access only some of 1206 the rows from each processor. The algorithm used here reads 1207 relatively small blocks of data rather than reading the entire 1208 matrix and then subsetting it. 1209 1210 Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`. 1211 Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`, 1212 or the sequence like 1213 .vb 1214 `PetscViewer` v; 1215 `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v); 1216 `PetscViewerSetType`(v,`PETSCVIEWERBINARY`); 1217 `PetscViewerSetFromOptions`(v); 1218 `PetscViewerFileSetMode`(v,`FILE_MODE_READ`); 1219 `PetscViewerFileSetName`(v,"datafile"); 1220 .ve 1221 The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option 1222 $ -viewer_type {binary,hdf5} 1223 1224 See the example src/ksp/ksp/tutorials/ex27.c with the first approach, 1225 and src/mat/tutorials/ex10.c with the second approach. 1226 1227 In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks 1228 is read onto rank 0 and then shipped to its destination rank, one after another. 1229 Multiple objects, both matrices and vectors, can be stored within the same file. 1230 Their PetscObject name is ignored; they are loaded in the order of their storage. 1231 1232 Most users should not need to know the details of the binary storage 1233 format, since `MatLoad()` and `MatView()` completely hide these details. 1234 But for anyone who's interested, the standard binary matrix storage 1235 format is 1236 1237 .vb 1238 PetscInt MAT_FILE_CLASSID 1239 PetscInt number of rows 1240 PetscInt number of columns 1241 PetscInt total number of nonzeros 1242 PetscInt *number nonzeros in each row 1243 PetscInt *column indices of all nonzeros (starting index is zero) 1244 PetscScalar *values of all nonzeros 1245 .ve 1246 1247 PETSc automatically does the byte swapping for 1248 machines that store the bytes reversed. Thus if you write your own binary 1249 read/write routines you have to swap the bytes; see `PetscBinaryRead()` 1250 and `PetscBinaryWrite()` to see how this may be done. 1251 1252 In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used. 1253 Each processor's chunk is loaded independently by its owning rank. 1254 Multiple objects, both matrices and vectors, can be stored within the same file. 1255 They are looked up by their PetscObject name. 1256 1257 As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use 1258 by default the same structure and naming of the AIJ arrays and column count 1259 within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g. 1260 $ save example.mat A b -v7.3 1261 can be directly read by this routine (see Reference 1 for details). 1262 1263 Depending on your MATLAB version, this format might be a default, 1264 otherwise you can set it as default in Preferences. 1265 1266 Unless -nocompression flag is used to save the file in MATLAB, 1267 PETSc must be configured with ZLIB package. 1268 1269 See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c 1270 1271 This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5` 1272 1273 Corresponding `MatView()` is not yet implemented. 1274 1275 The loaded matrix is actually a transpose of the original one in MATLAB, 1276 unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above). 1277 With this format, matrix is automatically transposed by PETSc, 1278 unless the matrix is marked as SPD or symmetric 1279 (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`). 1280 1281 References: 1282 . * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version 1283 1284 .seealso: [](chapter_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()` 1285 @*/ 1286 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer) 1287 { 1288 PetscBool flg; 1289 1290 PetscFunctionBegin; 1291 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1292 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1293 1294 if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ)); 1295 1296 flg = PETSC_FALSE; 1297 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL)); 1298 if (flg) { 1299 PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE)); 1300 PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE)); 1301 } 1302 flg = PETSC_FALSE; 1303 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL)); 1304 if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE)); 1305 1306 PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0)); 1307 PetscUseTypeMethod(mat, load, viewer); 1308 PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0)); 1309 PetscFunctionReturn(PETSC_SUCCESS); 1310 } 1311 1312 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant) 1313 { 1314 Mat_Redundant *redund = *redundant; 1315 1316 PetscFunctionBegin; 1317 if (redund) { 1318 if (redund->matseq) { /* via MatCreateSubMatrices() */ 1319 PetscCall(ISDestroy(&redund->isrow)); 1320 PetscCall(ISDestroy(&redund->iscol)); 1321 PetscCall(MatDestroySubMatrices(1, &redund->matseq)); 1322 } else { 1323 PetscCall(PetscFree2(redund->send_rank, redund->recv_rank)); 1324 PetscCall(PetscFree(redund->sbuf_j)); 1325 PetscCall(PetscFree(redund->sbuf_a)); 1326 for (PetscInt i = 0; i < redund->nrecvs; i++) { 1327 PetscCall(PetscFree(redund->rbuf_j[i])); 1328 PetscCall(PetscFree(redund->rbuf_a[i])); 1329 } 1330 PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a)); 1331 } 1332 1333 if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm)); 1334 PetscCall(PetscFree(redund)); 1335 } 1336 PetscFunctionReturn(PETSC_SUCCESS); 1337 } 1338 1339 /*@C 1340 MatDestroy - Frees space taken by a matrix. 1341 1342 Collective 1343 1344 Input Parameter: 1345 . A - the matrix 1346 1347 Level: beginner 1348 1349 Developer Note: 1350 Some special arrays of matrices are not destroyed in this routine but instead by the routines called by 1351 `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines. 1352 `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes 1353 if changes are needed here. 1354 1355 .seealso: [](chapter_matrices), `Mat`, `MatCreate()` 1356 @*/ 1357 PetscErrorCode MatDestroy(Mat *A) 1358 { 1359 PetscFunctionBegin; 1360 if (!*A) PetscFunctionReturn(PETSC_SUCCESS); 1361 PetscValidHeaderSpecific(*A, MAT_CLASSID, 1); 1362 if (--((PetscObject)(*A))->refct > 0) { 1363 *A = NULL; 1364 PetscFunctionReturn(PETSC_SUCCESS); 1365 } 1366 1367 /* if memory was published with SAWs then destroy it */ 1368 PetscCall(PetscObjectSAWsViewOff((PetscObject)*A)); 1369 PetscTryTypeMethod((*A), destroy); 1370 1371 PetscCall(PetscFree((*A)->factorprefix)); 1372 PetscCall(PetscFree((*A)->defaultvectype)); 1373 PetscCall(PetscFree((*A)->defaultrandtype)); 1374 PetscCall(PetscFree((*A)->bsizes)); 1375 PetscCall(PetscFree((*A)->solvertype)); 1376 for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i])); 1377 if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL; 1378 PetscCall(MatDestroy_Redundant(&(*A)->redundant)); 1379 PetscCall(MatProductClear(*A)); 1380 PetscCall(MatNullSpaceDestroy(&(*A)->nullsp)); 1381 PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp)); 1382 PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp)); 1383 PetscCall(MatDestroy(&(*A)->schur)); 1384 PetscCall(PetscLayoutDestroy(&(*A)->rmap)); 1385 PetscCall(PetscLayoutDestroy(&(*A)->cmap)); 1386 PetscCall(PetscHeaderDestroy(A)); 1387 PetscFunctionReturn(PETSC_SUCCESS); 1388 } 1389 1390 /*@C 1391 MatSetValues - Inserts or adds a block of values into a matrix. 1392 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1393 MUST be called after all calls to `MatSetValues()` have been completed. 1394 1395 Not Collective 1396 1397 Input Parameters: 1398 + mat - the matrix 1399 . v - a logically two-dimensional array of values 1400 . m - the number of rows 1401 . idxm - the global indices of the rows 1402 . n - the number of columns 1403 . idxn - the global indices of the columns 1404 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1405 1406 Level: beginner 1407 1408 Notes: 1409 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1410 1411 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1412 options cannot be mixed without intervening calls to the assembly 1413 routines. 1414 1415 `MatSetValues()` uses 0-based row and column numbers in Fortran 1416 as well as in C. 1417 1418 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1419 simply ignored. This allows easily inserting element stiffness matrices 1420 with homogeneous Dirchlet boundary conditions that you don't want represented 1421 in the matrix. 1422 1423 Efficiency Alert: 1424 The routine `MatSetValuesBlocked()` may offer much better efficiency 1425 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1426 1427 Developer Note: 1428 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1429 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1430 1431 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1432 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1433 @*/ 1434 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1435 { 1436 PetscFunctionBeginHot; 1437 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1438 PetscValidType(mat, 1); 1439 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1440 PetscValidIntPointer(idxm, 3); 1441 PetscValidIntPointer(idxn, 5); 1442 MatCheckPreallocated(mat, 1); 1443 1444 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1445 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1446 1447 if (PetscDefined(USE_DEBUG)) { 1448 PetscInt i, j; 1449 1450 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1451 for (i = 0; i < m; i++) { 1452 for (j = 0; j < n; j++) { 1453 if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j])) 1454 #if defined(PETSC_USE_COMPLEX) 1455 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]); 1456 #else 1457 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]); 1458 #endif 1459 } 1460 } 1461 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); 1462 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); 1463 } 1464 1465 if (mat->assembled) { 1466 mat->was_assembled = PETSC_TRUE; 1467 mat->assembled = PETSC_FALSE; 1468 } 1469 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1470 PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv); 1471 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1472 PetscFunctionReturn(PETSC_SUCCESS); 1473 } 1474 1475 /*@C 1476 MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns 1477 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1478 MUST be called after all calls to `MatSetValues()` have been completed. 1479 1480 Not Collective 1481 1482 Input Parameters: 1483 + mat - the matrix 1484 . v - a logically two-dimensional array of values 1485 . ism - the rows to provide 1486 . isn - the columns to provide 1487 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1488 1489 Level: beginner 1490 1491 Notes: 1492 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1493 1494 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1495 options cannot be mixed without intervening calls to the assembly 1496 routines. 1497 1498 `MatSetValues()` uses 0-based row and column numbers in Fortran 1499 as well as in C. 1500 1501 Negative indices may be passed in `ism` and `isn`, these rows and columns are 1502 simply ignored. This allows easily inserting element stiffness matrices 1503 with homogeneous Dirchlet boundary conditions that you don't want represented 1504 in the matrix. 1505 1506 Efficiency Alert: 1507 The routine `MatSetValuesBlocked()` may offer much better efficiency 1508 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1509 1510 This is currently not optimized for any particular `ISType` 1511 1512 Developer Notes: 1513 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1514 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1515 1516 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1517 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()` 1518 @*/ 1519 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv) 1520 { 1521 PetscInt m, n; 1522 const PetscInt *rows, *cols; 1523 1524 PetscFunctionBeginHot; 1525 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1526 PetscCall(ISGetIndices(ism, &rows)); 1527 PetscCall(ISGetIndices(isn, &cols)); 1528 PetscCall(ISGetLocalSize(ism, &m)); 1529 PetscCall(ISGetLocalSize(isn, &n)); 1530 PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv)); 1531 PetscCall(ISRestoreIndices(ism, &rows)); 1532 PetscCall(ISRestoreIndices(isn, &cols)); 1533 PetscFunctionReturn(PETSC_SUCCESS); 1534 } 1535 1536 /*@ 1537 MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1538 values into a matrix 1539 1540 Not Collective 1541 1542 Input Parameters: 1543 + mat - the matrix 1544 . row - the (block) row to set 1545 - v - a logically two-dimensional array of values 1546 1547 Level: intermediate 1548 1549 Notes: 1550 The values, `v`, are column-oriented (for the block version) and sorted 1551 1552 All the nonzeros in the row must be provided 1553 1554 The matrix must have previously had its column indices set, likely by having been assembled. 1555 1556 The row must belong to this process 1557 1558 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1559 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()` 1560 @*/ 1561 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[]) 1562 { 1563 PetscInt globalrow; 1564 1565 PetscFunctionBegin; 1566 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1567 PetscValidType(mat, 1); 1568 PetscValidScalarPointer(v, 3); 1569 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow)); 1570 PetscCall(MatSetValuesRow(mat, globalrow, v)); 1571 PetscFunctionReturn(PETSC_SUCCESS); 1572 } 1573 1574 /*@ 1575 MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1576 values into a matrix 1577 1578 Not Collective 1579 1580 Input Parameters: 1581 + mat - the matrix 1582 . row - the (block) row to set 1583 - 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 1584 1585 Level: advanced 1586 1587 Notes: 1588 The values, `v`, are column-oriented for the block version. 1589 1590 All the nonzeros in the row must be provided 1591 1592 THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used. 1593 1594 The row must belong to this process 1595 1596 .seealso: [](chapter_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1597 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()` 1598 @*/ 1599 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[]) 1600 { 1601 PetscFunctionBeginHot; 1602 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1603 PetscValidType(mat, 1); 1604 MatCheckPreallocated(mat, 1); 1605 PetscValidScalarPointer(v, 3); 1606 PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values"); 1607 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1608 mat->insertmode = INSERT_VALUES; 1609 1610 if (mat->assembled) { 1611 mat->was_assembled = PETSC_TRUE; 1612 mat->assembled = PETSC_FALSE; 1613 } 1614 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1615 PetscUseTypeMethod(mat, setvaluesrow, row, v); 1616 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1617 PetscFunctionReturn(PETSC_SUCCESS); 1618 } 1619 1620 /*@ 1621 MatSetValuesStencil - Inserts or adds a block of values into a matrix. 1622 Using structured grid indexing 1623 1624 Not Collective 1625 1626 Input Parameters: 1627 + mat - the matrix 1628 . m - number of rows being entered 1629 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered 1630 . n - number of columns being entered 1631 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered 1632 . v - a logically two-dimensional array of values 1633 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values 1634 1635 Level: beginner 1636 1637 Notes: 1638 By default the values, `v`, are row-oriented. See `MatSetOption()` for other options. 1639 1640 Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1641 options cannot be mixed without intervening calls to the assembly 1642 routines. 1643 1644 The grid coordinates are across the entire grid, not just the local portion 1645 1646 `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran 1647 as well as in C. 1648 1649 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1650 1651 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1652 or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1653 1654 The columns and rows in the stencil passed in MUST be contained within the 1655 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1656 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1657 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1658 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1659 1660 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 1661 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 1662 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 1663 `DM_BOUNDARY_PERIODIC` boundary type. 1664 1665 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 1666 a single value per point) you can skip filling those indices. 1667 1668 Inspired by the structured grid interface to the HYPRE package 1669 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1670 1671 Efficiency Alert: 1672 The routine `MatSetValuesBlockedStencil()` may offer much better efficiency 1673 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1674 1675 Fortran Note: 1676 `idxm` and `idxn` should be declared as 1677 $ MatStencil idxm(4,m),idxn(4,n) 1678 and the values inserted using 1679 .vb 1680 idxm(MatStencil_i,1) = i 1681 idxm(MatStencil_j,1) = j 1682 idxm(MatStencil_k,1) = k 1683 idxm(MatStencil_c,1) = c 1684 etc 1685 .ve 1686 1687 .seealso: [](chapter_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1688 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil` 1689 @*/ 1690 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1691 { 1692 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1693 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1694 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1695 1696 PetscFunctionBegin; 1697 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1698 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1699 PetscValidType(mat, 1); 1700 PetscValidPointer(idxm, 3); 1701 PetscValidPointer(idxn, 5); 1702 1703 if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 1704 jdxm = buf; 1705 jdxn = buf + m; 1706 } else { 1707 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1708 jdxm = bufm; 1709 jdxn = bufn; 1710 } 1711 for (i = 0; i < m; i++) { 1712 for (j = 0; j < 3 - sdim; j++) dxm++; 1713 tmp = *dxm++ - starts[0]; 1714 for (j = 0; j < dim - 1; j++) { 1715 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1716 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1717 } 1718 if (mat->stencil.noc) dxm++; 1719 jdxm[i] = tmp; 1720 } 1721 for (i = 0; i < n; i++) { 1722 for (j = 0; j < 3 - sdim; j++) dxn++; 1723 tmp = *dxn++ - starts[0]; 1724 for (j = 0; j < dim - 1; j++) { 1725 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1726 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1727 } 1728 if (mat->stencil.noc) dxn++; 1729 jdxn[i] = tmp; 1730 } 1731 PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv)); 1732 PetscCall(PetscFree2(bufm, bufn)); 1733 PetscFunctionReturn(PETSC_SUCCESS); 1734 } 1735 1736 /*@ 1737 MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix. 1738 Using structured grid indexing 1739 1740 Not Collective 1741 1742 Input Parameters: 1743 + mat - the matrix 1744 . m - number of rows being entered 1745 . idxm - grid coordinates for matrix rows being entered 1746 . n - number of columns being entered 1747 . idxn - grid coordinates for matrix columns being entered 1748 . v - a logically two-dimensional array of values 1749 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values 1750 1751 Level: beginner 1752 1753 Notes: 1754 By default the values, `v`, are row-oriented and unsorted. 1755 See `MatSetOption()` for other options. 1756 1757 Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1758 options cannot be mixed without intervening calls to the assembly 1759 routines. 1760 1761 The grid coordinates are across the entire grid, not just the local portion 1762 1763 `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran 1764 as well as in C. 1765 1766 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1767 1768 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1769 or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1770 1771 The columns and rows in the stencil passed in MUST be contained within the 1772 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1773 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1774 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1775 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1776 1777 Negative indices may be passed in idxm and idxn, these rows and columns are 1778 simply ignored. This allows easily inserting element stiffness matrices 1779 with homogeneous Dirchlet boundary conditions that you don't want represented 1780 in the matrix. 1781 1782 Inspired by the structured grid interface to the HYPRE package 1783 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1784 1785 Fortran Note: 1786 `idxm` and `idxn` should be declared as 1787 $ MatStencil idxm(4,m),idxn(4,n) 1788 and the values inserted using 1789 .vb 1790 idxm(MatStencil_i,1) = i 1791 idxm(MatStencil_j,1) = j 1792 idxm(MatStencil_k,1) = k 1793 etc 1794 .ve 1795 1796 .seealso: [](chapter_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1797 `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`, 1798 `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` 1799 @*/ 1800 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1801 { 1802 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1803 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1804 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1805 1806 PetscFunctionBegin; 1807 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1808 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1809 PetscValidType(mat, 1); 1810 PetscValidPointer(idxm, 3); 1811 PetscValidPointer(idxn, 5); 1812 PetscValidScalarPointer(v, 6); 1813 1814 if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 1815 jdxm = buf; 1816 jdxn = buf + m; 1817 } else { 1818 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1819 jdxm = bufm; 1820 jdxn = bufn; 1821 } 1822 for (i = 0; i < m; i++) { 1823 for (j = 0; j < 3 - sdim; j++) dxm++; 1824 tmp = *dxm++ - starts[0]; 1825 for (j = 0; j < sdim - 1; j++) { 1826 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1827 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1828 } 1829 dxm++; 1830 jdxm[i] = tmp; 1831 } 1832 for (i = 0; i < n; i++) { 1833 for (j = 0; j < 3 - sdim; j++) dxn++; 1834 tmp = *dxn++ - starts[0]; 1835 for (j = 0; j < sdim - 1; j++) { 1836 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1837 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1838 } 1839 dxn++; 1840 jdxn[i] = tmp; 1841 } 1842 PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv)); 1843 PetscCall(PetscFree2(bufm, bufn)); 1844 PetscFunctionReturn(PETSC_SUCCESS); 1845 } 1846 1847 /*@ 1848 MatSetStencil - Sets the grid information for setting values into a matrix via 1849 `MatSetValuesStencil()` 1850 1851 Not Collective 1852 1853 Input Parameters: 1854 + mat - the matrix 1855 . dim - dimension of the grid 1, 2, or 3 1856 . dims - number of grid points in x, y, and z direction, including ghost points on your processor 1857 . starts - starting point of ghost nodes on your processor in x, y, and z direction 1858 - dof - number of degrees of freedom per node 1859 1860 Level: beginner 1861 1862 Notes: 1863 Inspired by the structured grid interface to the HYPRE package 1864 (www.llnl.gov/CASC/hyper) 1865 1866 For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the 1867 user. 1868 1869 .seealso: [](chapter_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1870 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()` 1871 @*/ 1872 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof) 1873 { 1874 PetscFunctionBegin; 1875 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1876 PetscValidIntPointer(dims, 3); 1877 PetscValidIntPointer(starts, 4); 1878 1879 mat->stencil.dim = dim + (dof > 1); 1880 for (PetscInt i = 0; i < dim; i++) { 1881 mat->stencil.dims[i] = dims[dim - i - 1]; /* copy the values in backwards */ 1882 mat->stencil.starts[i] = starts[dim - i - 1]; 1883 } 1884 mat->stencil.dims[dim] = dof; 1885 mat->stencil.starts[dim] = 0; 1886 mat->stencil.noc = (PetscBool)(dof == 1); 1887 PetscFunctionReturn(PETSC_SUCCESS); 1888 } 1889 1890 /*@C 1891 MatSetValuesBlocked - Inserts or adds a block of values into a matrix. 1892 1893 Not Collective 1894 1895 Input Parameters: 1896 + mat - the matrix 1897 . v - a logically two-dimensional array of values 1898 . m - the number of block rows 1899 . idxm - the global block indices 1900 . n - the number of block columns 1901 . idxn - the global block indices 1902 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values 1903 1904 Level: intermediate 1905 1906 Notes: 1907 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call 1908 MatXXXXSetPreallocation() or `MatSetUp()` before using this routine. 1909 1910 The `m` and `n` count the NUMBER of blocks in the row direction and column direction, 1911 NOT the total number of rows/columns; for example, if the block size is 2 and 1912 you are passing in values for rows 2,3,4,5 then m would be 2 (not 4). 1913 The values in idxm would be 1 2; that is the first index for each block divided by 1914 the block size. 1915 1916 You must call `MatSetBlockSize()` when constructing this matrix (before 1917 preallocating it). 1918 1919 By default the values, `v`, are row-oriented, so the layout of 1920 `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options. 1921 1922 Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES` 1923 options cannot be mixed without intervening calls to the assembly 1924 routines. 1925 1926 `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran 1927 as well as in C. 1928 1929 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1930 simply ignored. This allows easily inserting element stiffness matrices 1931 with homogeneous Dirchlet boundary conditions that you don't want represented 1932 in the matrix. 1933 1934 Each time an entry is set within a sparse matrix via `MatSetValues()`, 1935 internal searching must be done to determine where to place the 1936 data in the matrix storage space. By instead inserting blocks of 1937 entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is 1938 reduced. 1939 1940 Example: 1941 .vb 1942 Suppose m=n=2 and block size(bs) = 2 The array is 1943 1944 1 2 | 3 4 1945 5 6 | 7 8 1946 - - - | - - - 1947 9 10 | 11 12 1948 13 14 | 15 16 1949 1950 v[] should be passed in like 1951 v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] 1952 1953 If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then 1954 v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16] 1955 .ve 1956 1957 .seealso: [](chapter_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()` 1958 @*/ 1959 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1960 { 1961 PetscFunctionBeginHot; 1962 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1963 PetscValidType(mat, 1); 1964 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1965 PetscValidIntPointer(idxm, 3); 1966 PetscValidIntPointer(idxn, 5); 1967 MatCheckPreallocated(mat, 1); 1968 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1969 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1970 if (PetscDefined(USE_DEBUG)) { 1971 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1972 PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 1973 } 1974 if (PetscDefined(USE_DEBUG)) { 1975 PetscInt rbs, cbs, M, N, i; 1976 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1977 PetscCall(MatGetSize(mat, &M, &N)); 1978 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); 1979 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); 1980 } 1981 if (mat->assembled) { 1982 mat->was_assembled = PETSC_TRUE; 1983 mat->assembled = PETSC_FALSE; 1984 } 1985 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1986 if (mat->ops->setvaluesblocked) { 1987 PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv); 1988 } else { 1989 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn; 1990 PetscInt i, j, bs, cbs; 1991 1992 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 1993 if (m * bs + n * cbs <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 1994 iidxm = buf; 1995 iidxn = buf + m * bs; 1996 } else { 1997 PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc)); 1998 iidxm = bufr; 1999 iidxn = bufc; 2000 } 2001 for (i = 0; i < m; i++) { 2002 for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j; 2003 } 2004 if (m != n || bs != cbs || idxm != idxn) { 2005 for (i = 0; i < n; i++) { 2006 for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j; 2007 } 2008 } else iidxn = iidxm; 2009 PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv)); 2010 PetscCall(PetscFree2(bufr, bufc)); 2011 } 2012 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2013 PetscFunctionReturn(PETSC_SUCCESS); 2014 } 2015 2016 /*@C 2017 MatGetValues - Gets a block of local values from a matrix. 2018 2019 Not Collective; can only return values that are owned by the give process 2020 2021 Input Parameters: 2022 + mat - the matrix 2023 . v - a logically two-dimensional array for storing the values 2024 . m - the number of rows 2025 . idxm - the global indices of the rows 2026 . n - the number of columns 2027 - idxn - the global indices of the columns 2028 2029 Level: advanced 2030 2031 Notes: 2032 The user must allocate space (m*n `PetscScalar`s) for the values, `v`. 2033 The values, `v`, are then returned in a row-oriented format, 2034 analogous to that used by default in `MatSetValues()`. 2035 2036 `MatGetValues()` uses 0-based row and column numbers in 2037 Fortran as well as in C. 2038 2039 `MatGetValues()` requires that the matrix has been assembled 2040 with `MatAssemblyBegin()`/`MatAssemblyEnd()`. Thus, calls to 2041 `MatSetValues()` and `MatGetValues()` CANNOT be made in succession 2042 without intermediate matrix assembly. 2043 2044 Negative row or column indices will be ignored and those locations in `v` will be 2045 left unchanged. 2046 2047 For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI rank. 2048 That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable 2049 from `MatGetOwnershipRange`(mat,&rstart,&rend). 2050 2051 .seealso: [](chapter_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()` 2052 @*/ 2053 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) 2054 { 2055 PetscFunctionBegin; 2056 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2057 PetscValidType(mat, 1); 2058 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); 2059 PetscValidIntPointer(idxm, 3); 2060 PetscValidIntPointer(idxn, 5); 2061 PetscValidScalarPointer(v, 6); 2062 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2063 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2064 MatCheckPreallocated(mat, 1); 2065 2066 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2067 PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v); 2068 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2069 PetscFunctionReturn(PETSC_SUCCESS); 2070 } 2071 2072 /*@C 2073 MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices 2074 defined previously by `MatSetLocalToGlobalMapping()` 2075 2076 Not Collective 2077 2078 Input Parameters: 2079 + mat - the matrix 2080 . nrow - number of rows 2081 . irow - the row local indices 2082 . ncol - number of columns 2083 - icol - the column local indices 2084 2085 Output Parameter: 2086 . y - a logically two-dimensional array of values 2087 2088 Level: advanced 2089 2090 Notes: 2091 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine. 2092 2093 This routine can only return values that are owned by the requesting MPI rank. That is, for standard matrix formats, rows that, in the global numbering, 2094 are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can 2095 determine if the resulting global row associated with the local row r is owned by the requesting MPI rank by applying the `ISLocalToGlobalMapping` set 2096 with `MatSetLocalToGlobalMapping()`. 2097 2098 Developer Note: 2099 This is labelled with C so does not automatically generate Fortran stubs and interfaces 2100 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2101 2102 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2103 `MatSetValuesLocal()`, `MatGetValues()` 2104 @*/ 2105 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[]) 2106 { 2107 PetscFunctionBeginHot; 2108 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2109 PetscValidType(mat, 1); 2110 MatCheckPreallocated(mat, 1); 2111 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */ 2112 PetscValidIntPointer(irow, 3); 2113 PetscValidIntPointer(icol, 5); 2114 if (PetscDefined(USE_DEBUG)) { 2115 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2116 PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2117 } 2118 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2119 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2120 if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y); 2121 else { 2122 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm; 2123 if ((nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2124 irowm = buf; 2125 icolm = buf + nrow; 2126 } else { 2127 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2128 irowm = bufr; 2129 icolm = bufc; 2130 } 2131 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping())."); 2132 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping())."); 2133 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm)); 2134 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm)); 2135 PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y)); 2136 PetscCall(PetscFree2(bufr, bufc)); 2137 } 2138 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2139 PetscFunctionReturn(PETSC_SUCCESS); 2140 } 2141 2142 /*@ 2143 MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and 2144 the same size. Currently, this can only be called once and creates the given matrix. 2145 2146 Not Collective 2147 2148 Input Parameters: 2149 + mat - the matrix 2150 . nb - the number of blocks 2151 . bs - the number of rows (and columns) in each block 2152 . rows - a concatenation of the rows for each block 2153 - v - a concatenation of logically two-dimensional arrays of values 2154 2155 Level: advanced 2156 2157 Note: 2158 `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values 2159 2160 In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix. 2161 2162 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 2163 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()` 2164 @*/ 2165 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[]) 2166 { 2167 PetscFunctionBegin; 2168 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2169 PetscValidType(mat, 1); 2170 PetscValidIntPointer(rows, 4); 2171 PetscValidScalarPointer(v, 5); 2172 PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2173 2174 PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0)); 2175 if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v); 2176 else { 2177 for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES)); 2178 } 2179 PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0)); 2180 PetscFunctionReturn(PETSC_SUCCESS); 2181 } 2182 2183 /*@ 2184 MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by 2185 the routine `MatSetValuesLocal()` to allow users to insert matrix entries 2186 using a local (per-processor) numbering. 2187 2188 Not Collective 2189 2190 Input Parameters: 2191 + x - the matrix 2192 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()` 2193 - cmapping - column mapping 2194 2195 Level: intermediate 2196 2197 Note: 2198 If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix 2199 2200 .seealso: [](chapter_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()` 2201 @*/ 2202 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping) 2203 { 2204 PetscFunctionBegin; 2205 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 2206 PetscValidType(x, 1); 2207 if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2); 2208 if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3); 2209 if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping); 2210 else { 2211 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping)); 2212 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping)); 2213 } 2214 PetscFunctionReturn(PETSC_SUCCESS); 2215 } 2216 2217 /*@ 2218 MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()` 2219 2220 Not Collective 2221 2222 Input Parameter: 2223 . A - the matrix 2224 2225 Output Parameters: 2226 + rmapping - row mapping 2227 - cmapping - column mapping 2228 2229 Level: advanced 2230 2231 .seealso: [](chapter_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()` 2232 @*/ 2233 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping) 2234 { 2235 PetscFunctionBegin; 2236 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2237 PetscValidType(A, 1); 2238 if (rmapping) { 2239 PetscValidPointer(rmapping, 2); 2240 *rmapping = A->rmap->mapping; 2241 } 2242 if (cmapping) { 2243 PetscValidPointer(cmapping, 3); 2244 *cmapping = A->cmap->mapping; 2245 } 2246 PetscFunctionReturn(PETSC_SUCCESS); 2247 } 2248 2249 /*@ 2250 MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix 2251 2252 Logically Collective 2253 2254 Input Parameters: 2255 + A - the matrix 2256 . rmap - row layout 2257 - cmap - column layout 2258 2259 Level: advanced 2260 2261 Note: 2262 The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called. 2263 2264 .seealso: [](chapter_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()` 2265 @*/ 2266 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap) 2267 { 2268 PetscFunctionBegin; 2269 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2270 PetscCall(PetscLayoutReference(rmap, &A->rmap)); 2271 PetscCall(PetscLayoutReference(cmap, &A->cmap)); 2272 PetscFunctionReturn(PETSC_SUCCESS); 2273 } 2274 2275 /*@ 2276 MatGetLayouts - Gets the `PetscLayout` objects for rows and columns 2277 2278 Not Collective 2279 2280 Input Parameter: 2281 . A - the matrix 2282 2283 Output Parameters: 2284 + rmap - row layout 2285 - cmap - column layout 2286 2287 Level: advanced 2288 2289 .seealso: [](chapter_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()` 2290 @*/ 2291 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap) 2292 { 2293 PetscFunctionBegin; 2294 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2295 PetscValidType(A, 1); 2296 if (rmap) { 2297 PetscValidPointer(rmap, 2); 2298 *rmap = A->rmap; 2299 } 2300 if (cmap) { 2301 PetscValidPointer(cmap, 3); 2302 *cmap = A->cmap; 2303 } 2304 PetscFunctionReturn(PETSC_SUCCESS); 2305 } 2306 2307 /*@C 2308 MatSetValuesLocal - Inserts or adds values into certain locations of a matrix, 2309 using a local numbering of the nodes. 2310 2311 Not Collective 2312 2313 Input Parameters: 2314 + mat - the matrix 2315 . nrow - number of rows 2316 . irow - the row local indices 2317 . ncol - number of columns 2318 . icol - the column local indices 2319 . y - a logically two-dimensional array of values 2320 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2321 2322 Level: intermediate 2323 2324 Notes: 2325 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 2326 `MatSetUp()` before using this routine 2327 2328 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine 2329 2330 Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2331 options cannot be mixed without intervening calls to the assembly 2332 routines. 2333 2334 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2335 MUST be called after all calls to `MatSetValuesLocal()` have been completed. 2336 2337 Developer Note: 2338 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2339 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2340 2341 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2342 `MatGetValuesLocal()` 2343 @*/ 2344 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2345 { 2346 PetscFunctionBeginHot; 2347 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2348 PetscValidType(mat, 1); 2349 MatCheckPreallocated(mat, 1); 2350 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2351 PetscValidIntPointer(irow, 3); 2352 PetscValidIntPointer(icol, 5); 2353 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2354 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2355 if (PetscDefined(USE_DEBUG)) { 2356 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2357 PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2358 } 2359 2360 if (mat->assembled) { 2361 mat->was_assembled = PETSC_TRUE; 2362 mat->assembled = PETSC_FALSE; 2363 } 2364 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2365 if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv); 2366 else { 2367 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2368 const PetscInt *irowm, *icolm; 2369 2370 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2371 bufr = buf; 2372 bufc = buf + nrow; 2373 irowm = bufr; 2374 icolm = bufc; 2375 } else { 2376 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2377 irowm = bufr; 2378 icolm = bufc; 2379 } 2380 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr)); 2381 else irowm = irow; 2382 if (mat->cmap->mapping) { 2383 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2384 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc)); 2385 } else icolm = irowm; 2386 } else icolm = icol; 2387 PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv)); 2388 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2389 } 2390 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2391 PetscFunctionReturn(PETSC_SUCCESS); 2392 } 2393 2394 /*@C 2395 MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix, 2396 using a local ordering of the nodes a block at a time. 2397 2398 Not Collective 2399 2400 Input Parameters: 2401 + x - the matrix 2402 . nrow - number of rows 2403 . irow - the row local indices 2404 . ncol - number of columns 2405 . icol - the column local indices 2406 . y - a logically two-dimensional array of values 2407 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2408 2409 Level: intermediate 2410 2411 Notes: 2412 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 2413 `MatSetUp()` before using this routine 2414 2415 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()` 2416 before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the 2417 2418 Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2419 options cannot be mixed without intervening calls to the assembly 2420 routines. 2421 2422 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2423 MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed. 2424 2425 Developer Note: 2426 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2427 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2428 2429 .seealso: [](chapter_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, 2430 `MatSetValuesLocal()`, `MatSetValuesBlocked()` 2431 @*/ 2432 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2433 { 2434 PetscFunctionBeginHot; 2435 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2436 PetscValidType(mat, 1); 2437 MatCheckPreallocated(mat, 1); 2438 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2439 PetscValidIntPointer(irow, 3); 2440 PetscValidIntPointer(icol, 5); 2441 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2442 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2443 if (PetscDefined(USE_DEBUG)) { 2444 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2445 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); 2446 } 2447 2448 if (mat->assembled) { 2449 mat->was_assembled = PETSC_TRUE; 2450 mat->assembled = PETSC_FALSE; 2451 } 2452 if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */ 2453 PetscInt irbs, rbs; 2454 PetscCall(MatGetBlockSizes(mat, &rbs, NULL)); 2455 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs)); 2456 PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs); 2457 } 2458 if (PetscUnlikelyDebug(mat->cmap->mapping)) { 2459 PetscInt icbs, cbs; 2460 PetscCall(MatGetBlockSizes(mat, NULL, &cbs)); 2461 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs)); 2462 PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs); 2463 } 2464 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2465 if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv); 2466 else { 2467 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2468 const PetscInt *irowm, *icolm; 2469 2470 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2471 bufr = buf; 2472 bufc = buf + nrow; 2473 irowm = bufr; 2474 icolm = bufc; 2475 } else { 2476 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2477 irowm = bufr; 2478 icolm = bufc; 2479 } 2480 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr)); 2481 else irowm = irow; 2482 if (mat->cmap->mapping) { 2483 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2484 PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc)); 2485 } else icolm = irowm; 2486 } else icolm = icol; 2487 PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv)); 2488 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2489 } 2490 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2491 PetscFunctionReturn(PETSC_SUCCESS); 2492 } 2493 2494 /*@ 2495 MatMultDiagonalBlock - Computes the matrix-vector product, y = Dx. Where D is defined by the inode or block structure of the diagonal 2496 2497 Collective 2498 2499 Input Parameters: 2500 + mat - the matrix 2501 - x - the vector to be multiplied 2502 2503 Output Parameter: 2504 . y - the result 2505 2506 Level: developer 2507 2508 Note: 2509 The vectors `x` and `y` cannot be the same. I.e., one cannot 2510 call `MatMultDiagonalBlock`(A,y,y). 2511 2512 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2513 @*/ 2514 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y) 2515 { 2516 PetscFunctionBegin; 2517 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2518 PetscValidType(mat, 1); 2519 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2520 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2521 2522 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2523 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2524 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2525 MatCheckPreallocated(mat, 1); 2526 2527 PetscUseTypeMethod(mat, multdiagonalblock, x, y); 2528 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2529 PetscFunctionReturn(PETSC_SUCCESS); 2530 } 2531 2532 /*@ 2533 MatMult - Computes the matrix-vector product, y = Ax. 2534 2535 Neighbor-wise Collective 2536 2537 Input Parameters: 2538 + mat - the matrix 2539 - x - the vector to be multiplied 2540 2541 Output Parameter: 2542 . y - the result 2543 2544 Level: beginner 2545 2546 Note: 2547 The vectors `x` and `y` cannot be the same. I.e., one cannot 2548 call `MatMult`(A,y,y). 2549 2550 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2551 @*/ 2552 PetscErrorCode MatMult(Mat mat, Vec x, Vec y) 2553 { 2554 PetscFunctionBegin; 2555 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2556 PetscValidType(mat, 1); 2557 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2558 VecCheckAssembled(x); 2559 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2560 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2561 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2562 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2563 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); 2564 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); 2565 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); 2566 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); 2567 PetscCall(VecSetErrorIfLocked(y, 3)); 2568 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2569 MatCheckPreallocated(mat, 1); 2570 2571 PetscCall(VecLockReadPush(x)); 2572 PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0)); 2573 PetscUseTypeMethod(mat, mult, x, y); 2574 PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0)); 2575 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2576 PetscCall(VecLockReadPop(x)); 2577 PetscFunctionReturn(PETSC_SUCCESS); 2578 } 2579 2580 /*@ 2581 MatMultTranspose - Computes matrix transpose times a vector y = A^T * x. 2582 2583 Neighbor-wise Collective 2584 2585 Input Parameters: 2586 + mat - the matrix 2587 - x - the vector to be multiplied 2588 2589 Output Parameter: 2590 . y - the result 2591 2592 Level: beginner 2593 2594 Notes: 2595 The vectors `x` and `y` cannot be the same. I.e., one cannot 2596 call `MatMultTranspose`(A,y,y). 2597 2598 For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple, 2599 use `MatMultHermitianTranspose()` 2600 2601 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()` 2602 @*/ 2603 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y) 2604 { 2605 PetscErrorCode (*op)(Mat, Vec, Vec) = NULL; 2606 2607 PetscFunctionBegin; 2608 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2609 PetscValidType(mat, 1); 2610 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2611 VecCheckAssembled(x); 2612 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2613 2614 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2615 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2616 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2617 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); 2618 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); 2619 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); 2620 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); 2621 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2622 MatCheckPreallocated(mat, 1); 2623 2624 if (!mat->ops->multtranspose) { 2625 if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult; 2626 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); 2627 } else op = mat->ops->multtranspose; 2628 PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0)); 2629 PetscCall(VecLockReadPush(x)); 2630 PetscCall((*op)(mat, x, y)); 2631 PetscCall(VecLockReadPop(x)); 2632 PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0)); 2633 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2634 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2635 PetscFunctionReturn(PETSC_SUCCESS); 2636 } 2637 2638 /*@ 2639 MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector. 2640 2641 Neighbor-wise Collective 2642 2643 Input Parameters: 2644 + mat - the matrix 2645 - x - the vector to be multilplied 2646 2647 Output Parameter: 2648 . y - the result 2649 2650 Level: beginner 2651 2652 Notes: 2653 The vectors `x` and `y` cannot be the same. I.e., one cannot 2654 call `MatMultHermitianTranspose`(A,y,y). 2655 2656 Also called the conjugate transpose, complex conjugate transpose, or adjoint. 2657 2658 For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical. 2659 2660 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()` 2661 @*/ 2662 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y) 2663 { 2664 PetscFunctionBegin; 2665 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2666 PetscValidType(mat, 1); 2667 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2668 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2669 2670 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2671 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2672 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2673 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); 2674 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); 2675 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); 2676 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); 2677 MatCheckPreallocated(mat, 1); 2678 2679 PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0)); 2680 #if defined(PETSC_USE_COMPLEX) 2681 if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) { 2682 PetscCall(VecLockReadPush(x)); 2683 if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y); 2684 else PetscUseTypeMethod(mat, mult, x, y); 2685 PetscCall(VecLockReadPop(x)); 2686 } else { 2687 Vec w; 2688 PetscCall(VecDuplicate(x, &w)); 2689 PetscCall(VecCopy(x, w)); 2690 PetscCall(VecConjugate(w)); 2691 PetscCall(MatMultTranspose(mat, w, y)); 2692 PetscCall(VecDestroy(&w)); 2693 PetscCall(VecConjugate(y)); 2694 } 2695 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2696 #else 2697 PetscCall(MatMultTranspose(mat, x, y)); 2698 #endif 2699 PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0)); 2700 PetscFunctionReturn(PETSC_SUCCESS); 2701 } 2702 2703 /*@ 2704 MatMultAdd - Computes v3 = v2 + A * v1. 2705 2706 Neighbor-wise Collective 2707 2708 Input Parameters: 2709 + mat - the matrix 2710 . v1 - the vector to be multiplied by `mat` 2711 - v2 - the vector to be added to the result 2712 2713 Output Parameter: 2714 . v3 - the result 2715 2716 Level: beginner 2717 2718 Note: 2719 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2720 call `MatMultAdd`(A,v1,v2,v1). 2721 2722 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()` 2723 @*/ 2724 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2725 { 2726 PetscFunctionBegin; 2727 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2728 PetscValidType(mat, 1); 2729 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2730 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2731 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2732 2733 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2734 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2735 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); 2736 /* 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); 2737 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); */ 2738 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); 2739 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); 2740 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2741 MatCheckPreallocated(mat, 1); 2742 2743 PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3)); 2744 PetscCall(VecLockReadPush(v1)); 2745 PetscUseTypeMethod(mat, multadd, v1, v2, v3); 2746 PetscCall(VecLockReadPop(v1)); 2747 PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3)); 2748 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2749 PetscFunctionReturn(PETSC_SUCCESS); 2750 } 2751 2752 /*@ 2753 MatMultTransposeAdd - Computes v3 = v2 + A' * v1. 2754 2755 Neighbor-wise Collective 2756 2757 Input Parameters: 2758 + mat - the matrix 2759 . v1 - the vector to be multiplied by the transpose of the matrix 2760 - v2 - the vector to be added to the result 2761 2762 Output Parameter: 2763 . v3 - the result 2764 2765 Level: beginner 2766 2767 Note: 2768 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2769 call `MatMultTransposeAdd`(A,v1,v2,v1). 2770 2771 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2772 @*/ 2773 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2774 { 2775 PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd; 2776 2777 PetscFunctionBegin; 2778 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2779 PetscValidType(mat, 1); 2780 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2781 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2782 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2783 2784 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2785 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2786 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); 2787 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); 2788 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); 2789 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2790 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2791 MatCheckPreallocated(mat, 1); 2792 2793 PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2794 PetscCall(VecLockReadPush(v1)); 2795 PetscCall((*op)(mat, v1, v2, v3)); 2796 PetscCall(VecLockReadPop(v1)); 2797 PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2798 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2799 PetscFunctionReturn(PETSC_SUCCESS); 2800 } 2801 2802 /*@ 2803 MatMultHermitianTransposeAdd - Computes v3 = v2 + A^H * v1. 2804 2805 Neighbor-wise Collective 2806 2807 Input Parameters: 2808 + mat - the matrix 2809 . v1 - the vector to be multiplied by the Hermitian transpose 2810 - v2 - the vector to be added to the result 2811 2812 Output Parameter: 2813 . v3 - the result 2814 2815 Level: beginner 2816 2817 Note: 2818 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2819 call `MatMultHermitianTransposeAdd`(A,v1,v2,v1). 2820 2821 .seealso: [](chapter_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2822 @*/ 2823 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2824 { 2825 PetscFunctionBegin; 2826 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2827 PetscValidType(mat, 1); 2828 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2829 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2830 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2831 2832 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2833 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2834 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2835 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); 2836 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); 2837 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); 2838 MatCheckPreallocated(mat, 1); 2839 2840 PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2841 PetscCall(VecLockReadPush(v1)); 2842 if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3); 2843 else { 2844 Vec w, z; 2845 PetscCall(VecDuplicate(v1, &w)); 2846 PetscCall(VecCopy(v1, w)); 2847 PetscCall(VecConjugate(w)); 2848 PetscCall(VecDuplicate(v3, &z)); 2849 PetscCall(MatMultTranspose(mat, w, z)); 2850 PetscCall(VecDestroy(&w)); 2851 PetscCall(VecConjugate(z)); 2852 if (v2 != v3) { 2853 PetscCall(VecWAXPY(v3, 1.0, v2, z)); 2854 } else { 2855 PetscCall(VecAXPY(v3, 1.0, z)); 2856 } 2857 PetscCall(VecDestroy(&z)); 2858 } 2859 PetscCall(VecLockReadPop(v1)); 2860 PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2861 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2862 PetscFunctionReturn(PETSC_SUCCESS); 2863 } 2864 2865 /*@C 2866 MatGetFactorType - gets the type of factorization it is 2867 2868 Not Collective 2869 2870 Input Parameter: 2871 . mat - the matrix 2872 2873 Output Parameter: 2874 . 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` 2875 2876 Level: intermediate 2877 2878 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2879 `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2880 @*/ 2881 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t) 2882 { 2883 PetscFunctionBegin; 2884 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2885 PetscValidType(mat, 1); 2886 PetscValidPointer(t, 2); 2887 *t = mat->factortype; 2888 PetscFunctionReturn(PETSC_SUCCESS); 2889 } 2890 2891 /*@C 2892 MatSetFactorType - sets the type of factorization it is 2893 2894 Logically Collective 2895 2896 Input Parameters: 2897 + mat - the matrix 2898 - 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` 2899 2900 Level: intermediate 2901 2902 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2903 `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2904 @*/ 2905 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t) 2906 { 2907 PetscFunctionBegin; 2908 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2909 PetscValidType(mat, 1); 2910 mat->factortype = t; 2911 PetscFunctionReturn(PETSC_SUCCESS); 2912 } 2913 2914 /*@C 2915 MatGetInfo - Returns information about matrix storage (number of 2916 nonzeros, memory, etc.). 2917 2918 Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag 2919 2920 Input Parameters: 2921 + mat - the matrix 2922 - 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) 2923 2924 Output Parameter: 2925 . info - matrix information context 2926 2927 Notes: 2928 The `MatInfo` context contains a variety of matrix data, including 2929 number of nonzeros allocated and used, number of mallocs during 2930 matrix assembly, etc. Additional information for factored matrices 2931 is provided (such as the fill ratio, number of mallocs during 2932 factorization, etc.). Much of this info is printed to `PETSC_STDOUT` 2933 when using the runtime options 2934 $ -info -mat_view ::ascii_info 2935 2936 Example: 2937 See the file ${PETSC_DIR}/include/petscmat.h for a complete list of 2938 data within the MatInfo context. For example, 2939 .vb 2940 MatInfo info; 2941 Mat A; 2942 double mal, nz_a, nz_u; 2943 2944 MatGetInfo(A,MAT_LOCAL,&info); 2945 mal = info.mallocs; 2946 nz_a = info.nz_allocated; 2947 .ve 2948 2949 Fortran users should declare info as a double precision 2950 array of dimension `MAT_INFO_SIZE`, and then extract the parameters 2951 of interest. See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h 2952 a complete list of parameter names. 2953 .vb 2954 double precision info(MAT_INFO_SIZE) 2955 double precision mal, nz_a 2956 Mat A 2957 integer ierr 2958 2959 call MatGetInfo(A,MAT_LOCAL,info,ierr) 2960 mal = info(MAT_INFO_MALLOCS) 2961 nz_a = info(MAT_INFO_NZ_ALLOCATED) 2962 .ve 2963 2964 Level: intermediate 2965 2966 Developer Note: 2967 The Fortran interface is not autogenerated as the 2968 interface definition cannot be generated correctly [due to `MatInfo` argument] 2969 2970 .seealso: [](chapter_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()` 2971 @*/ 2972 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info) 2973 { 2974 PetscFunctionBegin; 2975 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2976 PetscValidType(mat, 1); 2977 PetscValidPointer(info, 3); 2978 MatCheckPreallocated(mat, 1); 2979 PetscUseTypeMethod(mat, getinfo, flag, info); 2980 PetscFunctionReturn(PETSC_SUCCESS); 2981 } 2982 2983 /* 2984 This is used by external packages where it is not easy to get the info from the actual 2985 matrix factorization. 2986 */ 2987 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info) 2988 { 2989 PetscFunctionBegin; 2990 PetscCall(PetscMemzero(info, sizeof(MatInfo))); 2991 PetscFunctionReturn(PETSC_SUCCESS); 2992 } 2993 2994 /*@C 2995 MatLUFactor - Performs in-place LU factorization of matrix. 2996 2997 Collective 2998 2999 Input Parameters: 3000 + mat - the matrix 3001 . row - row permutation 3002 . col - column permutation 3003 - info - options for factorization, includes 3004 .vb 3005 fill - expected fill as ratio of original fill. 3006 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3007 Run with the option -info to determine an optimal value to use 3008 .ve 3009 Level: developer 3010 3011 Notes: 3012 Most users should employ the `KSP` interface for linear solvers 3013 instead of working directly with matrix algebra routines such as this. 3014 See, e.g., `KSPCreate()`. 3015 3016 This changes the state of the matrix to a factored matrix; it cannot be used 3017 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3018 3019 This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()` 3020 when not using `KSP`. 3021 3022 Developer Note: 3023 The Fortran interface is not autogenerated as the 3024 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3025 3026 .seealso: [](chapter_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, 3027 `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3028 @*/ 3029 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3030 { 3031 MatFactorInfo tinfo; 3032 3033 PetscFunctionBegin; 3034 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3035 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3036 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3037 if (info) PetscValidPointer(info, 4); 3038 PetscValidType(mat, 1); 3039 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3040 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3041 MatCheckPreallocated(mat, 1); 3042 if (!info) { 3043 PetscCall(MatFactorInfoInitialize(&tinfo)); 3044 info = &tinfo; 3045 } 3046 3047 PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0)); 3048 PetscUseTypeMethod(mat, lufactor, row, col, info); 3049 PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0)); 3050 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3051 PetscFunctionReturn(PETSC_SUCCESS); 3052 } 3053 3054 /*@C 3055 MatILUFactor - Performs in-place ILU factorization of matrix. 3056 3057 Collective 3058 3059 Input Parameters: 3060 + mat - the matrix 3061 . row - row permutation 3062 . col - column permutation 3063 - info - structure containing 3064 .vb 3065 levels - number of levels of fill. 3066 expected fill - as ratio of original fill. 3067 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 3068 missing diagonal entries) 3069 .ve 3070 3071 Level: developer 3072 3073 Notes: 3074 Most users should employ the `KSP` interface for linear solvers 3075 instead of working directly with matrix algebra routines such as this. 3076 See, e.g., `KSPCreate()`. 3077 3078 Probably really in-place only when level of fill is zero, otherwise allocates 3079 new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()` 3080 when not using `KSP`. 3081 3082 Developer Note: 3083 The Fortran interface is not autogenerated as the 3084 interface definition cannot be generated correctly [due to MatFactorInfo] 3085 3086 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 3087 @*/ 3088 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3089 { 3090 PetscFunctionBegin; 3091 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3092 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3093 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3094 PetscValidPointer(info, 4); 3095 PetscValidType(mat, 1); 3096 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 3097 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3098 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3099 MatCheckPreallocated(mat, 1); 3100 3101 PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0)); 3102 PetscUseTypeMethod(mat, ilufactor, row, col, info); 3103 PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0)); 3104 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3105 PetscFunctionReturn(PETSC_SUCCESS); 3106 } 3107 3108 /*@C 3109 MatLUFactorSymbolic - Performs symbolic LU factorization of matrix. 3110 Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`. 3111 3112 Collective 3113 3114 Input Parameters: 3115 + fact - the factor matrix obtained with `MatGetFactor()` 3116 . mat - the matrix 3117 . row - the row permutation 3118 . col - the column permutation 3119 - info - options for factorization, includes 3120 .vb 3121 fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use 3122 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3123 .ve 3124 3125 Level: developer 3126 3127 Notes: 3128 See [Matrix Factorization](sec_matfactor) for additional information about factorizations 3129 3130 Most users should employ the simplified `KSP` interface for linear solvers 3131 instead of working directly with matrix algebra routines such as this. 3132 See, e.g., `KSPCreate()`. 3133 3134 Developer Note: 3135 The Fortran interface is not autogenerated as the 3136 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3137 3138 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3139 @*/ 3140 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 3141 { 3142 MatFactorInfo tinfo; 3143 3144 PetscFunctionBegin; 3145 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3146 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3147 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 3148 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 3149 if (info) PetscValidPointer(info, 5); 3150 PetscValidType(fact, 1); 3151 PetscValidType(mat, 2); 3152 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3153 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3154 MatCheckPreallocated(mat, 2); 3155 if (!info) { 3156 PetscCall(MatFactorInfoInitialize(&tinfo)); 3157 info = &tinfo; 3158 } 3159 3160 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0)); 3161 PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info); 3162 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0)); 3163 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3164 PetscFunctionReturn(PETSC_SUCCESS); 3165 } 3166 3167 /*@C 3168 MatLUFactorNumeric - Performs numeric LU factorization of a matrix. 3169 Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`. 3170 3171 Collective 3172 3173 Input Parameters: 3174 + fact - the factor matrix obtained with `MatGetFactor()` 3175 . mat - the matrix 3176 - info - options for factorization 3177 3178 Level: developer 3179 3180 Notes: 3181 See `MatLUFactor()` for in-place factorization. See 3182 `MatCholeskyFactorNumeric()` for the symmetric, positive definite case. 3183 3184 Most users should employ the `KSP` interface for linear solvers 3185 instead of working directly with matrix algebra routines such as this. 3186 See, e.g., `KSPCreate()`. 3187 3188 Developer Note: 3189 The Fortran interface is not autogenerated as the 3190 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3191 3192 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()` 3193 @*/ 3194 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3195 { 3196 MatFactorInfo tinfo; 3197 3198 PetscFunctionBegin; 3199 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3200 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3201 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3202 PetscValidType(fact, 1); 3203 PetscValidType(mat, 2); 3204 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3205 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, 3206 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3207 3208 MatCheckPreallocated(mat, 2); 3209 if (!info) { 3210 PetscCall(MatFactorInfoInitialize(&tinfo)); 3211 info = &tinfo; 3212 } 3213 3214 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3215 else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0)); 3216 PetscUseTypeMethod(fact, lufactornumeric, mat, info); 3217 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3218 else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0)); 3219 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3220 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3221 PetscFunctionReturn(PETSC_SUCCESS); 3222 } 3223 3224 /*@C 3225 MatCholeskyFactor - Performs in-place Cholesky factorization of a 3226 symmetric matrix. 3227 3228 Collective 3229 3230 Input Parameters: 3231 + mat - the matrix 3232 . perm - row and column permutations 3233 - f - expected fill as ratio of original fill 3234 3235 Level: developer 3236 3237 Notes: 3238 See `MatLUFactor()` for the nonsymmetric case. See also `MatGetFactor()`, 3239 `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`. 3240 3241 Most users should employ the `KSP` interface for linear solvers 3242 instead of working directly with matrix algebra routines such as this. 3243 See, e.g., `KSPCreate()`. 3244 3245 Developer Note: 3246 The Fortran interface is not autogenerated as the 3247 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3248 3249 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()` 3250 `MatGetOrdering()` 3251 @*/ 3252 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info) 3253 { 3254 MatFactorInfo tinfo; 3255 3256 PetscFunctionBegin; 3257 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3258 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2); 3259 if (info) PetscValidPointer(info, 3); 3260 PetscValidType(mat, 1); 3261 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3262 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3263 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3264 MatCheckPreallocated(mat, 1); 3265 if (!info) { 3266 PetscCall(MatFactorInfoInitialize(&tinfo)); 3267 info = &tinfo; 3268 } 3269 3270 PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0)); 3271 PetscUseTypeMethod(mat, choleskyfactor, perm, info); 3272 PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0)); 3273 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3274 PetscFunctionReturn(PETSC_SUCCESS); 3275 } 3276 3277 /*@C 3278 MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization 3279 of a symmetric matrix. 3280 3281 Collective 3282 3283 Input Parameters: 3284 + fact - the factor matrix obtained with `MatGetFactor()` 3285 . mat - the matrix 3286 . perm - row and column permutations 3287 - info - options for factorization, includes 3288 .vb 3289 fill - expected fill as ratio of original fill. 3290 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3291 Run with the option -info to determine an optimal value to use 3292 .ve 3293 3294 Level: developer 3295 3296 Notes: 3297 See `MatLUFactorSymbolic()` for the nonsymmetric case. See also 3298 `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`. 3299 3300 Most users should employ the `KSP` interface for linear solvers 3301 instead of working directly with matrix algebra routines such as this. 3302 See, e.g., `KSPCreate()`. 3303 3304 Developer Note: 3305 The Fortran interface is not autogenerated as the 3306 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3307 3308 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()` 3309 `MatGetOrdering()` 3310 @*/ 3311 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 3312 { 3313 MatFactorInfo tinfo; 3314 3315 PetscFunctionBegin; 3316 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3317 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3318 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 3319 if (info) PetscValidPointer(info, 4); 3320 PetscValidType(fact, 1); 3321 PetscValidType(mat, 2); 3322 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3323 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3324 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3325 MatCheckPreallocated(mat, 2); 3326 if (!info) { 3327 PetscCall(MatFactorInfoInitialize(&tinfo)); 3328 info = &tinfo; 3329 } 3330 3331 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3332 PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info); 3333 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3334 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3335 PetscFunctionReturn(PETSC_SUCCESS); 3336 } 3337 3338 /*@C 3339 MatCholeskyFactorNumeric - Performs numeric Cholesky factorization 3340 of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and 3341 `MatCholeskyFactorSymbolic()`. 3342 3343 Collective 3344 3345 Input Parameters: 3346 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored 3347 . mat - the initial matrix that is to be factored 3348 - info - options for factorization 3349 3350 Level: developer 3351 3352 Note: 3353 Most users should employ the `KSP` interface for linear solvers 3354 instead of working directly with matrix algebra routines such as this. 3355 See, e.g., `KSPCreate()`. 3356 3357 Developer Note: 3358 The Fortran interface is not autogenerated as the 3359 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3360 3361 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()` 3362 @*/ 3363 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3364 { 3365 MatFactorInfo tinfo; 3366 3367 PetscFunctionBegin; 3368 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3369 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3370 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3371 PetscValidType(fact, 1); 3372 PetscValidType(mat, 2); 3373 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3374 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, 3375 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3376 MatCheckPreallocated(mat, 2); 3377 if (!info) { 3378 PetscCall(MatFactorInfoInitialize(&tinfo)); 3379 info = &tinfo; 3380 } 3381 3382 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3383 else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0)); 3384 PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info); 3385 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3386 else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0)); 3387 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3388 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3389 PetscFunctionReturn(PETSC_SUCCESS); 3390 } 3391 3392 /*@ 3393 MatQRFactor - Performs in-place QR factorization of matrix. 3394 3395 Collective 3396 3397 Input Parameters: 3398 + mat - the matrix 3399 . col - column permutation 3400 - info - options for factorization, includes 3401 .vb 3402 fill - expected fill as ratio of original fill. 3403 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3404 Run with the option -info to determine an optimal value to use 3405 .ve 3406 3407 Level: developer 3408 3409 Notes: 3410 Most users should employ the `KSP` interface for linear solvers 3411 instead of working directly with matrix algebra routines such as this. 3412 See, e.g., `KSPCreate()`. 3413 3414 This changes the state of the matrix to a factored matrix; it cannot be used 3415 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3416 3417 Developer Note: 3418 The Fortran interface is not autogenerated as the 3419 interface definition cannot be generated correctly [due to MatFactorInfo] 3420 3421 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`, 3422 `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3423 @*/ 3424 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info) 3425 { 3426 PetscFunctionBegin; 3427 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3428 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2); 3429 if (info) PetscValidPointer(info, 3); 3430 PetscValidType(mat, 1); 3431 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3432 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3433 MatCheckPreallocated(mat, 1); 3434 PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0)); 3435 PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info)); 3436 PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0)); 3437 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3438 PetscFunctionReturn(PETSC_SUCCESS); 3439 } 3440 3441 /*@ 3442 MatQRFactorSymbolic - Performs symbolic QR factorization of matrix. 3443 Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`. 3444 3445 Collective 3446 3447 Input Parameters: 3448 + fact - the factor matrix obtained with `MatGetFactor()` 3449 . mat - the matrix 3450 . col - column permutation 3451 - info - options for factorization, includes 3452 .vb 3453 fill - expected fill as ratio of original fill. 3454 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3455 Run with the option -info to determine an optimal value to use 3456 .ve 3457 3458 Level: developer 3459 3460 Note: 3461 Most users should employ the `KSP` interface for linear solvers 3462 instead of working directly with matrix algebra routines such as this. 3463 See, e.g., `KSPCreate()`. 3464 3465 Developer Note: 3466 The Fortran interface is not autogenerated as the 3467 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3468 3469 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3470 @*/ 3471 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info) 3472 { 3473 MatFactorInfo tinfo; 3474 3475 PetscFunctionBegin; 3476 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3477 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3478 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3479 if (info) PetscValidPointer(info, 4); 3480 PetscValidType(fact, 1); 3481 PetscValidType(mat, 2); 3482 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3483 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3484 MatCheckPreallocated(mat, 2); 3485 if (!info) { 3486 PetscCall(MatFactorInfoInitialize(&tinfo)); 3487 info = &tinfo; 3488 } 3489 3490 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3491 PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info)); 3492 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3493 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3494 PetscFunctionReturn(PETSC_SUCCESS); 3495 } 3496 3497 /*@ 3498 MatQRFactorNumeric - Performs numeric QR factorization of a matrix. 3499 Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`. 3500 3501 Collective 3502 3503 Input Parameters: 3504 + fact - the factor matrix obtained with `MatGetFactor()` 3505 . mat - the matrix 3506 - info - options for factorization 3507 3508 Level: developer 3509 3510 Notes: 3511 See `MatQRFactor()` for in-place factorization. 3512 3513 Most users should employ the `KSP` interface for linear solvers 3514 instead of working directly with matrix algebra routines such as this. 3515 See, e.g., `KSPCreate()`. 3516 3517 Developer Note: 3518 The Fortran interface is not autogenerated as the 3519 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3520 3521 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()` 3522 @*/ 3523 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3524 { 3525 MatFactorInfo tinfo; 3526 3527 PetscFunctionBegin; 3528 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3529 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3530 PetscValidType(fact, 1); 3531 PetscValidType(mat, 2); 3532 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3533 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, 3534 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3535 3536 MatCheckPreallocated(mat, 2); 3537 if (!info) { 3538 PetscCall(MatFactorInfoInitialize(&tinfo)); 3539 info = &tinfo; 3540 } 3541 3542 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3543 else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0)); 3544 PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info)); 3545 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3546 else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0)); 3547 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3548 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3549 PetscFunctionReturn(PETSC_SUCCESS); 3550 } 3551 3552 /*@ 3553 MatSolve - Solves A x = b, given a factored matrix. 3554 3555 Neighbor-wise Collective 3556 3557 Input Parameters: 3558 + mat - the factored matrix 3559 - b - the right-hand-side vector 3560 3561 Output Parameter: 3562 . x - the result vector 3563 3564 Level: developer 3565 3566 Notes: 3567 The vectors `b` and `x` cannot be the same. I.e., one cannot 3568 call `MatSolve`(A,x,x). 3569 3570 Most users should employ the `KSP` interface for linear solvers 3571 instead of working directly with matrix algebra routines such as this. 3572 See, e.g., `KSPCreate()`. 3573 3574 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3575 @*/ 3576 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x) 3577 { 3578 PetscFunctionBegin; 3579 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3580 PetscValidType(mat, 1); 3581 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3582 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3583 PetscCheckSameComm(mat, 1, b, 2); 3584 PetscCheckSameComm(mat, 1, x, 3); 3585 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3586 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); 3587 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); 3588 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); 3589 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3590 MatCheckPreallocated(mat, 1); 3591 3592 PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0)); 3593 if (mat->factorerrortype) { 3594 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3595 PetscCall(VecSetInf(x)); 3596 } else PetscUseTypeMethod(mat, solve, b, x); 3597 PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0)); 3598 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3599 PetscFunctionReturn(PETSC_SUCCESS); 3600 } 3601 3602 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans) 3603 { 3604 Vec b, x; 3605 PetscInt N, i; 3606 PetscErrorCode (*f)(Mat, Vec, Vec); 3607 PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE; 3608 3609 PetscFunctionBegin; 3610 if (A->factorerrortype) { 3611 PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype)); 3612 PetscCall(MatSetInf(X)); 3613 PetscFunctionReturn(PETSC_SUCCESS); 3614 } 3615 f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose; 3616 PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 3617 PetscCall(MatBoundToCPU(A, &Abound)); 3618 if (!Abound) { 3619 PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3620 PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3621 } 3622 #if defined(PETSC_HAVE_CUDA) 3623 if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B)); 3624 if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X)); 3625 #elif (PETSC_HAVE_HIP) 3626 if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B)); 3627 if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X)); 3628 #endif 3629 PetscCall(MatGetSize(B, NULL, &N)); 3630 for (i = 0; i < N; i++) { 3631 PetscCall(MatDenseGetColumnVecRead(B, i, &b)); 3632 PetscCall(MatDenseGetColumnVecWrite(X, i, &x)); 3633 PetscCall((*f)(A, b, x)); 3634 PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x)); 3635 PetscCall(MatDenseRestoreColumnVecRead(B, i, &b)); 3636 } 3637 if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B)); 3638 if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X)); 3639 PetscFunctionReturn(PETSC_SUCCESS); 3640 } 3641 3642 /*@ 3643 MatMatSolve - Solves A X = B, given a factored matrix. 3644 3645 Neighbor-wise Collective 3646 3647 Input Parameters: 3648 + A - the factored matrix 3649 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS) 3650 3651 Output Parameter: 3652 . X - the result matrix (dense matrix) 3653 3654 Level: developer 3655 3656 Note: 3657 If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`; 3658 otherwise, `B` and `X` cannot be the same. 3659 3660 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3661 @*/ 3662 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X) 3663 { 3664 PetscFunctionBegin; 3665 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3666 PetscValidType(A, 1); 3667 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3668 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3669 PetscCheckSameComm(A, 1, B, 2); 3670 PetscCheckSameComm(A, 1, X, 3); 3671 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); 3672 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); 3673 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"); 3674 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3675 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3676 MatCheckPreallocated(A, 1); 3677 3678 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3679 if (!A->ops->matsolve) { 3680 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name)); 3681 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE)); 3682 } else PetscUseTypeMethod(A, matsolve, B, X); 3683 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3684 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3685 PetscFunctionReturn(PETSC_SUCCESS); 3686 } 3687 3688 /*@ 3689 MatMatSolveTranspose - Solves A^T X = B, given a factored matrix. 3690 3691 Neighbor-wise Collective 3692 3693 Input Parameters: 3694 + A - the factored matrix 3695 - B - the right-hand-side matrix (`MATDENSE` matrix) 3696 3697 Output Parameter: 3698 . X - the result matrix (dense matrix) 3699 3700 Level: developer 3701 3702 Note: 3703 The matrices `B` and `X` cannot be the same. I.e., one cannot 3704 call `MatMatSolveTranspose`(A,X,X). 3705 3706 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()` 3707 @*/ 3708 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X) 3709 { 3710 PetscFunctionBegin; 3711 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3712 PetscValidType(A, 1); 3713 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3714 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3715 PetscCheckSameComm(A, 1, B, 2); 3716 PetscCheckSameComm(A, 1, X, 3); 3717 PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3718 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); 3719 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); 3720 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); 3721 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"); 3722 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3723 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3724 MatCheckPreallocated(A, 1); 3725 3726 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3727 if (!A->ops->matsolvetranspose) { 3728 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name)); 3729 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE)); 3730 } else PetscUseTypeMethod(A, matsolvetranspose, B, X); 3731 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3732 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3733 PetscFunctionReturn(PETSC_SUCCESS); 3734 } 3735 3736 /*@ 3737 MatMatTransposeSolve - Solves A X = B^T, given a factored matrix. 3738 3739 Neighbor-wise Collective 3740 3741 Input Parameters: 3742 + A - the factored matrix 3743 - Bt - the transpose of right-hand-side matrix as a `MATDENSE` 3744 3745 Output Parameter: 3746 . X - the result matrix (dense matrix) 3747 3748 Level: developer 3749 3750 Note: 3751 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 3752 format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`. 3753 3754 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3755 @*/ 3756 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X) 3757 { 3758 PetscFunctionBegin; 3759 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3760 PetscValidType(A, 1); 3761 PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2); 3762 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3763 PetscCheckSameComm(A, 1, Bt, 2); 3764 PetscCheckSameComm(A, 1, X, 3); 3765 3766 PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3767 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); 3768 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); 3769 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"); 3770 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3771 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3772 MatCheckPreallocated(A, 1); 3773 3774 PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0)); 3775 PetscUseTypeMethod(A, mattransposesolve, Bt, X); 3776 PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0)); 3777 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3778 PetscFunctionReturn(PETSC_SUCCESS); 3779 } 3780 3781 /*@ 3782 MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or 3783 U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U, 3784 3785 Neighbor-wise Collective 3786 3787 Input Parameters: 3788 + mat - the factored matrix 3789 - b - the right-hand-side vector 3790 3791 Output Parameter: 3792 . x - the result vector 3793 3794 Level: developer 3795 3796 Notes: 3797 `MatSolve()` should be used for most applications, as it performs 3798 a forward solve followed by a backward solve. 3799 3800 The vectors `b` and `x` cannot be the same, i.e., one cannot 3801 call `MatForwardSolve`(A,x,x). 3802 3803 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3804 the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet. 3805 `MatForwardSolve()` solves U^T*D y = b, and 3806 `MatBackwardSolve()` solves U x = y. 3807 Thus they do not provide a symmetric preconditioner. 3808 3809 .seealso: [](chapter_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatBackwardSolve()` 3810 @*/ 3811 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x) 3812 { 3813 PetscFunctionBegin; 3814 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3815 PetscValidType(mat, 1); 3816 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3817 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3818 PetscCheckSameComm(mat, 1, b, 2); 3819 PetscCheckSameComm(mat, 1, x, 3); 3820 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3821 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); 3822 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); 3823 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); 3824 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3825 MatCheckPreallocated(mat, 1); 3826 3827 PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0)); 3828 PetscUseTypeMethod(mat, forwardsolve, b, x); 3829 PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0)); 3830 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3831 PetscFunctionReturn(PETSC_SUCCESS); 3832 } 3833 3834 /*@ 3835 MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU. 3836 D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U, 3837 3838 Neighbor-wise Collective 3839 3840 Input Parameters: 3841 + mat - the factored matrix 3842 - b - the right-hand-side vector 3843 3844 Output Parameter: 3845 . x - the result vector 3846 3847 Level: developer 3848 3849 Notes: 3850 `MatSolve()` should be used for most applications, as it performs 3851 a forward solve followed by a backward solve. 3852 3853 The vectors `b` and `x` cannot be the same. I.e., one cannot 3854 call `MatBackwardSolve`(A,x,x). 3855 3856 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3857 the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet. 3858 `MatForwardSolve()` solves U^T*D y = b, and 3859 `MatBackwardSolve()` solves U x = y. 3860 Thus they do not provide a symmetric preconditioner. 3861 3862 .seealso: [](chapter_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatForwardSolve()` 3863 @*/ 3864 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x) 3865 { 3866 PetscFunctionBegin; 3867 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3868 PetscValidType(mat, 1); 3869 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3870 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3871 PetscCheckSameComm(mat, 1, b, 2); 3872 PetscCheckSameComm(mat, 1, x, 3); 3873 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3874 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); 3875 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); 3876 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); 3877 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3878 MatCheckPreallocated(mat, 1); 3879 3880 PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0)); 3881 PetscUseTypeMethod(mat, backwardsolve, b, x); 3882 PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0)); 3883 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3884 PetscFunctionReturn(PETSC_SUCCESS); 3885 } 3886 3887 /*@ 3888 MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix. 3889 3890 Neighbor-wise Collective 3891 3892 Input Parameters: 3893 + mat - the factored matrix 3894 . b - the right-hand-side vector 3895 - y - the vector to be added to 3896 3897 Output Parameter: 3898 . x - the result vector 3899 3900 Level: developer 3901 3902 Note: 3903 The vectors `b` and `x` cannot be the same. I.e., one cannot 3904 call `MatSolveAdd`(A,x,y,x). 3905 3906 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3907 @*/ 3908 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x) 3909 { 3910 PetscScalar one = 1.0; 3911 Vec tmp; 3912 3913 PetscFunctionBegin; 3914 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3915 PetscValidType(mat, 1); 3916 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 3917 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3918 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 3919 PetscCheckSameComm(mat, 1, b, 2); 3920 PetscCheckSameComm(mat, 1, y, 3); 3921 PetscCheckSameComm(mat, 1, x, 4); 3922 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3923 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); 3924 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); 3925 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); 3926 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); 3927 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); 3928 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3929 MatCheckPreallocated(mat, 1); 3930 3931 PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y)); 3932 if (mat->factorerrortype) { 3933 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3934 PetscCall(VecSetInf(x)); 3935 } else if (mat->ops->solveadd) { 3936 PetscUseTypeMethod(mat, solveadd, b, y, x); 3937 } else { 3938 /* do the solve then the add manually */ 3939 if (x != y) { 3940 PetscCall(MatSolve(mat, b, x)); 3941 PetscCall(VecAXPY(x, one, y)); 3942 } else { 3943 PetscCall(VecDuplicate(x, &tmp)); 3944 PetscCall(VecCopy(x, tmp)); 3945 PetscCall(MatSolve(mat, b, x)); 3946 PetscCall(VecAXPY(x, one, tmp)); 3947 PetscCall(VecDestroy(&tmp)); 3948 } 3949 } 3950 PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y)); 3951 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3952 PetscFunctionReturn(PETSC_SUCCESS); 3953 } 3954 3955 /*@ 3956 MatSolveTranspose - Solves A' x = b, given a factored matrix. 3957 3958 Neighbor-wise Collective 3959 3960 Input Parameters: 3961 + mat - the factored matrix 3962 - b - the right-hand-side vector 3963 3964 Output Parameter: 3965 . x - the result vector 3966 3967 Level: developer 3968 3969 Notes: 3970 The vectors `b` and `x` cannot be the same. I.e., one cannot 3971 call `MatSolveTranspose`(A,x,x). 3972 3973 Most users should employ the `KSP` interface for linear solvers 3974 instead of working directly with matrix algebra routines such as this. 3975 See, e.g., `KSPCreate()`. 3976 3977 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()` 3978 @*/ 3979 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x) 3980 { 3981 PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose; 3982 3983 PetscFunctionBegin; 3984 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3985 PetscValidType(mat, 1); 3986 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3987 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3988 PetscCheckSameComm(mat, 1, b, 2); 3989 PetscCheckSameComm(mat, 1, x, 3); 3990 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3991 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); 3992 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); 3993 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3994 MatCheckPreallocated(mat, 1); 3995 PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0)); 3996 if (mat->factorerrortype) { 3997 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3998 PetscCall(VecSetInf(x)); 3999 } else { 4000 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name); 4001 PetscCall((*f)(mat, b, x)); 4002 } 4003 PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0)); 4004 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4005 PetscFunctionReturn(PETSC_SUCCESS); 4006 } 4007 4008 /*@ 4009 MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a 4010 factored matrix. 4011 4012 Neighbor-wise Collective 4013 4014 Input Parameters: 4015 + mat - the factored matrix 4016 . b - the right-hand-side vector 4017 - y - the vector to be added to 4018 4019 Output Parameter: 4020 . x - the result vector 4021 4022 Level: developer 4023 4024 Note: 4025 The vectors `b` and `x` cannot be the same. I.e., one cannot 4026 call `MatSolveTransposeAdd`(A,x,y,x). 4027 4028 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()` 4029 @*/ 4030 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x) 4031 { 4032 PetscScalar one = 1.0; 4033 Vec tmp; 4034 PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd; 4035 4036 PetscFunctionBegin; 4037 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4038 PetscValidType(mat, 1); 4039 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4040 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4041 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4042 PetscCheckSameComm(mat, 1, b, 2); 4043 PetscCheckSameComm(mat, 1, y, 3); 4044 PetscCheckSameComm(mat, 1, x, 4); 4045 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4046 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); 4047 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); 4048 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); 4049 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); 4050 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4051 MatCheckPreallocated(mat, 1); 4052 4053 PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y)); 4054 if (mat->factorerrortype) { 4055 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4056 PetscCall(VecSetInf(x)); 4057 } else if (f) { 4058 PetscCall((*f)(mat, b, y, x)); 4059 } else { 4060 /* do the solve then the add manually */ 4061 if (x != y) { 4062 PetscCall(MatSolveTranspose(mat, b, x)); 4063 PetscCall(VecAXPY(x, one, y)); 4064 } else { 4065 PetscCall(VecDuplicate(x, &tmp)); 4066 PetscCall(VecCopy(x, tmp)); 4067 PetscCall(MatSolveTranspose(mat, b, x)); 4068 PetscCall(VecAXPY(x, one, tmp)); 4069 PetscCall(VecDestroy(&tmp)); 4070 } 4071 } 4072 PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y)); 4073 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4074 PetscFunctionReturn(PETSC_SUCCESS); 4075 } 4076 4077 /*@ 4078 MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps. 4079 4080 Neighbor-wise Collective 4081 4082 Input Parameters: 4083 + mat - the matrix 4084 . b - the right hand side 4085 . omega - the relaxation factor 4086 . flag - flag indicating the type of SOR (see below) 4087 . shift - diagonal shift 4088 . its - the number of iterations 4089 - lits - the number of local iterations 4090 4091 Output Parameter: 4092 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess) 4093 4094 SOR Flags: 4095 + `SOR_FORWARD_SWEEP` - forward SOR 4096 . `SOR_BACKWARD_SWEEP` - backward SOR 4097 . `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR) 4098 . `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR 4099 . `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR 4100 . `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR 4101 . `SOR_EISENSTAT` - SOR with Eisenstat trick 4102 . `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies 4103 upper/lower triangular part of matrix to 4104 vector (with omega) 4105 - `SOR_ZERO_INITIAL_GUESS` - zero initial guess 4106 4107 Level: developer 4108 4109 Notes: 4110 `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and 4111 `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings 4112 on each processor. 4113 4114 Application programmers will not generally use `MatSOR()` directly, 4115 but instead will employ the `KSP`/`PC` interface. 4116 4117 For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing 4118 4119 Most users should employ the `KSP` interface for linear solvers 4120 instead of working directly with matrix algebra routines such as this. 4121 See, e.g., `KSPCreate()`. 4122 4123 Vectors `x` and `b` CANNOT be the same 4124 4125 The flags are implemented as bitwise inclusive or operations. 4126 For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`) 4127 to specify a zero initial guess for SSOR. 4128 4129 Developer Note: 4130 We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes 4131 4132 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()` 4133 @*/ 4134 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x) 4135 { 4136 PetscFunctionBegin; 4137 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4138 PetscValidType(mat, 1); 4139 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4140 PetscValidHeaderSpecific(x, VEC_CLASSID, 8); 4141 PetscCheckSameComm(mat, 1, b, 2); 4142 PetscCheckSameComm(mat, 1, x, 8); 4143 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4144 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4145 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); 4146 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); 4147 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); 4148 PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its); 4149 PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits); 4150 PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same"); 4151 4152 MatCheckPreallocated(mat, 1); 4153 PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0)); 4154 PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x); 4155 PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0)); 4156 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4157 PetscFunctionReturn(PETSC_SUCCESS); 4158 } 4159 4160 /* 4161 Default matrix copy routine. 4162 */ 4163 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str) 4164 { 4165 PetscInt i, rstart = 0, rend = 0, nz; 4166 const PetscInt *cwork; 4167 const PetscScalar *vwork; 4168 4169 PetscFunctionBegin; 4170 if (B->assembled) PetscCall(MatZeroEntries(B)); 4171 if (str == SAME_NONZERO_PATTERN) { 4172 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 4173 for (i = rstart; i < rend; i++) { 4174 PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork)); 4175 PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES)); 4176 PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork)); 4177 } 4178 } else { 4179 PetscCall(MatAYPX(B, 0.0, A, str)); 4180 } 4181 PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 4182 PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 4183 PetscFunctionReturn(PETSC_SUCCESS); 4184 } 4185 4186 /*@ 4187 MatCopy - Copies a matrix to another matrix. 4188 4189 Collective 4190 4191 Input Parameters: 4192 + A - the matrix 4193 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN` 4194 4195 Output Parameter: 4196 . B - where the copy is put 4197 4198 Level: intermediate 4199 4200 Notes: 4201 If you use `SAME_NONZERO_PATTERN` then the two matrices must have the same nonzero pattern or the routine will crash. 4202 4203 `MatCopy()` copies the matrix entries of a matrix to another existing 4204 matrix (after first zeroing the second matrix). A related routine is 4205 `MatConvert()`, which first creates a new matrix and then copies the data. 4206 4207 .seealso: [](chapter_matrices), `Mat`, `MatConvert()`, `MatDuplicate()` 4208 @*/ 4209 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str) 4210 { 4211 PetscInt i; 4212 4213 PetscFunctionBegin; 4214 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 4215 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 4216 PetscValidType(A, 1); 4217 PetscValidType(B, 2); 4218 PetscCheckSameComm(A, 1, B, 2); 4219 MatCheckPreallocated(B, 2); 4220 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4221 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4222 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, 4223 A->cmap->N, B->cmap->N); 4224 MatCheckPreallocated(A, 1); 4225 if (A == B) PetscFunctionReturn(PETSC_SUCCESS); 4226 4227 PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0)); 4228 if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str); 4229 else PetscCall(MatCopy_Basic(A, B, str)); 4230 4231 B->stencil.dim = A->stencil.dim; 4232 B->stencil.noc = A->stencil.noc; 4233 for (i = 0; i <= A->stencil.dim; i++) { 4234 B->stencil.dims[i] = A->stencil.dims[i]; 4235 B->stencil.starts[i] = A->stencil.starts[i]; 4236 } 4237 4238 PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0)); 4239 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4240 PetscFunctionReturn(PETSC_SUCCESS); 4241 } 4242 4243 /*@C 4244 MatConvert - Converts a matrix to another matrix, either of the same 4245 or different type. 4246 4247 Collective 4248 4249 Input Parameters: 4250 + mat - the matrix 4251 . newtype - new matrix type. Use `MATSAME` to create a new matrix of the 4252 same type as the original matrix. 4253 - reuse - denotes if the destination matrix is to be created or reused. 4254 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 4255 `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). 4256 4257 Output Parameter: 4258 . M - pointer to place new matrix 4259 4260 Level: intermediate 4261 4262 Notes: 4263 `MatConvert()` first creates a new matrix and then copies the data from 4264 the first matrix. A related routine is `MatCopy()`, which copies the matrix 4265 entries of one matrix to another already existing matrix context. 4266 4267 Cannot be used to convert a sequential matrix to parallel or parallel to sequential, 4268 the MPI communicator of the generated matrix is always the same as the communicator 4269 of the input matrix. 4270 4271 .seealso: [](chapter_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 4272 @*/ 4273 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M) 4274 { 4275 PetscBool sametype, issame, flg; 4276 PetscBool3 issymmetric, ishermitian; 4277 char convname[256], mtype[256]; 4278 Mat B; 4279 4280 PetscFunctionBegin; 4281 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4282 PetscValidType(mat, 1); 4283 PetscValidPointer(M, 4); 4284 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4285 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4286 MatCheckPreallocated(mat, 1); 4287 4288 PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg)); 4289 if (flg) newtype = mtype; 4290 4291 PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype)); 4292 PetscCall(PetscStrcmp(newtype, "same", &issame)); 4293 PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix"); 4294 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"); 4295 4296 if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) { 4297 PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4298 PetscFunctionReturn(PETSC_SUCCESS); 4299 } 4300 4301 /* Cache Mat options because some converters use MatHeaderReplace */ 4302 issymmetric = mat->symmetric; 4303 ishermitian = mat->hermitian; 4304 4305 if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) { 4306 PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4307 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4308 } else { 4309 PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL; 4310 const char *prefix[3] = {"seq", "mpi", ""}; 4311 PetscInt i; 4312 /* 4313 Order of precedence: 4314 0) See if newtype is a superclass of the current matrix. 4315 1) See if a specialized converter is known to the current matrix. 4316 2) See if a specialized converter is known to the desired matrix class. 4317 3) See if a good general converter is registered for the desired class 4318 (as of 6/27/03 only MATMPIADJ falls into this category). 4319 4) See if a good general converter is known for the current matrix. 4320 5) Use a really basic converter. 4321 */ 4322 4323 /* 0) See if newtype is a superclass of the current matrix. 4324 i.e mat is mpiaij and newtype is aij */ 4325 for (i = 0; i < 2; i++) { 4326 PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname))); 4327 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4328 PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg)); 4329 PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg)); 4330 if (flg) { 4331 if (reuse == MAT_INPLACE_MATRIX) { 4332 PetscCall(PetscInfo(mat, "Early return\n")); 4333 PetscFunctionReturn(PETSC_SUCCESS); 4334 } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) { 4335 PetscCall(PetscInfo(mat, "Calling MatDuplicate\n")); 4336 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4337 PetscFunctionReturn(PETSC_SUCCESS); 4338 } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) { 4339 PetscCall(PetscInfo(mat, "Calling MatCopy\n")); 4340 PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN)); 4341 PetscFunctionReturn(PETSC_SUCCESS); 4342 } 4343 } 4344 } 4345 /* 1) See if a specialized converter is known to the current matrix and the desired class */ 4346 for (i = 0; i < 3; i++) { 4347 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4348 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4349 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4350 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4351 PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname))); 4352 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4353 PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv)); 4354 PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv)); 4355 if (conv) goto foundconv; 4356 } 4357 4358 /* 2) See if a specialized converter is known to the desired matrix class. */ 4359 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B)); 4360 PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 4361 PetscCall(MatSetType(B, newtype)); 4362 for (i = 0; i < 3; i++) { 4363 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4364 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4365 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4366 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4367 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4368 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4369 PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv)); 4370 PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv)); 4371 if (conv) { 4372 PetscCall(MatDestroy(&B)); 4373 goto foundconv; 4374 } 4375 } 4376 4377 /* 3) See if a good general converter is registered for the desired class */ 4378 conv = B->ops->convertfrom; 4379 PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv)); 4380 PetscCall(MatDestroy(&B)); 4381 if (conv) goto foundconv; 4382 4383 /* 4) See if a good general converter is known for the current matrix */ 4384 if (mat->ops->convert) conv = mat->ops->convert; 4385 PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv)); 4386 if (conv) goto foundconv; 4387 4388 /* 5) Use a really basic converter. */ 4389 PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n")); 4390 conv = MatConvert_Basic; 4391 4392 foundconv: 4393 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4394 PetscCall((*conv)(mat, newtype, reuse, M)); 4395 if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) { 4396 /* the block sizes must be same if the mappings are copied over */ 4397 (*M)->rmap->bs = mat->rmap->bs; 4398 (*M)->cmap->bs = mat->cmap->bs; 4399 PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping)); 4400 PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping)); 4401 (*M)->rmap->mapping = mat->rmap->mapping; 4402 (*M)->cmap->mapping = mat->cmap->mapping; 4403 } 4404 (*M)->stencil.dim = mat->stencil.dim; 4405 (*M)->stencil.noc = mat->stencil.noc; 4406 for (i = 0; i <= mat->stencil.dim; i++) { 4407 (*M)->stencil.dims[i] = mat->stencil.dims[i]; 4408 (*M)->stencil.starts[i] = mat->stencil.starts[i]; 4409 } 4410 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4411 } 4412 PetscCall(PetscObjectStateIncrease((PetscObject)*M)); 4413 4414 /* Copy Mat options */ 4415 if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE)); 4416 else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE)); 4417 if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE)); 4418 else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE)); 4419 PetscFunctionReturn(PETSC_SUCCESS); 4420 } 4421 4422 /*@C 4423 MatFactorGetSolverType - Returns name of the package providing the factorization routines 4424 4425 Not Collective 4426 4427 Input Parameter: 4428 . mat - the matrix, must be a factored matrix 4429 4430 Output Parameter: 4431 . type - the string name of the package (do not free this string) 4432 4433 Level: intermediate 4434 4435 Fortran Note: 4436 Pass in an empty string and the package name will be copied into it. Make sure the string is long enough. 4437 4438 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()` 4439 @*/ 4440 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type) 4441 { 4442 PetscErrorCode (*conv)(Mat, MatSolverType *); 4443 4444 PetscFunctionBegin; 4445 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4446 PetscValidType(mat, 1); 4447 PetscValidPointer(type, 2); 4448 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 4449 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv)); 4450 if (conv) PetscCall((*conv)(mat, type)); 4451 else *type = MATSOLVERPETSC; 4452 PetscFunctionReturn(PETSC_SUCCESS); 4453 } 4454 4455 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType; 4456 struct _MatSolverTypeForSpecifcType { 4457 MatType mtype; 4458 /* no entry for MAT_FACTOR_NONE */ 4459 PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *); 4460 MatSolverTypeForSpecifcType next; 4461 }; 4462 4463 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder; 4464 struct _MatSolverTypeHolder { 4465 char *name; 4466 MatSolverTypeForSpecifcType handlers; 4467 MatSolverTypeHolder next; 4468 }; 4469 4470 static MatSolverTypeHolder MatSolverTypeHolders = NULL; 4471 4472 /*@C 4473 MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type 4474 4475 Input Parameters: 4476 + package - name of the package, for example petsc or superlu 4477 . mtype - the matrix type that works with this package 4478 . ftype - the type of factorization supported by the package 4479 - createfactor - routine that will create the factored matrix ready to be used 4480 4481 Level: developer 4482 4483 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()` 4484 @*/ 4485 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *)) 4486 { 4487 MatSolverTypeHolder next = MatSolverTypeHolders, prev = NULL; 4488 PetscBool flg; 4489 MatSolverTypeForSpecifcType inext, iprev = NULL; 4490 4491 PetscFunctionBegin; 4492 PetscCall(MatInitializePackage()); 4493 if (!next) { 4494 PetscCall(PetscNew(&MatSolverTypeHolders)); 4495 PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name)); 4496 PetscCall(PetscNew(&MatSolverTypeHolders->handlers)); 4497 PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype)); 4498 MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor; 4499 PetscFunctionReturn(PETSC_SUCCESS); 4500 } 4501 while (next) { 4502 PetscCall(PetscStrcasecmp(package, next->name, &flg)); 4503 if (flg) { 4504 PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers"); 4505 inext = next->handlers; 4506 while (inext) { 4507 PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg)); 4508 if (flg) { 4509 inext->createfactor[(int)ftype - 1] = createfactor; 4510 PetscFunctionReturn(PETSC_SUCCESS); 4511 } 4512 iprev = inext; 4513 inext = inext->next; 4514 } 4515 PetscCall(PetscNew(&iprev->next)); 4516 PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype)); 4517 iprev->next->createfactor[(int)ftype - 1] = createfactor; 4518 PetscFunctionReturn(PETSC_SUCCESS); 4519 } 4520 prev = next; 4521 next = next->next; 4522 } 4523 PetscCall(PetscNew(&prev->next)); 4524 PetscCall(PetscStrallocpy(package, &prev->next->name)); 4525 PetscCall(PetscNew(&prev->next->handlers)); 4526 PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype)); 4527 prev->next->handlers->createfactor[(int)ftype - 1] = createfactor; 4528 PetscFunctionReturn(PETSC_SUCCESS); 4529 } 4530 4531 /*@C 4532 MatSolverTypeGet - Gets the function that creates the factor matrix if it exist 4533 4534 Input Parameters: 4535 + type - name of the package, for example petsc or superlu 4536 . ftype - the type of factorization supported by the type 4537 - mtype - the matrix type that works with this type 4538 4539 Output Parameters: 4540 + foundtype - `PETSC_TRUE` if the type was registered 4541 . foundmtype - `PETSC_TRUE` if the type supports the requested mtype 4542 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found 4543 4544 Level: developer 4545 4546 .seealso: [](chapter_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()` 4547 @*/ 4548 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *)) 4549 { 4550 MatSolverTypeHolder next = MatSolverTypeHolders; 4551 PetscBool flg; 4552 MatSolverTypeForSpecifcType inext; 4553 4554 PetscFunctionBegin; 4555 if (foundtype) *foundtype = PETSC_FALSE; 4556 if (foundmtype) *foundmtype = PETSC_FALSE; 4557 if (createfactor) *createfactor = NULL; 4558 4559 if (type) { 4560 while (next) { 4561 PetscCall(PetscStrcasecmp(type, next->name, &flg)); 4562 if (flg) { 4563 if (foundtype) *foundtype = PETSC_TRUE; 4564 inext = next->handlers; 4565 while (inext) { 4566 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4567 if (flg) { 4568 if (foundmtype) *foundmtype = PETSC_TRUE; 4569 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4570 PetscFunctionReturn(PETSC_SUCCESS); 4571 } 4572 inext = inext->next; 4573 } 4574 } 4575 next = next->next; 4576 } 4577 } else { 4578 while (next) { 4579 inext = next->handlers; 4580 while (inext) { 4581 PetscCall(PetscStrcmp(mtype, inext->mtype, &flg)); 4582 if (flg && inext->createfactor[(int)ftype - 1]) { 4583 if (foundtype) *foundtype = PETSC_TRUE; 4584 if (foundmtype) *foundmtype = PETSC_TRUE; 4585 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4586 PetscFunctionReturn(PETSC_SUCCESS); 4587 } 4588 inext = inext->next; 4589 } 4590 next = next->next; 4591 } 4592 /* try with base classes inext->mtype */ 4593 next = MatSolverTypeHolders; 4594 while (next) { 4595 inext = next->handlers; 4596 while (inext) { 4597 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4598 if (flg && inext->createfactor[(int)ftype - 1]) { 4599 if (foundtype) *foundtype = PETSC_TRUE; 4600 if (foundmtype) *foundmtype = PETSC_TRUE; 4601 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4602 PetscFunctionReturn(PETSC_SUCCESS); 4603 } 4604 inext = inext->next; 4605 } 4606 next = next->next; 4607 } 4608 } 4609 PetscFunctionReturn(PETSC_SUCCESS); 4610 } 4611 4612 PetscErrorCode MatSolverTypeDestroy(void) 4613 { 4614 MatSolverTypeHolder next = MatSolverTypeHolders, prev; 4615 MatSolverTypeForSpecifcType inext, iprev; 4616 4617 PetscFunctionBegin; 4618 while (next) { 4619 PetscCall(PetscFree(next->name)); 4620 inext = next->handlers; 4621 while (inext) { 4622 PetscCall(PetscFree(inext->mtype)); 4623 iprev = inext; 4624 inext = inext->next; 4625 PetscCall(PetscFree(iprev)); 4626 } 4627 prev = next; 4628 next = next->next; 4629 PetscCall(PetscFree(prev)); 4630 } 4631 MatSolverTypeHolders = NULL; 4632 PetscFunctionReturn(PETSC_SUCCESS); 4633 } 4634 4635 /*@C 4636 MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4637 4638 Logically Collective 4639 4640 Input Parameter: 4641 . mat - the matrix 4642 4643 Output Parameter: 4644 . flg - `PETSC_TRUE` if uses the ordering 4645 4646 Level: developer 4647 4648 Note: 4649 Most internal PETSc factorizations use the ordering passed to the factorization routine but external 4650 packages do not, thus we want to skip generating the ordering when it is not needed or used. 4651 4652 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4653 @*/ 4654 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg) 4655 { 4656 PetscFunctionBegin; 4657 *flg = mat->canuseordering; 4658 PetscFunctionReturn(PETSC_SUCCESS); 4659 } 4660 4661 /*@C 4662 MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object 4663 4664 Logically Collective 4665 4666 Input Parameters: 4667 + mat - the matrix obtained with `MatGetFactor()` 4668 - ftype - the factorization type to be used 4669 4670 Output Parameter: 4671 . otype - the preferred ordering type 4672 4673 Level: developer 4674 4675 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4676 @*/ 4677 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype) 4678 { 4679 PetscFunctionBegin; 4680 *otype = mat->preferredordering[ftype]; 4681 PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering"); 4682 PetscFunctionReturn(PETSC_SUCCESS); 4683 } 4684 4685 /*@C 4686 MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic() 4687 4688 Collective 4689 4690 Input Parameters: 4691 + mat - the matrix 4692 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4693 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4694 4695 Output Parameter: 4696 . f - the factor matrix used with MatXXFactorSymbolic() calls. Can be `NULL` in some cases, see notes below. 4697 4698 Options Database Key: 4699 . -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory. 4700 One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices. 4701 4702 Level: intermediate 4703 4704 Notes: 4705 The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization 4706 types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime. 4707 4708 Users usually access the factorization solvers via `KSP` 4709 4710 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4711 such as pastix, superlu, mumps etc. 4712 4713 PETSc must have been ./configure to use the external solver, using the option --download-package 4714 4715 Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption 4716 where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set 4717 call `MatSetOptionsPrefixFactor()` on the originating matrix or `MatSetOptionsPrefix()` on the resulting factor matrix. 4718 4719 Developer Note: 4720 This should actually be called `MatCreateFactor()` since it creates a new factor object 4721 4722 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, 4723 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4724 @*/ 4725 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f) 4726 { 4727 PetscBool foundtype, foundmtype; 4728 PetscErrorCode (*conv)(Mat, MatFactorType, Mat *); 4729 4730 PetscFunctionBegin; 4731 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4732 PetscValidType(mat, 1); 4733 4734 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4735 MatCheckPreallocated(mat, 1); 4736 4737 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv)); 4738 if (!foundtype) { 4739 if (type) { 4740 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], 4741 ((PetscObject)mat)->type_name, type); 4742 } else { 4743 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); 4744 } 4745 } 4746 PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name); 4747 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); 4748 4749 PetscCall((*conv)(mat, ftype, f)); 4750 if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix)); 4751 PetscFunctionReturn(PETSC_SUCCESS); 4752 } 4753 4754 /*@C 4755 MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type 4756 4757 Not Collective 4758 4759 Input Parameters: 4760 + mat - the matrix 4761 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4762 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4763 4764 Output Parameter: 4765 . flg - PETSC_TRUE if the factorization is available 4766 4767 Level: intermediate 4768 4769 Notes: 4770 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4771 such as pastix, superlu, mumps etc. 4772 4773 PETSc must have been ./configure to use the external solver, using the option --download-package 4774 4775 Developer Note: 4776 This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object 4777 4778 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactor()`, `MatSolverTypeRegister()`, 4779 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4780 @*/ 4781 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg) 4782 { 4783 PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *); 4784 4785 PetscFunctionBegin; 4786 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4787 PetscValidType(mat, 1); 4788 PetscValidBoolPointer(flg, 4); 4789 4790 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4791 MatCheckPreallocated(mat, 1); 4792 4793 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv)); 4794 *flg = gconv ? PETSC_TRUE : PETSC_FALSE; 4795 PetscFunctionReturn(PETSC_SUCCESS); 4796 } 4797 4798 /*@ 4799 MatDuplicate - Duplicates a matrix including the non-zero structure. 4800 4801 Collective 4802 4803 Input Parameters: 4804 + mat - the matrix 4805 - op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`. 4806 See the manual page for `MatDuplicateOption()` for an explanation of these options. 4807 4808 Output Parameter: 4809 . M - pointer to place new matrix 4810 4811 Level: intermediate 4812 4813 Notes: 4814 You cannot change the nonzero pattern for the parent or child matrix if you use `MAT_SHARE_NONZERO_PATTERN`. 4815 4816 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. 4817 4818 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 4819 is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated. 4820 User should not use `MatDuplicate()` to create new matrix M if M is intended to be reused as the product of matrix operation. 4821 4822 .seealso: [](chapter_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption` 4823 @*/ 4824 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M) 4825 { 4826 Mat B; 4827 VecType vtype; 4828 PetscInt i; 4829 PetscObject dm; 4830 void (*viewf)(void); 4831 4832 PetscFunctionBegin; 4833 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4834 PetscValidType(mat, 1); 4835 PetscValidPointer(M, 3); 4836 PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix"); 4837 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4838 MatCheckPreallocated(mat, 1); 4839 4840 *M = NULL; 4841 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4842 PetscUseTypeMethod(mat, duplicate, op, M); 4843 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4844 B = *M; 4845 4846 PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf)); 4847 if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf)); 4848 PetscCall(MatGetVecType(mat, &vtype)); 4849 PetscCall(MatSetVecType(B, vtype)); 4850 4851 B->stencil.dim = mat->stencil.dim; 4852 B->stencil.noc = mat->stencil.noc; 4853 for (i = 0; i <= mat->stencil.dim; i++) { 4854 B->stencil.dims[i] = mat->stencil.dims[i]; 4855 B->stencil.starts[i] = mat->stencil.starts[i]; 4856 } 4857 4858 B->nooffproczerorows = mat->nooffproczerorows; 4859 B->nooffprocentries = mat->nooffprocentries; 4860 4861 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm)); 4862 if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm)); 4863 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4864 PetscFunctionReturn(PETSC_SUCCESS); 4865 } 4866 4867 /*@ 4868 MatGetDiagonal - Gets the diagonal of a matrix as a `Vec` 4869 4870 Logically Collective 4871 4872 Input Parameter: 4873 . mat - the matrix 4874 4875 Output Parameter: 4876 . v - the diagonal of the matrix 4877 4878 Level: intermediate 4879 4880 Note: 4881 Currently only correct in parallel for square matrices. 4882 4883 .seealso: [](chapter_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()` 4884 @*/ 4885 PetscErrorCode MatGetDiagonal(Mat mat, Vec v) 4886 { 4887 PetscFunctionBegin; 4888 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4889 PetscValidType(mat, 1); 4890 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4891 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4892 MatCheckPreallocated(mat, 1); 4893 4894 PetscUseTypeMethod(mat, getdiagonal, v); 4895 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4896 PetscFunctionReturn(PETSC_SUCCESS); 4897 } 4898 4899 /*@C 4900 MatGetRowMin - Gets the minimum value (of the real part) of each 4901 row of the matrix 4902 4903 Logically Collective 4904 4905 Input Parameter: 4906 . mat - the matrix 4907 4908 Output Parameters: 4909 + v - the vector for storing the maximums 4910 - idx - the indices of the column found for each row (optional) 4911 4912 Level: intermediate 4913 4914 Note: 4915 The result of this call are the same as if one converted the matrix to dense format 4916 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 4917 4918 This code is only implemented for a couple of matrix formats. 4919 4920 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, 4921 `MatGetRowMax()` 4922 @*/ 4923 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[]) 4924 { 4925 PetscFunctionBegin; 4926 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4927 PetscValidType(mat, 1); 4928 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4929 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4930 4931 if (!mat->cmap->N) { 4932 PetscCall(VecSet(v, PETSC_MAX_REAL)); 4933 if (idx) { 4934 PetscInt i, m = mat->rmap->n; 4935 for (i = 0; i < m; i++) idx[i] = -1; 4936 } 4937 } else { 4938 MatCheckPreallocated(mat, 1); 4939 } 4940 PetscUseTypeMethod(mat, getrowmin, v, idx); 4941 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4942 PetscFunctionReturn(PETSC_SUCCESS); 4943 } 4944 4945 /*@C 4946 MatGetRowMinAbs - Gets the minimum value (in absolute value) of each 4947 row of the matrix 4948 4949 Logically Collective 4950 4951 Input Parameter: 4952 . mat - the matrix 4953 4954 Output Parameters: 4955 + v - the vector for storing the minimums 4956 - idx - the indices of the column found for each row (or `NULL` if not needed) 4957 4958 Level: intermediate 4959 4960 Notes: 4961 if a row is completely empty or has only 0.0 values then the idx[] value for that 4962 row is 0 (the first column). 4963 4964 This code is only implemented for a couple of matrix formats. 4965 4966 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()` 4967 @*/ 4968 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[]) 4969 { 4970 PetscFunctionBegin; 4971 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4972 PetscValidType(mat, 1); 4973 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4974 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4975 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4976 4977 if (!mat->cmap->N) { 4978 PetscCall(VecSet(v, 0.0)); 4979 if (idx) { 4980 PetscInt i, m = mat->rmap->n; 4981 for (i = 0; i < m; i++) idx[i] = -1; 4982 } 4983 } else { 4984 MatCheckPreallocated(mat, 1); 4985 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 4986 PetscUseTypeMethod(mat, getrowminabs, v, idx); 4987 } 4988 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4989 PetscFunctionReturn(PETSC_SUCCESS); 4990 } 4991 4992 /*@C 4993 MatGetRowMax - Gets the maximum value (of the real part) of each 4994 row of the matrix 4995 4996 Logically Collective 4997 4998 Input Parameter: 4999 . mat - the matrix 5000 5001 Output Parameters: 5002 + v - the vector for storing the maximums 5003 - idx - the indices of the column found for each row (optional) 5004 5005 Level: intermediate 5006 5007 Notes: 5008 The result of this call are the same as if one converted the matrix to dense format 5009 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5010 5011 This code is only implemented for a couple of matrix formats. 5012 5013 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5014 @*/ 5015 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[]) 5016 { 5017 PetscFunctionBegin; 5018 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5019 PetscValidType(mat, 1); 5020 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5021 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5022 5023 if (!mat->cmap->N) { 5024 PetscCall(VecSet(v, PETSC_MIN_REAL)); 5025 if (idx) { 5026 PetscInt i, m = mat->rmap->n; 5027 for (i = 0; i < m; i++) idx[i] = -1; 5028 } 5029 } else { 5030 MatCheckPreallocated(mat, 1); 5031 PetscUseTypeMethod(mat, getrowmax, v, idx); 5032 } 5033 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5034 PetscFunctionReturn(PETSC_SUCCESS); 5035 } 5036 5037 /*@C 5038 MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each 5039 row of the matrix 5040 5041 Logically Collective 5042 5043 Input Parameter: 5044 . mat - the matrix 5045 5046 Output Parameters: 5047 + v - the vector for storing the maximums 5048 - idx - the indices of the column found for each row (or `NULL` if not needed) 5049 5050 Level: intermediate 5051 5052 Notes: 5053 if a row is completely empty or has only 0.0 values then the idx[] value for that 5054 row is 0 (the first column). 5055 5056 This code is only implemented for a couple of matrix formats. 5057 5058 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5059 @*/ 5060 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[]) 5061 { 5062 PetscFunctionBegin; 5063 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5064 PetscValidType(mat, 1); 5065 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5066 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5067 5068 if (!mat->cmap->N) { 5069 PetscCall(VecSet(v, 0.0)); 5070 if (idx) { 5071 PetscInt i, m = mat->rmap->n; 5072 for (i = 0; i < m; i++) idx[i] = -1; 5073 } 5074 } else { 5075 MatCheckPreallocated(mat, 1); 5076 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5077 PetscUseTypeMethod(mat, getrowmaxabs, v, idx); 5078 } 5079 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5080 PetscFunctionReturn(PETSC_SUCCESS); 5081 } 5082 5083 /*@ 5084 MatGetRowSum - Gets the sum of each row of the matrix 5085 5086 Logically or Neighborhood Collective 5087 5088 Input Parameter: 5089 . mat - the matrix 5090 5091 Output Parameter: 5092 . v - the vector for storing the sum of rows 5093 5094 Level: intermediate 5095 5096 Notes: 5097 This code is slow since it is not currently specialized for different formats 5098 5099 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()` 5100 @*/ 5101 PetscErrorCode MatGetRowSum(Mat mat, Vec v) 5102 { 5103 Vec ones; 5104 5105 PetscFunctionBegin; 5106 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5107 PetscValidType(mat, 1); 5108 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5109 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5110 MatCheckPreallocated(mat, 1); 5111 PetscCall(MatCreateVecs(mat, &ones, NULL)); 5112 PetscCall(VecSet(ones, 1.)); 5113 PetscCall(MatMult(mat, ones, v)); 5114 PetscCall(VecDestroy(&ones)); 5115 PetscFunctionReturn(PETSC_SUCCESS); 5116 } 5117 5118 /*@ 5119 MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) 5120 when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B) 5121 5122 Collective 5123 5124 Input Parameter: 5125 . mat - the matrix to provide the transpose 5126 5127 Output Parameter: 5128 . mat - 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 5129 5130 Level: advanced 5131 5132 Note: 5133 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 5134 routine allows bypassing that call. 5135 5136 .seealso: [](chapter_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5137 @*/ 5138 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B) 5139 { 5140 PetscContainer rB = NULL; 5141 MatParentState *rb = NULL; 5142 5143 PetscFunctionBegin; 5144 PetscCall(PetscNew(&rb)); 5145 rb->id = ((PetscObject)mat)->id; 5146 rb->state = 0; 5147 PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate)); 5148 PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB)); 5149 PetscCall(PetscContainerSetPointer(rB, rb)); 5150 PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault)); 5151 PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB)); 5152 PetscCall(PetscObjectDereference((PetscObject)rB)); 5153 PetscFunctionReturn(PETSC_SUCCESS); 5154 } 5155 5156 /*@ 5157 MatTranspose - Computes an in-place or out-of-place transpose of a matrix. 5158 5159 Collective 5160 5161 Input Parameters: 5162 + mat - the matrix to transpose 5163 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5164 5165 Output Parameter: 5166 . B - the transpose 5167 5168 Level: intermediate 5169 5170 Notes: 5171 If you use `MAT_INPLACE_MATRIX` then you must pass in &mat for B 5172 5173 `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 5174 transpose, call `MatTransposeSetPrecursor`(mat,B) before calling this routine. 5175 5176 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. 5177 5178 Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed. 5179 5180 If mat is unchanged from the last call this function returns immediately without recomputing the result 5181 5182 If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()` 5183 5184 .seealso: [](chapter_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`, 5185 `MatTransposeSymbolic()`, `MatCreateTranspose()` 5186 @*/ 5187 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B) 5188 { 5189 PetscContainer rB = NULL; 5190 MatParentState *rb = NULL; 5191 5192 PetscFunctionBegin; 5193 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5194 PetscValidType(mat, 1); 5195 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5196 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5197 PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first"); 5198 PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX"); 5199 MatCheckPreallocated(mat, 1); 5200 if (reuse == MAT_REUSE_MATRIX) { 5201 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5202 PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor()."); 5203 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5204 PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5205 if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS); 5206 } 5207 5208 PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0)); 5209 if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) { 5210 PetscUseTypeMethod(mat, transpose, reuse, B); 5211 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5212 } 5213 PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0)); 5214 5215 if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B)); 5216 if (reuse != MAT_INPLACE_MATRIX) { 5217 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5218 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5219 rb->state = ((PetscObject)mat)->state; 5220 rb->nonzerostate = mat->nonzerostate; 5221 } 5222 PetscFunctionReturn(PETSC_SUCCESS); 5223 } 5224 5225 /*@ 5226 MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix. 5227 5228 Collective 5229 5230 Input Parameter: 5231 . A - the matrix to transpose 5232 5233 Output Parameter: 5234 . 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 5235 numerical portion. 5236 5237 Level: intermediate 5238 5239 Note: 5240 This is not supported for many matrix types, use `MatTranspose()` in those cases 5241 5242 .seealso: [](chapter_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5243 @*/ 5244 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B) 5245 { 5246 PetscFunctionBegin; 5247 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5248 PetscValidType(A, 1); 5249 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5250 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5251 PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0)); 5252 PetscUseTypeMethod(A, transposesymbolic, B); 5253 PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0)); 5254 5255 PetscCall(MatTransposeSetPrecursor(A, *B)); 5256 PetscFunctionReturn(PETSC_SUCCESS); 5257 } 5258 5259 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B) 5260 { 5261 PetscContainer rB; 5262 MatParentState *rb; 5263 5264 PetscFunctionBegin; 5265 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5266 PetscValidType(A, 1); 5267 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5268 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5269 PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB)); 5270 PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()"); 5271 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5272 PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5273 PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure"); 5274 PetscFunctionReturn(PETSC_SUCCESS); 5275 } 5276 5277 /*@ 5278 MatIsTranspose - Test whether a matrix is another one's transpose, 5279 or its own, in which case it tests symmetry. 5280 5281 Collective 5282 5283 Input Parameters: 5284 + A - the matrix to test 5285 . B - the matrix to test against, this can equal the first parameter 5286 - tol - tolerance, differences between entries smaller than this are counted as zero 5287 5288 Output Parameter: 5289 . flg - the result 5290 5291 Level: intermediate 5292 5293 Notes: 5294 Only available for `MATAIJ` matrices. 5295 5296 The sequential algorithm has a running time of the order of the number of nonzeros; the parallel 5297 test involves parallel copies of the block-offdiagonal parts of the matrix. 5298 5299 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()` 5300 @*/ 5301 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5302 { 5303 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5304 5305 PetscFunctionBegin; 5306 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5307 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5308 PetscValidBoolPointer(flg, 4); 5309 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f)); 5310 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g)); 5311 *flg = PETSC_FALSE; 5312 if (f && g) { 5313 PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test"); 5314 PetscCall((*f)(A, B, tol, flg)); 5315 } else { 5316 MatType mattype; 5317 5318 PetscCall(MatGetType(f ? B : A, &mattype)); 5319 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype); 5320 } 5321 PetscFunctionReturn(PETSC_SUCCESS); 5322 } 5323 5324 /*@ 5325 MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate. 5326 5327 Collective 5328 5329 Input Parameters: 5330 + mat - the matrix to transpose and complex conjugate 5331 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5332 5333 Output Parameter: 5334 . B - the Hermitian transpose 5335 5336 Level: intermediate 5337 5338 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse` 5339 @*/ 5340 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B) 5341 { 5342 PetscFunctionBegin; 5343 PetscCall(MatTranspose(mat, reuse, B)); 5344 #if defined(PETSC_USE_COMPLEX) 5345 PetscCall(MatConjugate(*B)); 5346 #endif 5347 PetscFunctionReturn(PETSC_SUCCESS); 5348 } 5349 5350 /*@ 5351 MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose, 5352 5353 Collective 5354 5355 Input Parameters: 5356 + A - the matrix to test 5357 . B - the matrix to test against, this can equal the first parameter 5358 - tol - tolerance, differences between entries smaller than this are counted as zero 5359 5360 Output Parameter: 5361 . flg - the result 5362 5363 Level: intermediate 5364 5365 Notes: 5366 Only available for `MATAIJ` matrices. 5367 5368 The sequential algorithm 5369 has a running time of the order of the number of nonzeros; the parallel 5370 test involves parallel copies of the block-offdiagonal parts of the matrix. 5371 5372 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()` 5373 @*/ 5374 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5375 { 5376 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5377 5378 PetscFunctionBegin; 5379 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5380 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5381 PetscValidBoolPointer(flg, 4); 5382 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f)); 5383 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g)); 5384 if (f && g) { 5385 PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test"); 5386 PetscCall((*f)(A, B, tol, flg)); 5387 } 5388 PetscFunctionReturn(PETSC_SUCCESS); 5389 } 5390 5391 /*@ 5392 MatPermute - Creates a new matrix with rows and columns permuted from the 5393 original. 5394 5395 Collective 5396 5397 Input Parameters: 5398 + mat - the matrix to permute 5399 . row - row permutation, each processor supplies only the permutation for its rows 5400 - col - column permutation, each processor supplies only the permutation for its columns 5401 5402 Output Parameter: 5403 . B - the permuted matrix 5404 5405 Level: advanced 5406 5407 Note: 5408 The index sets map from row/col of permuted matrix to row/col of original matrix. 5409 The index sets should be on the same communicator as mat and have the same local sizes. 5410 5411 Developer Note: 5412 If you want to implement `MatPermute()` for a matrix type, and your approach doesn't 5413 exploit the fact that row and col are permutations, consider implementing the 5414 more general `MatCreateSubMatrix()` instead. 5415 5416 .seealso: [](chapter_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()` 5417 @*/ 5418 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B) 5419 { 5420 PetscFunctionBegin; 5421 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5422 PetscValidType(mat, 1); 5423 PetscValidHeaderSpecific(row, IS_CLASSID, 2); 5424 PetscValidHeaderSpecific(col, IS_CLASSID, 3); 5425 PetscValidPointer(B, 4); 5426 PetscCheckSameComm(mat, 1, row, 2); 5427 if (row != col) PetscCheckSameComm(row, 2, col, 3); 5428 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5429 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5430 PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name); 5431 MatCheckPreallocated(mat, 1); 5432 5433 if (mat->ops->permute) { 5434 PetscUseTypeMethod(mat, permute, row, col, B); 5435 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5436 } else { 5437 PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B)); 5438 } 5439 PetscFunctionReturn(PETSC_SUCCESS); 5440 } 5441 5442 /*@ 5443 MatEqual - Compares two matrices. 5444 5445 Collective 5446 5447 Input Parameters: 5448 + A - the first matrix 5449 - B - the second matrix 5450 5451 Output Parameter: 5452 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise. 5453 5454 Level: intermediate 5455 5456 .seealso: [](chapter_matrices), `Mat` 5457 @*/ 5458 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg) 5459 { 5460 PetscFunctionBegin; 5461 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5462 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5463 PetscValidType(A, 1); 5464 PetscValidType(B, 2); 5465 PetscValidBoolPointer(flg, 3); 5466 PetscCheckSameComm(A, 1, B, 2); 5467 MatCheckPreallocated(A, 1); 5468 MatCheckPreallocated(B, 2); 5469 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5470 PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5471 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, 5472 B->cmap->N); 5473 if (A->ops->equal && A->ops->equal == B->ops->equal) { 5474 PetscUseTypeMethod(A, equal, B, flg); 5475 } else { 5476 PetscCall(MatMultEqual(A, B, 10, flg)); 5477 } 5478 PetscFunctionReturn(PETSC_SUCCESS); 5479 } 5480 5481 /*@ 5482 MatDiagonalScale - Scales a matrix on the left and right by diagonal 5483 matrices that are stored as vectors. Either of the two scaling 5484 matrices can be `NULL`. 5485 5486 Collective 5487 5488 Input Parameters: 5489 + mat - the matrix to be scaled 5490 . l - the left scaling vector (or `NULL`) 5491 - r - the right scaling vector (or `NULL`) 5492 5493 Level: intermediate 5494 5495 Note: 5496 `MatDiagonalScale()` computes A = LAR, where 5497 L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector) 5498 The L scales the rows of the matrix, the R scales the columns of the matrix. 5499 5500 .seealso: [](chapter_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()` 5501 @*/ 5502 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r) 5503 { 5504 PetscFunctionBegin; 5505 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5506 PetscValidType(mat, 1); 5507 if (l) { 5508 PetscValidHeaderSpecific(l, VEC_CLASSID, 2); 5509 PetscCheckSameComm(mat, 1, l, 2); 5510 } 5511 if (r) { 5512 PetscValidHeaderSpecific(r, VEC_CLASSID, 3); 5513 PetscCheckSameComm(mat, 1, r, 3); 5514 } 5515 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5516 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5517 MatCheckPreallocated(mat, 1); 5518 if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS); 5519 5520 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5521 PetscUseTypeMethod(mat, diagonalscale, l, r); 5522 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5523 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5524 if (l != r) mat->symmetric = PETSC_BOOL3_FALSE; 5525 PetscFunctionReturn(PETSC_SUCCESS); 5526 } 5527 5528 /*@ 5529 MatScale - Scales all elements of a matrix by a given number. 5530 5531 Logically Collective 5532 5533 Input Parameters: 5534 + mat - the matrix to be scaled 5535 - a - the scaling value 5536 5537 Level: intermediate 5538 5539 .seealso: [](chapter_matrices), `Mat`, `MatDiagonalScale()` 5540 @*/ 5541 PetscErrorCode MatScale(Mat mat, PetscScalar a) 5542 { 5543 PetscFunctionBegin; 5544 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5545 PetscValidType(mat, 1); 5546 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5547 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5548 PetscValidLogicalCollectiveScalar(mat, a, 2); 5549 MatCheckPreallocated(mat, 1); 5550 5551 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5552 if (a != (PetscScalar)1.0) { 5553 PetscUseTypeMethod(mat, scale, a); 5554 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5555 } 5556 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5557 PetscFunctionReturn(PETSC_SUCCESS); 5558 } 5559 5560 /*@ 5561 MatNorm - Calculates various norms of a matrix. 5562 5563 Collective 5564 5565 Input Parameters: 5566 + mat - the matrix 5567 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY` 5568 5569 Output Parameter: 5570 . nrm - the resulting norm 5571 5572 Level: intermediate 5573 5574 .seealso: [](chapter_matrices), `Mat` 5575 @*/ 5576 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm) 5577 { 5578 PetscFunctionBegin; 5579 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5580 PetscValidType(mat, 1); 5581 PetscValidRealPointer(nrm, 3); 5582 5583 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5584 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5585 MatCheckPreallocated(mat, 1); 5586 5587 PetscUseTypeMethod(mat, norm, type, nrm); 5588 PetscFunctionReturn(PETSC_SUCCESS); 5589 } 5590 5591 /* 5592 This variable is used to prevent counting of MatAssemblyBegin() that 5593 are called from within a MatAssemblyEnd(). 5594 */ 5595 static PetscInt MatAssemblyEnd_InUse = 0; 5596 /*@ 5597 MatAssemblyBegin - Begins assembling the matrix. This routine should 5598 be called after completing all calls to `MatSetValues()`. 5599 5600 Collective 5601 5602 Input Parameters: 5603 + mat - the matrix 5604 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5605 5606 Level: beginner 5607 5608 Notes: 5609 `MatSetValues()` generally caches the values that belong to other MPI ranks. The matrix is ready to 5610 use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called. 5611 5612 Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES` 5613 in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before 5614 using the matrix. 5615 5616 ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the 5617 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 5618 a global collective operation requiring all processes that share the matrix. 5619 5620 Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed 5621 out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros 5622 before `MAT_FINAL_ASSEMBLY` so the space is not compressed out. 5623 5624 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()` 5625 @*/ 5626 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type) 5627 { 5628 PetscFunctionBegin; 5629 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5630 PetscValidType(mat, 1); 5631 MatCheckPreallocated(mat, 1); 5632 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?"); 5633 if (mat->assembled) { 5634 mat->was_assembled = PETSC_TRUE; 5635 mat->assembled = PETSC_FALSE; 5636 } 5637 5638 if (!MatAssemblyEnd_InUse) { 5639 PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0)); 5640 PetscTryTypeMethod(mat, assemblybegin, type); 5641 PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0)); 5642 } else PetscTryTypeMethod(mat, assemblybegin, type); 5643 PetscFunctionReturn(PETSC_SUCCESS); 5644 } 5645 5646 /*@ 5647 MatAssembled - Indicates if a matrix has been assembled and is ready for 5648 use; for example, in matrix-vector product. 5649 5650 Not Collective 5651 5652 Input Parameter: 5653 . mat - the matrix 5654 5655 Output Parameter: 5656 . assembled - `PETSC_TRUE` or `PETSC_FALSE` 5657 5658 Level: advanced 5659 5660 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()` 5661 @*/ 5662 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled) 5663 { 5664 PetscFunctionBegin; 5665 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5666 PetscValidBoolPointer(assembled, 2); 5667 *assembled = mat->assembled; 5668 PetscFunctionReturn(PETSC_SUCCESS); 5669 } 5670 5671 /*@ 5672 MatAssemblyEnd - Completes assembling the matrix. This routine should 5673 be called after `MatAssemblyBegin()`. 5674 5675 Collective 5676 5677 Input Parameters: 5678 + mat - the matrix 5679 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5680 5681 Options Database Keys: 5682 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatEndAssembly()` 5683 . -mat_view ::ascii_info_detail - Prints more detailed info 5684 . -mat_view - Prints matrix in ASCII format 5685 . -mat_view ::ascii_matlab - Prints matrix in Matlab format 5686 . -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 5687 . -display <name> - Sets display name (default is host) 5688 . -draw_pause <sec> - Sets number of seconds to pause after display 5689 . -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See [Using MATLAB with PETSc](ch_matlab)) 5690 . -viewer_socket_machine <machine> - Machine to use for socket 5691 . -viewer_socket_port <port> - Port number to use for socket 5692 - -mat_view binary:filename[:append] - Save matrix to file in binary format 5693 5694 Level: beginner 5695 5696 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()` 5697 @*/ 5698 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type) 5699 { 5700 static PetscInt inassm = 0; 5701 PetscBool flg = PETSC_FALSE; 5702 5703 PetscFunctionBegin; 5704 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5705 PetscValidType(mat, 1); 5706 5707 inassm++; 5708 MatAssemblyEnd_InUse++; 5709 if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */ 5710 PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0)); 5711 PetscTryTypeMethod(mat, assemblyend, type); 5712 PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0)); 5713 } else PetscTryTypeMethod(mat, assemblyend, type); 5714 5715 /* Flush assembly is not a true assembly */ 5716 if (type != MAT_FLUSH_ASSEMBLY) { 5717 if (mat->num_ass) { 5718 if (!mat->symmetry_eternal) { 5719 mat->symmetric = PETSC_BOOL3_UNKNOWN; 5720 mat->hermitian = PETSC_BOOL3_UNKNOWN; 5721 } 5722 if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN; 5723 if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN; 5724 } 5725 mat->num_ass++; 5726 mat->assembled = PETSC_TRUE; 5727 mat->ass_nonzerostate = mat->nonzerostate; 5728 } 5729 5730 mat->insertmode = NOT_SET_VALUES; 5731 MatAssemblyEnd_InUse--; 5732 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5733 if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) { 5734 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 5735 5736 if (mat->checksymmetryonassembly) { 5737 PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg)); 5738 if (flg) { 5739 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5740 } else { 5741 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5742 } 5743 } 5744 if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL)); 5745 } 5746 inassm--; 5747 PetscFunctionReturn(PETSC_SUCCESS); 5748 } 5749 5750 /*@ 5751 MatSetOption - Sets a parameter option for a matrix. Some options 5752 may be specific to certain storage formats. Some options 5753 determine how values will be inserted (or added). Sorted, 5754 row-oriented input will generally assemble the fastest. The default 5755 is row-oriented. 5756 5757 Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption` 5758 5759 Input Parameters: 5760 + mat - the matrix 5761 . option - the option, one of those listed below (and possibly others), 5762 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5763 5764 Options Describing Matrix Structure: 5765 + `MAT_SPD` - symmetric positive definite 5766 . `MAT_SYMMETRIC` - symmetric in terms of both structure and value 5767 . `MAT_HERMITIAN` - transpose is the complex conjugation 5768 . `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure 5769 . `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix 5770 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix 5771 - `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix 5772 5773 These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they 5774 do not need to be computed (usually at a high cost) 5775 5776 Options For Use with `MatSetValues()`: 5777 Insert a logically dense subblock, which can be 5778 . `MAT_ROW_ORIENTED` - row-oriented (default) 5779 5780 These options reflect the data you pass in with `MatSetValues()`; it has 5781 nothing to do with how the data is stored internally in the matrix 5782 data structure. 5783 5784 When (re)assembling a matrix, we can restrict the input for 5785 efficiency/debugging purposes. These options include 5786 + `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow) 5787 . `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated 5788 . `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries 5789 . `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry 5790 . `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly 5791 . `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if 5792 any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves 5793 performance for very large process counts. 5794 - `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset 5795 of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly 5796 functions, instead sending only neighbor messages. 5797 5798 Level: intermediate 5799 5800 Notes: 5801 Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg! 5802 5803 Some options are relevant only for particular matrix types and 5804 are thus ignored by others. Other options are not supported by 5805 certain matrix types and will generate an error message if set. 5806 5807 If using Fortran to compute a matrix, one may need to 5808 use the column-oriented option (or convert to the row-oriented 5809 format). 5810 5811 `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion 5812 that would generate a new entry in the nonzero structure is instead 5813 ignored. Thus, if memory has not already been allocated for this particular 5814 data, then the insertion is ignored. For dense matrices, in which 5815 the entire array is allocated, no entries are ever ignored. 5816 Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction 5817 5818 `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion 5819 that would generate a new entry in the nonzero structure instead produces 5820 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 5821 5822 `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion 5823 that would generate a new entry that has not been preallocated will 5824 instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats 5825 only.) This is a useful flag when debugging matrix memory preallocation. 5826 If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 5827 5828 `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for 5829 other processors should be dropped, rather than stashed. 5830 This is useful if you know that the "owning" processor is also 5831 always generating the correct matrix entries, so that PETSc need 5832 not transfer duplicate entries generated on another processor. 5833 5834 `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the 5835 searches during matrix assembly. When this flag is set, the hash table 5836 is created during the first matrix assembly. This hash table is 5837 used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()` 5838 to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag 5839 should be used with `MAT_USE_HASH_TABLE` flag. This option is currently 5840 supported by `MATMPIBAIJ` format only. 5841 5842 `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries 5843 are kept in the nonzero structure 5844 5845 `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating 5846 a zero location in the matrix 5847 5848 `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types 5849 5850 `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the 5851 zero row routines and thus improves performance for very large process counts. 5852 5853 `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular 5854 part of the matrix (since they should match the upper triangular part). 5855 5856 `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a 5857 single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common 5858 with finite difference schemes with non-periodic boundary conditions. 5859 5860 Developer Note: 5861 `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other 5862 places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRIC` or `MAT_SPD` would need to be changed back 5863 to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had 5864 not changed. 5865 5866 .seealso: [](chapter_matrices), `MatOption`, `Mat`, `MatGetOption()` 5867 @*/ 5868 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg) 5869 { 5870 PetscFunctionBegin; 5871 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5872 if (op > 0) { 5873 PetscValidLogicalCollectiveEnum(mat, op, 2); 5874 PetscValidLogicalCollectiveBool(mat, flg, 3); 5875 } 5876 5877 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); 5878 5879 switch (op) { 5880 case MAT_FORCE_DIAGONAL_ENTRIES: 5881 mat->force_diagonals = flg; 5882 PetscFunctionReturn(PETSC_SUCCESS); 5883 case MAT_NO_OFF_PROC_ENTRIES: 5884 mat->nooffprocentries = flg; 5885 PetscFunctionReturn(PETSC_SUCCESS); 5886 case MAT_SUBSET_OFF_PROC_ENTRIES: 5887 mat->assembly_subset = flg; 5888 if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */ 5889 #if !defined(PETSC_HAVE_MPIUNI) 5890 PetscCall(MatStashScatterDestroy_BTS(&mat->stash)); 5891 #endif 5892 mat->stash.first_assembly_done = PETSC_FALSE; 5893 } 5894 PetscFunctionReturn(PETSC_SUCCESS); 5895 case MAT_NO_OFF_PROC_ZERO_ROWS: 5896 mat->nooffproczerorows = flg; 5897 PetscFunctionReturn(PETSC_SUCCESS); 5898 case MAT_SPD: 5899 if (flg) { 5900 mat->spd = PETSC_BOOL3_TRUE; 5901 mat->symmetric = PETSC_BOOL3_TRUE; 5902 mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5903 } else { 5904 mat->spd = PETSC_BOOL3_FALSE; 5905 } 5906 break; 5907 case MAT_SYMMETRIC: 5908 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5909 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5910 #if !defined(PETSC_USE_COMPLEX) 5911 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5912 #endif 5913 break; 5914 case MAT_HERMITIAN: 5915 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5916 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5917 #if !defined(PETSC_USE_COMPLEX) 5918 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5919 #endif 5920 break; 5921 case MAT_STRUCTURALLY_SYMMETRIC: 5922 mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5923 break; 5924 case MAT_SYMMETRY_ETERNAL: 5925 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"); 5926 mat->symmetry_eternal = flg; 5927 if (flg) mat->structural_symmetry_eternal = PETSC_TRUE; 5928 break; 5929 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 5930 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"); 5931 mat->structural_symmetry_eternal = flg; 5932 break; 5933 case MAT_SPD_ETERNAL: 5934 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"); 5935 mat->spd_eternal = flg; 5936 if (flg) { 5937 mat->structural_symmetry_eternal = PETSC_TRUE; 5938 mat->symmetry_eternal = PETSC_TRUE; 5939 } 5940 break; 5941 case MAT_STRUCTURE_ONLY: 5942 mat->structure_only = flg; 5943 break; 5944 case MAT_SORTED_FULL: 5945 mat->sortedfull = flg; 5946 break; 5947 default: 5948 break; 5949 } 5950 PetscTryTypeMethod(mat, setoption, op, flg); 5951 PetscFunctionReturn(PETSC_SUCCESS); 5952 } 5953 5954 /*@ 5955 MatGetOption - Gets a parameter option that has been set for a matrix. 5956 5957 Logically Collective 5958 5959 Input Parameters: 5960 + mat - the matrix 5961 - option - the option, this only responds to certain options, check the code for which ones 5962 5963 Output Parameter: 5964 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5965 5966 Level: intermediate 5967 5968 Notes: 5969 Can only be called after `MatSetSizes()` and `MatSetType()` have been set. 5970 5971 Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or 5972 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 5973 5974 .seealso: [](chapter_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, 5975 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 5976 @*/ 5977 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg) 5978 { 5979 PetscFunctionBegin; 5980 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5981 PetscValidType(mat, 1); 5982 5983 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); 5984 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()"); 5985 5986 switch (op) { 5987 case MAT_NO_OFF_PROC_ENTRIES: 5988 *flg = mat->nooffprocentries; 5989 break; 5990 case MAT_NO_OFF_PROC_ZERO_ROWS: 5991 *flg = mat->nooffproczerorows; 5992 break; 5993 case MAT_SYMMETRIC: 5994 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()"); 5995 break; 5996 case MAT_HERMITIAN: 5997 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()"); 5998 break; 5999 case MAT_STRUCTURALLY_SYMMETRIC: 6000 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()"); 6001 break; 6002 case MAT_SPD: 6003 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()"); 6004 break; 6005 case MAT_SYMMETRY_ETERNAL: 6006 *flg = mat->symmetry_eternal; 6007 break; 6008 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6009 *flg = mat->symmetry_eternal; 6010 break; 6011 default: 6012 break; 6013 } 6014 PetscFunctionReturn(PETSC_SUCCESS); 6015 } 6016 6017 /*@ 6018 MatZeroEntries - Zeros all entries of a matrix. For sparse matrices 6019 this routine retains the old nonzero structure. 6020 6021 Logically Collective 6022 6023 Input Parameter: 6024 . mat - the matrix 6025 6026 Level: intermediate 6027 6028 Note: 6029 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. 6030 See the Performance chapter of the users manual for information on preallocating matrices. 6031 6032 .seealso: [](chapter_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()` 6033 @*/ 6034 PetscErrorCode MatZeroEntries(Mat mat) 6035 { 6036 PetscFunctionBegin; 6037 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6038 PetscValidType(mat, 1); 6039 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6040 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"); 6041 MatCheckPreallocated(mat, 1); 6042 6043 PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0)); 6044 PetscUseTypeMethod(mat, zeroentries); 6045 PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0)); 6046 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6047 PetscFunctionReturn(PETSC_SUCCESS); 6048 } 6049 6050 /*@ 6051 MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal) 6052 of a set of rows and columns of a matrix. 6053 6054 Collective 6055 6056 Input Parameters: 6057 + mat - the matrix 6058 . numRows - the number of rows/columns to zero 6059 . rows - the global row indices 6060 . diag - value put in the diagonal of the eliminated rows 6061 . x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call 6062 - b - optional vector of the right hand side, that will be adjusted by provided solution entries 6063 6064 Level: intermediate 6065 6066 Notes: 6067 This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6068 6069 For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`. 6070 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 6071 6072 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6073 Krylov method to take advantage of the known solution on the zeroed rows. 6074 6075 For the parallel case, all processes that share the matrix (i.e., 6076 those in the communicator used for matrix creation) MUST call this 6077 routine, regardless of whether any rows being zeroed are owned by 6078 them. 6079 6080 Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix. 6081 6082 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6083 list only rows local to itself). 6084 6085 The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine. 6086 6087 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6088 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6089 @*/ 6090 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6091 { 6092 PetscFunctionBegin; 6093 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6094 PetscValidType(mat, 1); 6095 if (numRows) PetscValidIntPointer(rows, 3); 6096 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6097 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6098 MatCheckPreallocated(mat, 1); 6099 6100 PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b); 6101 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6102 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6103 PetscFunctionReturn(PETSC_SUCCESS); 6104 } 6105 6106 /*@ 6107 MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal) 6108 of a set of rows and columns of a matrix. 6109 6110 Collective 6111 6112 Input Parameters: 6113 + mat - the matrix 6114 . is - the rows to zero 6115 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6116 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6117 - b - optional vector of right hand side, that will be adjusted by provided solution 6118 6119 Level: intermediate 6120 6121 Note: 6122 See `MatZeroRowsColumns()` for details on how this routine operates. 6123 6124 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6125 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()` 6126 @*/ 6127 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6128 { 6129 PetscInt numRows; 6130 const PetscInt *rows; 6131 6132 PetscFunctionBegin; 6133 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6134 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6135 PetscValidType(mat, 1); 6136 PetscValidType(is, 2); 6137 PetscCall(ISGetLocalSize(is, &numRows)); 6138 PetscCall(ISGetIndices(is, &rows)); 6139 PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b)); 6140 PetscCall(ISRestoreIndices(is, &rows)); 6141 PetscFunctionReturn(PETSC_SUCCESS); 6142 } 6143 6144 /*@ 6145 MatZeroRows - Zeros all entries (except possibly the main diagonal) 6146 of a set of rows of a matrix. 6147 6148 Collective 6149 6150 Input Parameters: 6151 + mat - the matrix 6152 . numRows - the number of rows to zero 6153 . rows - the global row indices 6154 . diag - value put in the diagonal of the zeroed rows 6155 . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call 6156 - b - optional vector of right hand side, that will be adjusted by provided solution entries 6157 6158 Level: intermediate 6159 6160 Notes: 6161 This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6162 6163 For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`. 6164 6165 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6166 Krylov method to take advantage of the known solution on the zeroed rows. 6167 6168 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) 6169 from the matrix. 6170 6171 Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix 6172 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 6173 formats this does not alter the nonzero structure. 6174 6175 If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure 6176 of the matrix is not changed the values are 6177 merely zeroed. 6178 6179 The user can set a value in the diagonal entry (or for the `MATAIJ` format 6180 formats can optionally remove the main diagonal entry from the 6181 nonzero structure as well, by passing 0.0 as the final argument). 6182 6183 For the parallel case, all processes that share the matrix (i.e., 6184 those in the communicator used for matrix creation) MUST call this 6185 routine, regardless of whether any rows being zeroed are owned by 6186 them. 6187 6188 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6189 list only rows local to itself). 6190 6191 You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it 6192 owns that are to be zeroed. This saves a global synchronization in the implementation. 6193 6194 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6195 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE` 6196 @*/ 6197 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6198 { 6199 PetscFunctionBegin; 6200 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6201 PetscValidType(mat, 1); 6202 if (numRows) PetscValidIntPointer(rows, 3); 6203 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6204 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6205 MatCheckPreallocated(mat, 1); 6206 6207 PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b); 6208 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6209 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6210 PetscFunctionReturn(PETSC_SUCCESS); 6211 } 6212 6213 /*@ 6214 MatZeroRowsIS - Zeros all entries (except possibly the main diagonal) 6215 of a set of rows of a matrix. 6216 6217 Collective 6218 6219 Input Parameters: 6220 + mat - the matrix 6221 . is - index set of rows to remove (if `NULL` then no row is removed) 6222 . diag - value put in all diagonals of eliminated rows 6223 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6224 - b - optional vector of right hand side, that will be adjusted by provided solution 6225 6226 Level: intermediate 6227 6228 Note: 6229 See `MatZeroRows()` for details on how this routine operates. 6230 6231 .seealso: [](chapter_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6232 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6233 @*/ 6234 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6235 { 6236 PetscInt numRows = 0; 6237 const PetscInt *rows = NULL; 6238 6239 PetscFunctionBegin; 6240 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6241 PetscValidType(mat, 1); 6242 if (is) { 6243 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6244 PetscCall(ISGetLocalSize(is, &numRows)); 6245 PetscCall(ISGetIndices(is, &rows)); 6246 } 6247 PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b)); 6248 if (is) PetscCall(ISRestoreIndices(is, &rows)); 6249 PetscFunctionReturn(PETSC_SUCCESS); 6250 } 6251 6252 /*@ 6253 MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal) 6254 of a set of rows of a matrix. These rows must be local to the process. 6255 6256 Collective 6257 6258 Input Parameters: 6259 + mat - the matrix 6260 . numRows - the number of rows to remove 6261 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6262 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6263 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6264 - b - optional vector of right hand side, that will be adjusted by provided solution 6265 6266 Level: intermediate 6267 6268 Notes: 6269 See `MatZeroRows()` for details on how this routine operates. 6270 6271 The grid coordinates are across the entire grid, not just the local portion 6272 6273 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6274 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6275 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6276 `DM_BOUNDARY_PERIODIC` boundary type. 6277 6278 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 6279 a single value per point) you can skip filling those indices. 6280 6281 Fortran Note: 6282 `idxm` and `idxn` should be declared as 6283 $ MatStencil idxm(4,m) 6284 and the values inserted using 6285 .vb 6286 idxm(MatStencil_i,1) = i 6287 idxm(MatStencil_j,1) = j 6288 idxm(MatStencil_k,1) = k 6289 idxm(MatStencil_c,1) = c 6290 etc 6291 .ve 6292 6293 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6294 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6295 @*/ 6296 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6297 { 6298 PetscInt dim = mat->stencil.dim; 6299 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6300 PetscInt *dims = mat->stencil.dims + 1; 6301 PetscInt *starts = mat->stencil.starts; 6302 PetscInt *dxm = (PetscInt *)rows; 6303 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6304 6305 PetscFunctionBegin; 6306 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6307 PetscValidType(mat, 1); 6308 if (numRows) PetscValidPointer(rows, 3); 6309 6310 PetscCall(PetscMalloc1(numRows, &jdxm)); 6311 for (i = 0; i < numRows; ++i) { 6312 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6313 for (j = 0; j < 3 - sdim; ++j) dxm++; 6314 /* Local index in X dir */ 6315 tmp = *dxm++ - starts[0]; 6316 /* Loop over remaining dimensions */ 6317 for (j = 0; j < dim - 1; ++j) { 6318 /* If nonlocal, set index to be negative */ 6319 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6320 /* Update local index */ 6321 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6322 } 6323 /* Skip component slot if necessary */ 6324 if (mat->stencil.noc) dxm++; 6325 /* Local row number */ 6326 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6327 } 6328 PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b)); 6329 PetscCall(PetscFree(jdxm)); 6330 PetscFunctionReturn(PETSC_SUCCESS); 6331 } 6332 6333 /*@ 6334 MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal) 6335 of a set of rows and columns of a matrix. 6336 6337 Collective 6338 6339 Input Parameters: 6340 + mat - the matrix 6341 . numRows - the number of rows/columns to remove 6342 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6343 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6344 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6345 - b - optional vector of right hand side, that will be adjusted by provided solution 6346 6347 Level: intermediate 6348 6349 Notes: 6350 See `MatZeroRowsColumns()` for details on how this routine operates. 6351 6352 The grid coordinates are across the entire grid, not just the local portion 6353 6354 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6355 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6356 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6357 `DM_BOUNDARY_PERIODIC` boundary type. 6358 6359 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 6360 a single value per point) you can skip filling those indices. 6361 6362 Fortran Note: 6363 `idxm` and `idxn` should be declared as 6364 $ MatStencil idxm(4,m) 6365 and the values inserted using 6366 .vb 6367 idxm(MatStencil_i,1) = i 6368 idxm(MatStencil_j,1) = j 6369 idxm(MatStencil_k,1) = k 6370 idxm(MatStencil_c,1) = c 6371 etc 6372 .ve 6373 6374 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6375 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()` 6376 @*/ 6377 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6378 { 6379 PetscInt dim = mat->stencil.dim; 6380 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6381 PetscInt *dims = mat->stencil.dims + 1; 6382 PetscInt *starts = mat->stencil.starts; 6383 PetscInt *dxm = (PetscInt *)rows; 6384 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6385 6386 PetscFunctionBegin; 6387 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6388 PetscValidType(mat, 1); 6389 if (numRows) PetscValidPointer(rows, 3); 6390 6391 PetscCall(PetscMalloc1(numRows, &jdxm)); 6392 for (i = 0; i < numRows; ++i) { 6393 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6394 for (j = 0; j < 3 - sdim; ++j) dxm++; 6395 /* Local index in X dir */ 6396 tmp = *dxm++ - starts[0]; 6397 /* Loop over remaining dimensions */ 6398 for (j = 0; j < dim - 1; ++j) { 6399 /* If nonlocal, set index to be negative */ 6400 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6401 /* Update local index */ 6402 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6403 } 6404 /* Skip component slot if necessary */ 6405 if (mat->stencil.noc) dxm++; 6406 /* Local row number */ 6407 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6408 } 6409 PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b)); 6410 PetscCall(PetscFree(jdxm)); 6411 PetscFunctionReturn(PETSC_SUCCESS); 6412 } 6413 6414 /*@C 6415 MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal) 6416 of a set of rows of a matrix; using local numbering of rows. 6417 6418 Collective 6419 6420 Input Parameters: 6421 + mat - the matrix 6422 . numRows - the number of rows to remove 6423 . rows - the local row indices 6424 . diag - value put in all diagonals of eliminated rows 6425 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6426 - b - optional vector of right hand side, that will be adjusted by provided solution 6427 6428 Level: intermediate 6429 6430 Notes: 6431 Before calling `MatZeroRowsLocal()`, the user must first set the 6432 local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`. 6433 6434 See `MatZeroRows()` for details on how this routine operates. 6435 6436 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`, 6437 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6438 @*/ 6439 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6440 { 6441 PetscFunctionBegin; 6442 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6443 PetscValidType(mat, 1); 6444 if (numRows) PetscValidIntPointer(rows, 3); 6445 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6446 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6447 MatCheckPreallocated(mat, 1); 6448 6449 if (mat->ops->zerorowslocal) { 6450 PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b); 6451 } else { 6452 IS is, newis; 6453 const PetscInt *newRows; 6454 6455 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6456 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6457 PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis)); 6458 PetscCall(ISGetIndices(newis, &newRows)); 6459 PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b); 6460 PetscCall(ISRestoreIndices(newis, &newRows)); 6461 PetscCall(ISDestroy(&newis)); 6462 PetscCall(ISDestroy(&is)); 6463 } 6464 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6465 PetscFunctionReturn(PETSC_SUCCESS); 6466 } 6467 6468 /*@ 6469 MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal) 6470 of a set of rows of a matrix; using local numbering of rows. 6471 6472 Collective 6473 6474 Input Parameters: 6475 + mat - the matrix 6476 . is - index set of rows to remove 6477 . diag - value put in all diagonals of eliminated rows 6478 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6479 - b - optional vector of right hand side, that will be adjusted by provided solution 6480 6481 Level: intermediate 6482 6483 Notes: 6484 Before calling `MatZeroRowsLocalIS()`, the user must first set the 6485 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6486 6487 See `MatZeroRows()` for details on how this routine operates. 6488 6489 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6490 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6491 @*/ 6492 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6493 { 6494 PetscInt numRows; 6495 const PetscInt *rows; 6496 6497 PetscFunctionBegin; 6498 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6499 PetscValidType(mat, 1); 6500 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6501 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6502 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6503 MatCheckPreallocated(mat, 1); 6504 6505 PetscCall(ISGetLocalSize(is, &numRows)); 6506 PetscCall(ISGetIndices(is, &rows)); 6507 PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b)); 6508 PetscCall(ISRestoreIndices(is, &rows)); 6509 PetscFunctionReturn(PETSC_SUCCESS); 6510 } 6511 6512 /*@ 6513 MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal) 6514 of a set of rows and columns of a matrix; using local numbering of rows. 6515 6516 Collective 6517 6518 Input Parameters: 6519 + mat - the matrix 6520 . numRows - the number of rows to remove 6521 . rows - the global row indices 6522 . diag - value put in all diagonals of eliminated rows 6523 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6524 - b - optional vector of right hand side, that will be adjusted by provided solution 6525 6526 Level: intermediate 6527 6528 Notes: 6529 Before calling `MatZeroRowsColumnsLocal()`, the user must first set the 6530 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6531 6532 See `MatZeroRowsColumns()` for details on how this routine operates. 6533 6534 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6535 `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6536 @*/ 6537 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6538 { 6539 IS is, newis; 6540 const PetscInt *newRows; 6541 6542 PetscFunctionBegin; 6543 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6544 PetscValidType(mat, 1); 6545 if (numRows) PetscValidIntPointer(rows, 3); 6546 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6547 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6548 MatCheckPreallocated(mat, 1); 6549 6550 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6551 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6552 PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis)); 6553 PetscCall(ISGetIndices(newis, &newRows)); 6554 PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b); 6555 PetscCall(ISRestoreIndices(newis, &newRows)); 6556 PetscCall(ISDestroy(&newis)); 6557 PetscCall(ISDestroy(&is)); 6558 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6559 PetscFunctionReturn(PETSC_SUCCESS); 6560 } 6561 6562 /*@ 6563 MatZeroRowsColumnsLocalIS - 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 . is - index set of rows to remove 6571 . diag - value put in all diagonals of eliminated rows 6572 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6573 - b - optional vector of right hand side, that will be adjusted by provided solution 6574 6575 Level: intermediate 6576 6577 Notes: 6578 Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the 6579 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6580 6581 See `MatZeroRowsColumns()` for details on how this routine operates. 6582 6583 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6584 `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6585 @*/ 6586 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6587 { 6588 PetscInt numRows; 6589 const PetscInt *rows; 6590 6591 PetscFunctionBegin; 6592 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6593 PetscValidType(mat, 1); 6594 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6595 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6596 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6597 MatCheckPreallocated(mat, 1); 6598 6599 PetscCall(ISGetLocalSize(is, &numRows)); 6600 PetscCall(ISGetIndices(is, &rows)); 6601 PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b)); 6602 PetscCall(ISRestoreIndices(is, &rows)); 6603 PetscFunctionReturn(PETSC_SUCCESS); 6604 } 6605 6606 /*@C 6607 MatGetSize - Returns the numbers of rows and columns in a matrix. 6608 6609 Not Collective 6610 6611 Input Parameter: 6612 . mat - the matrix 6613 6614 Output Parameters: 6615 + m - the number of global rows 6616 - n - the number of global columns 6617 6618 Level: beginner 6619 6620 Note: 6621 Both output parameters can be `NULL` on input. 6622 6623 .seealso: [](chapter_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()` 6624 @*/ 6625 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n) 6626 { 6627 PetscFunctionBegin; 6628 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6629 if (m) *m = mat->rmap->N; 6630 if (n) *n = mat->cmap->N; 6631 PetscFunctionReturn(PETSC_SUCCESS); 6632 } 6633 6634 /*@C 6635 MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns 6636 of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`. 6637 6638 Not Collective 6639 6640 Input Parameter: 6641 . mat - the matrix 6642 6643 Output Parameters: 6644 + m - the number of local rows, use `NULL` to not obtain this value 6645 - n - the number of local columns, use `NULL` to not obtain this value 6646 6647 Level: beginner 6648 6649 .seealso: [](chapter_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()` 6650 @*/ 6651 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n) 6652 { 6653 PetscFunctionBegin; 6654 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6655 if (m) PetscValidIntPointer(m, 2); 6656 if (n) PetscValidIntPointer(n, 3); 6657 if (m) *m = mat->rmap->n; 6658 if (n) *n = mat->cmap->n; 6659 PetscFunctionReturn(PETSC_SUCCESS); 6660 } 6661 6662 /*@C 6663 MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by 6664 this processor. (The columns of the "diagonal block" for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts. 6665 6666 Not Collective, unless matrix has not been allocated, then collective 6667 6668 Input Parameter: 6669 . mat - the matrix 6670 6671 Output Parameters: 6672 + m - the global index of the first local column, use `NULL` to not obtain this value 6673 - n - one more than the global index of the last local column, use `NULL` to not obtain this value 6674 6675 Level: developer 6676 6677 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout` 6678 @*/ 6679 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n) 6680 { 6681 PetscFunctionBegin; 6682 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6683 PetscValidType(mat, 1); 6684 if (m) PetscValidIntPointer(m, 2); 6685 if (n) PetscValidIntPointer(n, 3); 6686 MatCheckPreallocated(mat, 1); 6687 if (m) *m = mat->cmap->rstart; 6688 if (n) *n = mat->cmap->rend; 6689 PetscFunctionReturn(PETSC_SUCCESS); 6690 } 6691 6692 /*@C 6693 MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6694 this MPI rank. For all matrices it returns the range of matrix rows associated with rows of a vector that would contain the result of a matrix 6695 vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts 6696 6697 Not Collective 6698 6699 Input Parameter: 6700 . mat - the matrix 6701 6702 Output Parameters: 6703 + m - the global index of the first local row, use `NULL` to not obtain this value 6704 - n - one more than the global index of the last local row, use `NULL` to not obtain this value 6705 6706 Level: beginner 6707 6708 Note: 6709 This function requires that the matrix be preallocated. If you have not preallocated, consider using 6710 `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N) 6711 and then `MPI_Scan()` to calculate prefix sums of the local sizes. 6712 6713 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, 6714 `PetscLayout` 6715 @*/ 6716 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n) 6717 { 6718 PetscFunctionBegin; 6719 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6720 PetscValidType(mat, 1); 6721 if (m) PetscValidIntPointer(m, 2); 6722 if (n) PetscValidIntPointer(n, 3); 6723 MatCheckPreallocated(mat, 1); 6724 if (m) *m = mat->rmap->rstart; 6725 if (n) *n = mat->rmap->rend; 6726 PetscFunctionReturn(PETSC_SUCCESS); 6727 } 6728 6729 /*@C 6730 MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6731 each process. For all matrices it returns the ranges of matrix rows associated with rows of a vector that would contain the result of a matrix 6732 vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts 6733 6734 Not Collective, unless matrix has not been allocated 6735 6736 Input Parameter: 6737 . mat - the matrix 6738 6739 Output Parameter: 6740 . ranges - start of each processors portion plus one more than the total length at the end 6741 6742 Level: beginner 6743 6744 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout` 6745 @*/ 6746 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges) 6747 { 6748 PetscFunctionBegin; 6749 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6750 PetscValidType(mat, 1); 6751 MatCheckPreallocated(mat, 1); 6752 PetscCall(PetscLayoutGetRanges(mat->rmap, ranges)); 6753 PetscFunctionReturn(PETSC_SUCCESS); 6754 } 6755 6756 /*@C 6757 MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by 6758 each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts. 6759 6760 Not Collective, unless matrix has not been allocated 6761 6762 Input Parameter: 6763 . mat - the matrix 6764 6765 Output Parameter: 6766 . ranges - start of each processors portion plus one more then the total length at the end 6767 6768 Level: beginner 6769 6770 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()` 6771 @*/ 6772 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges) 6773 { 6774 PetscFunctionBegin; 6775 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6776 PetscValidType(mat, 1); 6777 MatCheckPreallocated(mat, 1); 6778 PetscCall(PetscLayoutGetRanges(mat->cmap, ranges)); 6779 PetscFunctionReturn(PETSC_SUCCESS); 6780 } 6781 6782 /*@C 6783 MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this 6784 corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership 6785 is more complicated. See :any:`<sec_matlayout>` for details on matrix layouts. 6786 6787 Not Collective 6788 6789 Input Parameter: 6790 . A - matrix 6791 6792 Output Parameters: 6793 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value 6794 - cols - columns in which this process owns elements, use `NULL` to not obtain this value 6795 6796 Level: intermediate 6797 6798 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK`` 6799 @*/ 6800 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols) 6801 { 6802 PetscErrorCode (*f)(Mat, IS *, IS *); 6803 6804 PetscFunctionBegin; 6805 MatCheckPreallocated(A, 1); 6806 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f)); 6807 if (f) { 6808 PetscCall((*f)(A, rows, cols)); 6809 } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */ 6810 if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows)); 6811 if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols)); 6812 } 6813 PetscFunctionReturn(PETSC_SUCCESS); 6814 } 6815 6816 /*@C 6817 MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()` 6818 Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()` 6819 to complete the factorization. 6820 6821 Collective 6822 6823 Input Parameters: 6824 + fact - the factorized matrix obtained with `MatGetFactor()` 6825 . mat - the matrix 6826 . row - row permutation 6827 . col - column permutation 6828 - info - structure containing 6829 .vb 6830 levels - number of levels of fill. 6831 expected fill - as ratio of original fill. 6832 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 6833 missing diagonal entries) 6834 .ve 6835 6836 Level: developer 6837 6838 Notes: 6839 See [Matrix Factorization](sec_matfactor) for additional information. 6840 6841 Most users should employ the `KSP` interface for linear solvers 6842 instead of working directly with matrix algebra routines such as this. 6843 See, e.g., `KSPCreate()`. 6844 6845 Uses the definition of level of fill as in Y. Saad, 2003 6846 6847 Developer Note: 6848 The Fortran interface is not autogenerated as the 6849 interface definition cannot be generated correctly [due to `MatFactorInfo`] 6850 6851 References: 6852 . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003 6853 6854 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 6855 `MatGetOrdering()`, `MatFactorInfo` 6856 @*/ 6857 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 6858 { 6859 PetscFunctionBegin; 6860 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 6861 PetscValidType(mat, 2); 6862 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 6863 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 6864 PetscValidPointer(info, 5); 6865 PetscValidPointer(fact, 1); 6866 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels); 6867 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 6868 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6869 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6870 MatCheckPreallocated(mat, 2); 6871 6872 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0)); 6873 PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info); 6874 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0)); 6875 PetscFunctionReturn(PETSC_SUCCESS); 6876 } 6877 6878 /*@C 6879 MatICCFactorSymbolic - Performs symbolic incomplete 6880 Cholesky factorization for a symmetric matrix. Use 6881 `MatCholeskyFactorNumeric()` to complete the factorization. 6882 6883 Collective 6884 6885 Input Parameters: 6886 + fact - the factorized matrix obtained with `MatGetFactor()` 6887 . mat - the matrix to be factored 6888 . perm - row and column permutation 6889 - info - structure containing 6890 .vb 6891 levels - number of levels of fill. 6892 expected fill - as ratio of original fill. 6893 .ve 6894 6895 Level: developer 6896 6897 Notes: 6898 Most users should employ the `KSP` interface for linear solvers 6899 instead of working directly with matrix algebra routines such as this. 6900 See, e.g., `KSPCreate()`. 6901 6902 This uses the definition of level of fill as in Y. Saad, 2003 6903 6904 Developer Note: 6905 The Fortran interface is not autogenerated as the 6906 interface definition cannot be generated correctly [due to `MatFactorInfo`] 6907 6908 References: 6909 . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003 6910 6911 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 6912 @*/ 6913 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 6914 { 6915 PetscFunctionBegin; 6916 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 6917 PetscValidType(mat, 2); 6918 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 6919 PetscValidPointer(info, 4); 6920 PetscValidPointer(fact, 1); 6921 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6922 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels); 6923 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 6924 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6925 MatCheckPreallocated(mat, 2); 6926 6927 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 6928 PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info); 6929 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 6930 PetscFunctionReturn(PETSC_SUCCESS); 6931 } 6932 6933 /*@C 6934 MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat 6935 points to an array of valid matrices, they may be reused to store the new 6936 submatrices. 6937 6938 Collective 6939 6940 Input Parameters: 6941 + mat - the matrix 6942 . n - the number of submatrixes to be extracted (on this processor, may be zero) 6943 . irow - index set of rows to extract 6944 . icol - index set of columns to extract 6945 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 6946 6947 Output Parameter: 6948 . submat - the array of submatrices 6949 6950 Level: advanced 6951 6952 Notes: 6953 `MatCreateSubMatrices()` can extract ONLY sequential submatrices 6954 (from both sequential and parallel matrices). Use `MatCreateSubMatrix()` 6955 to extract a parallel submatrix. 6956 6957 Some matrix types place restrictions on the row and column 6958 indices, such as that they be sorted or that they be equal to each other. 6959 6960 The index sets may not have duplicate entries. 6961 6962 When extracting submatrices from a parallel matrix, each processor can 6963 form a different submatrix by setting the rows and columns of its 6964 individual index sets according to the local submatrix desired. 6965 6966 When finished using the submatrices, the user should destroy 6967 them with `MatDestroySubMatrices()`. 6968 6969 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 6970 original matrix has not changed from that last call to `MatCreateSubMatrices()`. 6971 6972 This routine creates the matrices in submat; you should NOT create them before 6973 calling it. It also allocates the array of matrix pointers submat. 6974 6975 For `MATBAIJ` matrices the index sets must respect the block structure, that is if they 6976 request one row/column in a block, they must request all rows/columns that are in 6977 that block. For example, if the block size is 2 you cannot request just row 0 and 6978 column 0. 6979 6980 Fortran Note: 6981 The Fortran interface is slightly different from that given below; it 6982 requires one to pass in as `submat` a `Mat` (integer) array of size at least n+1. 6983 6984 .seealso: [](chapter_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 6985 @*/ 6986 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 6987 { 6988 PetscInt i; 6989 PetscBool eq; 6990 6991 PetscFunctionBegin; 6992 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6993 PetscValidType(mat, 1); 6994 if (n) { 6995 PetscValidPointer(irow, 3); 6996 for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3); 6997 PetscValidPointer(icol, 4); 6998 for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4); 6999 } 7000 PetscValidPointer(submat, 6); 7001 if (n && scall == MAT_REUSE_MATRIX) { 7002 PetscValidPointer(*submat, 6); 7003 for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6); 7004 } 7005 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7006 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7007 MatCheckPreallocated(mat, 1); 7008 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7009 PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat); 7010 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7011 for (i = 0; i < n; i++) { 7012 (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */ 7013 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7014 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7015 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 7016 if (mat->boundtocpu && mat->bindingpropagates) { 7017 PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE)); 7018 PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE)); 7019 } 7020 #endif 7021 } 7022 PetscFunctionReturn(PETSC_SUCCESS); 7023 } 7024 7025 /*@C 7026 MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms). 7027 7028 Collective 7029 7030 Input Parameters: 7031 + mat - the matrix 7032 . n - the number of submatrixes to be extracted 7033 . irow - index set of rows to extract 7034 . icol - index set of columns to extract 7035 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7036 7037 Output Parameter: 7038 . submat - the array of submatrices 7039 7040 Level: advanced 7041 7042 Note: 7043 This is used by `PCGASM` 7044 7045 .seealso: [](chapter_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7046 @*/ 7047 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7048 { 7049 PetscInt i; 7050 PetscBool eq; 7051 7052 PetscFunctionBegin; 7053 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7054 PetscValidType(mat, 1); 7055 if (n) { 7056 PetscValidPointer(irow, 3); 7057 PetscValidHeaderSpecific(*irow, IS_CLASSID, 3); 7058 PetscValidPointer(icol, 4); 7059 PetscValidHeaderSpecific(*icol, IS_CLASSID, 4); 7060 } 7061 PetscValidPointer(submat, 6); 7062 if (n && scall == MAT_REUSE_MATRIX) { 7063 PetscValidPointer(*submat, 6); 7064 PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6); 7065 } 7066 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7067 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7068 MatCheckPreallocated(mat, 1); 7069 7070 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7071 PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat); 7072 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7073 for (i = 0; i < n; i++) { 7074 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7075 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7076 } 7077 PetscFunctionReturn(PETSC_SUCCESS); 7078 } 7079 7080 /*@C 7081 MatDestroyMatrices - Destroys an array of matrices. 7082 7083 Collective 7084 7085 Input Parameters: 7086 + n - the number of local matrices 7087 - mat - the matrices (this is a pointer to the array of matrices) 7088 7089 Level: advanced 7090 7091 Note: 7092 Frees not only the matrices, but also the array that contains the matrices 7093 7094 Fortran Note: 7095 This does not free the array. 7096 7097 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()` 7098 @*/ 7099 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[]) 7100 { 7101 PetscInt i; 7102 7103 PetscFunctionBegin; 7104 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7105 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7106 PetscValidPointer(mat, 2); 7107 7108 for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i])); 7109 7110 /* memory is allocated even if n = 0 */ 7111 PetscCall(PetscFree(*mat)); 7112 PetscFunctionReturn(PETSC_SUCCESS); 7113 } 7114 7115 /*@C 7116 MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`. 7117 7118 Collective 7119 7120 Input Parameters: 7121 + n - the number of local matrices 7122 - mat - the matrices (this is a pointer to the array of matrices, just to match the calling 7123 sequence of `MatCreateSubMatrices()`) 7124 7125 Level: advanced 7126 7127 Note: 7128 Frees not only the matrices, but also the array that contains the matrices 7129 7130 Fortran Note: 7131 This does not free the array. 7132 7133 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7134 @*/ 7135 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[]) 7136 { 7137 Mat mat0; 7138 7139 PetscFunctionBegin; 7140 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7141 /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */ 7142 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7143 PetscValidPointer(mat, 2); 7144 7145 mat0 = (*mat)[0]; 7146 if (mat0 && mat0->ops->destroysubmatrices) { 7147 PetscCall((*mat0->ops->destroysubmatrices)(n, mat)); 7148 } else { 7149 PetscCall(MatDestroyMatrices(n, mat)); 7150 } 7151 PetscFunctionReturn(PETSC_SUCCESS); 7152 } 7153 7154 /*@C 7155 MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process 7156 7157 Collective 7158 7159 Input Parameter: 7160 . mat - the matrix 7161 7162 Output Parameter: 7163 . matstruct - the sequential matrix with the nonzero structure of mat 7164 7165 Level: developer 7166 7167 .seealso: [](chapter_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7168 @*/ 7169 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct) 7170 { 7171 PetscFunctionBegin; 7172 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7173 PetscValidPointer(matstruct, 2); 7174 7175 PetscValidType(mat, 1); 7176 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7177 MatCheckPreallocated(mat, 1); 7178 7179 PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7180 PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct); 7181 PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7182 PetscFunctionReturn(PETSC_SUCCESS); 7183 } 7184 7185 /*@C 7186 MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`. 7187 7188 Collective 7189 7190 Input Parameter: 7191 . mat - the matrix (this is a pointer to the array of matrices, just to match the calling 7192 sequence of `MatGetSequentialNonzeroStructure()`) 7193 7194 Level: advanced 7195 7196 Note: 7197 Frees not only the matrices, but also the array that contains the matrices 7198 7199 .seealso: [](chapter_matrices), `Mat`, `MatGetSeqNonzeroStructure()` 7200 @*/ 7201 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat) 7202 { 7203 PetscFunctionBegin; 7204 PetscValidPointer(mat, 1); 7205 PetscCall(MatDestroy(mat)); 7206 PetscFunctionReturn(PETSC_SUCCESS); 7207 } 7208 7209 /*@ 7210 MatIncreaseOverlap - Given a set of submatrices indicated by index sets, 7211 replaces the index sets by larger ones that represent submatrices with 7212 additional overlap. 7213 7214 Collective 7215 7216 Input Parameters: 7217 + mat - the matrix 7218 . n - the number of index sets 7219 . is - the array of index sets (these index sets will changed during the call) 7220 - ov - the additional overlap requested 7221 7222 Options Database Key: 7223 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7224 7225 Level: developer 7226 7227 Note: 7228 The computed overlap preserves the matrix block sizes when the blocks are square. 7229 That is: if a matrix nonzero for a given block would increase the overlap all columns associated with 7230 that block are included in the overlap regardless of whether each specific column would increase the overlap. 7231 7232 .seealso: [](chapter_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()` 7233 @*/ 7234 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov) 7235 { 7236 PetscInt i, bs, cbs; 7237 7238 PetscFunctionBegin; 7239 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7240 PetscValidType(mat, 1); 7241 PetscValidLogicalCollectiveInt(mat, n, 2); 7242 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7243 if (n) { 7244 PetscValidPointer(is, 3); 7245 for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3); 7246 } 7247 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7248 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7249 MatCheckPreallocated(mat, 1); 7250 7251 if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS); 7252 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7253 PetscUseTypeMethod(mat, increaseoverlap, n, is, ov); 7254 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7255 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 7256 if (bs == cbs) { 7257 for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs)); 7258 } 7259 PetscFunctionReturn(PETSC_SUCCESS); 7260 } 7261 7262 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt); 7263 7264 /*@ 7265 MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across 7266 a sub communicator, replaces the index sets by larger ones that represent submatrices with 7267 additional overlap. 7268 7269 Collective 7270 7271 Input Parameters: 7272 + mat - the matrix 7273 . n - the number of index sets 7274 . is - the array of index sets (these index sets will changed during the call) 7275 - ov - the additional overlap requested 7276 7277 ` Options Database Key: 7278 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7279 7280 Level: developer 7281 7282 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()` 7283 @*/ 7284 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov) 7285 { 7286 PetscInt i; 7287 7288 PetscFunctionBegin; 7289 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7290 PetscValidType(mat, 1); 7291 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7292 if (n) { 7293 PetscValidPointer(is, 3); 7294 PetscValidHeaderSpecific(*is, IS_CLASSID, 3); 7295 } 7296 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7297 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7298 MatCheckPreallocated(mat, 1); 7299 if (!ov) PetscFunctionReturn(PETSC_SUCCESS); 7300 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7301 for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov)); 7302 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7303 PetscFunctionReturn(PETSC_SUCCESS); 7304 } 7305 7306 /*@ 7307 MatGetBlockSize - Returns the matrix block size. 7308 7309 Not Collective 7310 7311 Input Parameter: 7312 . mat - the matrix 7313 7314 Output Parameter: 7315 . bs - block size 7316 7317 Level: intermediate 7318 7319 Notes: 7320 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7321 7322 If the block size has not been set yet this routine returns 1. 7323 7324 .seealso: [](chapter_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()` 7325 @*/ 7326 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs) 7327 { 7328 PetscFunctionBegin; 7329 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7330 PetscValidIntPointer(bs, 2); 7331 *bs = PetscAbs(mat->rmap->bs); 7332 PetscFunctionReturn(PETSC_SUCCESS); 7333 } 7334 7335 /*@ 7336 MatGetBlockSizes - Returns the matrix block row and column sizes. 7337 7338 Not Collective 7339 7340 Input Parameter: 7341 . mat - the matrix 7342 7343 Output Parameters: 7344 + rbs - row block size 7345 - cbs - column block size 7346 7347 Level: intermediate 7348 7349 Notes: 7350 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7351 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7352 7353 If a block size has not been set yet this routine returns 1. 7354 7355 .seealso: [](chapter_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()` 7356 @*/ 7357 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs) 7358 { 7359 PetscFunctionBegin; 7360 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7361 if (rbs) PetscValidIntPointer(rbs, 2); 7362 if (cbs) PetscValidIntPointer(cbs, 3); 7363 if (rbs) *rbs = PetscAbs(mat->rmap->bs); 7364 if (cbs) *cbs = PetscAbs(mat->cmap->bs); 7365 PetscFunctionReturn(PETSC_SUCCESS); 7366 } 7367 7368 /*@ 7369 MatSetBlockSize - Sets the matrix block size. 7370 7371 Logically Collective 7372 7373 Input Parameters: 7374 + mat - the matrix 7375 - bs - block size 7376 7377 Level: intermediate 7378 7379 Notes: 7380 Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix. 7381 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7382 7383 For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size 7384 is compatible with the matrix local sizes. 7385 7386 .seealso: [](chapter_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()` 7387 @*/ 7388 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs) 7389 { 7390 PetscFunctionBegin; 7391 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7392 PetscValidLogicalCollectiveInt(mat, bs, 2); 7393 PetscCall(MatSetBlockSizes(mat, bs, bs)); 7394 PetscFunctionReturn(PETSC_SUCCESS); 7395 } 7396 7397 typedef struct { 7398 PetscInt n; 7399 IS *is; 7400 Mat *mat; 7401 PetscObjectState nonzerostate; 7402 Mat C; 7403 } EnvelopeData; 7404 7405 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata) 7406 { 7407 for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i])); 7408 PetscCall(PetscFree(edata->is)); 7409 PetscCall(PetscFree(edata)); 7410 return PETSC_SUCCESS; 7411 } 7412 7413 /* 7414 MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores 7415 the sizes of these blocks in the matrix. An individual block may lie over several processes. 7416 7417 Collective 7418 7419 Input Parameter: 7420 . mat - the matrix 7421 7422 Notes: 7423 There can be zeros within the blocks 7424 7425 The blocks can overlap between processes, including laying on more than two processes 7426 7427 .seealso: [](chapter_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()` 7428 */ 7429 static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat) 7430 { 7431 PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend; 7432 PetscInt *diag, *odiag, sc; 7433 VecScatter scatter; 7434 PetscScalar *seqv; 7435 const PetscScalar *parv; 7436 const PetscInt *ia, *ja; 7437 PetscBool set, flag, done; 7438 Mat AA = mat, A; 7439 MPI_Comm comm; 7440 PetscMPIInt rank, size, tag; 7441 MPI_Status status; 7442 PetscContainer container; 7443 EnvelopeData *edata; 7444 Vec seq, par; 7445 IS isglobal; 7446 7447 PetscFunctionBegin; 7448 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7449 PetscCall(MatIsSymmetricKnown(mat, &set, &flag)); 7450 if (!set || !flag) { 7451 /* TOO: only needs nonzero structure of transpose */ 7452 PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA)); 7453 PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN)); 7454 } 7455 PetscCall(MatAIJGetLocalMat(AA, &A)); 7456 PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7457 PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix"); 7458 7459 PetscCall(MatGetLocalSize(mat, &n, NULL)); 7460 PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag)); 7461 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 7462 PetscCallMPI(MPI_Comm_size(comm, &size)); 7463 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7464 7465 PetscCall(PetscMalloc2(n, &sizes, n, &starts)); 7466 7467 if (rank > 0) { 7468 PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7469 PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7470 } 7471 PetscCall(MatGetOwnershipRange(mat, &rstart, NULL)); 7472 for (i = 0; i < n; i++) { 7473 env = PetscMax(env, ja[ia[i + 1] - 1]); 7474 II = rstart + i; 7475 if (env == II) { 7476 starts[lblocks] = tbs; 7477 sizes[lblocks++] = 1 + II - tbs; 7478 tbs = 1 + II; 7479 } 7480 } 7481 if (rank < size - 1) { 7482 PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm)); 7483 PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm)); 7484 } 7485 7486 PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7487 if (!set || !flag) PetscCall(MatDestroy(&AA)); 7488 PetscCall(MatDestroy(&A)); 7489 7490 PetscCall(PetscNew(&edata)); 7491 PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate)); 7492 edata->n = lblocks; 7493 /* create IS needed for extracting blocks from the original matrix */ 7494 PetscCall(PetscMalloc1(lblocks, &edata->is)); 7495 for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i])); 7496 7497 /* Create the resulting inverse matrix structure with preallocation information */ 7498 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C)); 7499 PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 7500 PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat)); 7501 PetscCall(MatSetType(edata->C, MATAIJ)); 7502 7503 /* Communicate the start and end of each row, from each block to the correct rank */ 7504 /* TODO: Use PetscSF instead of VecScatter */ 7505 for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i]; 7506 PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq)); 7507 PetscCall(VecGetArrayWrite(seq, &seqv)); 7508 for (PetscInt i = 0; i < lblocks; i++) { 7509 for (PetscInt j = 0; j < sizes[i]; j++) { 7510 seqv[cnt] = starts[i]; 7511 seqv[cnt + 1] = starts[i] + sizes[i]; 7512 cnt += 2; 7513 } 7514 } 7515 PetscCall(VecRestoreArrayWrite(seq, &seqv)); 7516 PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 7517 sc -= cnt; 7518 PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par)); 7519 PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal)); 7520 PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter)); 7521 PetscCall(ISDestroy(&isglobal)); 7522 PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7523 PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7524 PetscCall(VecScatterDestroy(&scatter)); 7525 PetscCall(VecDestroy(&seq)); 7526 PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend)); 7527 PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag)); 7528 PetscCall(VecGetArrayRead(par, &parv)); 7529 cnt = 0; 7530 PetscCall(MatGetSize(mat, NULL, &n)); 7531 for (PetscInt i = 0; i < mat->rmap->n; i++) { 7532 PetscInt start, end, d = 0, od = 0; 7533 7534 start = (PetscInt)PetscRealPart(parv[cnt]); 7535 end = (PetscInt)PetscRealPart(parv[cnt + 1]); 7536 cnt += 2; 7537 7538 if (start < cstart) { 7539 od += cstart - start + n - cend; 7540 d += cend - cstart; 7541 } else if (start < cend) { 7542 od += n - cend; 7543 d += cend - start; 7544 } else od += n - start; 7545 if (end <= cstart) { 7546 od -= cstart - end + n - cend; 7547 d -= cend - cstart; 7548 } else if (end < cend) { 7549 od -= n - cend; 7550 d -= cend - end; 7551 } else od -= n - end; 7552 7553 odiag[i] = od; 7554 diag[i] = d; 7555 } 7556 PetscCall(VecRestoreArrayRead(par, &parv)); 7557 PetscCall(VecDestroy(&par)); 7558 PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL)); 7559 PetscCall(PetscFree2(diag, odiag)); 7560 PetscCall(PetscFree2(sizes, starts)); 7561 7562 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container)); 7563 PetscCall(PetscContainerSetPointer(container, edata)); 7564 PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy)); 7565 PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container)); 7566 PetscCall(PetscObjectDereference((PetscObject)container)); 7567 PetscFunctionReturn(PETSC_SUCCESS); 7568 } 7569 7570 /*@ 7571 MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A 7572 7573 Collective 7574 7575 Input Parameters: 7576 + A - the matrix 7577 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine 7578 7579 Output Parameter: 7580 . C - matrix with inverted block diagonal of `A` 7581 7582 Level: advanced 7583 7584 Note: 7585 For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal. 7586 7587 .seealso: [](chapter_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()` 7588 @*/ 7589 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C) 7590 { 7591 PetscContainer container; 7592 EnvelopeData *edata; 7593 PetscObjectState nonzerostate; 7594 7595 PetscFunctionBegin; 7596 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7597 if (!container) { 7598 PetscCall(MatComputeVariableBlockEnvelope(A)); 7599 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7600 } 7601 PetscCall(PetscContainerGetPointer(container, (void **)&edata)); 7602 PetscCall(MatGetNonzeroState(A, &nonzerostate)); 7603 PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure"); 7604 PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output"); 7605 7606 PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat)); 7607 *C = edata->C; 7608 7609 for (PetscInt i = 0; i < edata->n; i++) { 7610 Mat D; 7611 PetscScalar *dvalues; 7612 7613 PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D)); 7614 PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE)); 7615 PetscCall(MatSeqDenseInvert(D)); 7616 PetscCall(MatDenseGetArray(D, &dvalues)); 7617 PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES)); 7618 PetscCall(MatDestroy(&D)); 7619 } 7620 PetscCall(MatDestroySubMatrices(edata->n, &edata->mat)); 7621 PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY)); 7622 PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY)); 7623 PetscFunctionReturn(PETSC_SUCCESS); 7624 } 7625 7626 /*@ 7627 MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size 7628 7629 Logically Collective 7630 7631 Input Parameters: 7632 + mat - the matrix 7633 . nblocks - the number of blocks on this process, each block can only exist on a single process 7634 - bsizes - the block sizes 7635 7636 Level: intermediate 7637 7638 Notes: 7639 Currently used by `PCVPBJACOBI` for `MATAIJ` matrices 7640 7641 Each variable point-block set of degrees of freedom must live on a single MPI rank. That is a point block cannot straddle two MPI ranks. 7642 7643 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, 7644 `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI` 7645 @*/ 7646 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes) 7647 { 7648 PetscInt i, ncnt = 0, nlocal; 7649 7650 PetscFunctionBegin; 7651 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7652 PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero"); 7653 PetscCall(MatGetLocalSize(mat, &nlocal, NULL)); 7654 for (i = 0; i < nblocks; i++) ncnt += bsizes[i]; 7655 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); 7656 PetscCall(PetscFree(mat->bsizes)); 7657 mat->nblocks = nblocks; 7658 PetscCall(PetscMalloc1(nblocks, &mat->bsizes)); 7659 PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks)); 7660 PetscFunctionReturn(PETSC_SUCCESS); 7661 } 7662 7663 /*@C 7664 MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size 7665 7666 Logically Collective; No Fortran Support 7667 7668 Input Parameter: 7669 . mat - the matrix 7670 7671 Output Parameters: 7672 + nblocks - the number of blocks on this process 7673 - bsizes - the block sizes 7674 7675 Level: intermediate 7676 7677 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()` 7678 @*/ 7679 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes) 7680 { 7681 PetscFunctionBegin; 7682 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7683 *nblocks = mat->nblocks; 7684 *bsizes = mat->bsizes; 7685 PetscFunctionReturn(PETSC_SUCCESS); 7686 } 7687 7688 /*@ 7689 MatSetBlockSizes - Sets the matrix block row and column sizes. 7690 7691 Logically Collective 7692 7693 Input Parameters: 7694 + mat - the matrix 7695 . rbs - row block size 7696 - cbs - column block size 7697 7698 Level: intermediate 7699 7700 Notes: 7701 Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix. 7702 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7703 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7704 7705 For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes 7706 are compatible with the matrix local sizes. 7707 7708 The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`. 7709 7710 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()` 7711 @*/ 7712 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs) 7713 { 7714 PetscFunctionBegin; 7715 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7716 PetscValidLogicalCollectiveInt(mat, rbs, 2); 7717 PetscValidLogicalCollectiveInt(mat, cbs, 3); 7718 PetscTryTypeMethod(mat, setblocksizes, rbs, cbs); 7719 if (mat->rmap->refcnt) { 7720 ISLocalToGlobalMapping l2g = NULL; 7721 PetscLayout nmap = NULL; 7722 7723 PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap)); 7724 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g)); 7725 PetscCall(PetscLayoutDestroy(&mat->rmap)); 7726 mat->rmap = nmap; 7727 mat->rmap->mapping = l2g; 7728 } 7729 if (mat->cmap->refcnt) { 7730 ISLocalToGlobalMapping l2g = NULL; 7731 PetscLayout nmap = NULL; 7732 7733 PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap)); 7734 if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g)); 7735 PetscCall(PetscLayoutDestroy(&mat->cmap)); 7736 mat->cmap = nmap; 7737 mat->cmap->mapping = l2g; 7738 } 7739 PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs)); 7740 PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs)); 7741 PetscFunctionReturn(PETSC_SUCCESS); 7742 } 7743 7744 /*@ 7745 MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices 7746 7747 Logically Collective 7748 7749 Input Parameters: 7750 + mat - the matrix 7751 . fromRow - matrix from which to copy row block size 7752 - fromCol - matrix from which to copy column block size (can be same as fromRow) 7753 7754 Level: developer 7755 7756 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()` 7757 @*/ 7758 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol) 7759 { 7760 PetscFunctionBegin; 7761 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7762 PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2); 7763 PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3); 7764 if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs)); 7765 if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs)); 7766 PetscFunctionReturn(PETSC_SUCCESS); 7767 } 7768 7769 /*@ 7770 MatResidual - Default routine to calculate the residual r = b - Ax 7771 7772 Collective 7773 7774 Input Parameters: 7775 + mat - the matrix 7776 . b - the right-hand-side 7777 - x - the approximate solution 7778 7779 Output Parameter: 7780 . r - location to store the residual 7781 7782 Level: developer 7783 7784 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()` 7785 @*/ 7786 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r) 7787 { 7788 PetscFunctionBegin; 7789 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7790 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 7791 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 7792 PetscValidHeaderSpecific(r, VEC_CLASSID, 4); 7793 PetscValidType(mat, 1); 7794 MatCheckPreallocated(mat, 1); 7795 PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0)); 7796 if (!mat->ops->residual) { 7797 PetscCall(MatMult(mat, x, r)); 7798 PetscCall(VecAYPX(r, -1.0, b)); 7799 } else { 7800 PetscUseTypeMethod(mat, residual, b, x, r); 7801 } 7802 PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0)); 7803 PetscFunctionReturn(PETSC_SUCCESS); 7804 } 7805 7806 /*MC 7807 MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix 7808 7809 Synopsis: 7810 MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 7811 7812 Not Collective 7813 7814 Input Parameters: 7815 + A - the matrix 7816 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7817 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7818 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7819 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7820 always used. 7821 7822 Output Parameters: 7823 + n - number of local rows in the (possibly compressed) matrix 7824 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 7825 . ja - the column indices 7826 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7827 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7828 7829 Level: developer 7830 7831 Note: 7832 Use `MatRestoreRowIJF90()` when you no longer need access to the data 7833 7834 .seealso: [](chapter_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()` 7835 M*/ 7836 7837 /*MC 7838 MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()` 7839 7840 Synopsis: 7841 MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 7842 7843 Not Collective 7844 7845 Input Parameters: 7846 + A - the matrix 7847 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7848 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7849 inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7850 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7851 always used. 7852 . n - number of local rows in the (possibly compressed) matrix 7853 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 7854 . ja - the column indices 7855 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7856 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7857 7858 Level: developer 7859 7860 .seealso: [](chapter_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()` 7861 M*/ 7862 7863 /*@C 7864 MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix 7865 7866 Collective 7867 7868 Input Parameters: 7869 + mat - the matrix 7870 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7871 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7872 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7873 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7874 always used. 7875 7876 Output Parameters: 7877 + n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed 7878 . 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 7879 . ja - the column indices, use `NULL` if not needed 7880 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7881 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7882 7883 Level: developer 7884 7885 Notes: 7886 You CANNOT change any of the ia[] or ja[] values. 7887 7888 Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values. 7889 7890 Fortran Notes: 7891 Use 7892 .vb 7893 PetscInt, pointer :: ia(:),ja(:) 7894 call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr) 7895 ! Access the ith and jth entries via ia(i) and ja(j) 7896 .ve 7897 `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()` 7898 7899 .seealso: [](chapter_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()` 7900 @*/ 7901 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7902 { 7903 PetscFunctionBegin; 7904 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7905 PetscValidType(mat, 1); 7906 if (n) PetscValidIntPointer(n, 5); 7907 if (ia) PetscValidPointer(ia, 6); 7908 if (ja) PetscValidPointer(ja, 7); 7909 if (done) PetscValidBoolPointer(done, 8); 7910 MatCheckPreallocated(mat, 1); 7911 if (!mat->ops->getrowij && done) *done = PETSC_FALSE; 7912 else { 7913 if (done) *done = PETSC_TRUE; 7914 PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0)); 7915 PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done); 7916 PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0)); 7917 } 7918 PetscFunctionReturn(PETSC_SUCCESS); 7919 } 7920 7921 /*@C 7922 MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices. 7923 7924 Collective 7925 7926 Input Parameters: 7927 + mat - the matrix 7928 . shift - 1 or zero indicating we want the indices starting at 0 or 1 7929 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be 7930 symmetrized 7931 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7932 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7933 always used. 7934 . n - number of columns in the (possibly compressed) matrix 7935 . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix 7936 - ja - the row indices 7937 7938 Output Parameter: 7939 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned 7940 7941 Level: developer 7942 7943 .seealso: [](chapter_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 7944 @*/ 7945 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7946 { 7947 PetscFunctionBegin; 7948 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7949 PetscValidType(mat, 1); 7950 PetscValidIntPointer(n, 5); 7951 if (ia) PetscValidPointer(ia, 6); 7952 if (ja) PetscValidPointer(ja, 7); 7953 PetscValidBoolPointer(done, 8); 7954 MatCheckPreallocated(mat, 1); 7955 if (!mat->ops->getcolumnij) *done = PETSC_FALSE; 7956 else { 7957 *done = PETSC_TRUE; 7958 PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 7959 } 7960 PetscFunctionReturn(PETSC_SUCCESS); 7961 } 7962 7963 /*@C 7964 MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`. 7965 7966 Collective 7967 7968 Input Parameters: 7969 + mat - the matrix 7970 . shift - 1 or zero indicating we want the indices starting at 0 or 1 7971 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7972 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7973 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7974 always used. 7975 . n - size of (possibly compressed) matrix 7976 . ia - the row pointers 7977 - ja - the column indices 7978 7979 Output Parameter: 7980 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 7981 7982 Level: developer 7983 7984 Note: 7985 This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental 7986 us of the array after it has been restored. If you pass `NULL`, it will 7987 not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid. 7988 7989 Fortran Note: 7990 `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()` 7991 7992 .seealso: [](chapter_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()` 7993 @*/ 7994 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7995 { 7996 PetscFunctionBegin; 7997 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7998 PetscValidType(mat, 1); 7999 if (ia) PetscValidPointer(ia, 6); 8000 if (ja) PetscValidPointer(ja, 7); 8001 if (done) PetscValidBoolPointer(done, 8); 8002 MatCheckPreallocated(mat, 1); 8003 8004 if (!mat->ops->restorerowij && done) *done = PETSC_FALSE; 8005 else { 8006 if (done) *done = PETSC_TRUE; 8007 PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8008 if (n) *n = 0; 8009 if (ia) *ia = NULL; 8010 if (ja) *ja = NULL; 8011 } 8012 PetscFunctionReturn(PETSC_SUCCESS); 8013 } 8014 8015 /*@C 8016 MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`. 8017 8018 Collective 8019 8020 Input Parameters: 8021 + mat - the matrix 8022 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8023 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8024 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8025 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8026 always used. 8027 8028 Output Parameters: 8029 + n - size of (possibly compressed) matrix 8030 . ia - the column pointers 8031 . ja - the row indices 8032 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8033 8034 Level: developer 8035 8036 .seealso: [](chapter_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()` 8037 @*/ 8038 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8039 { 8040 PetscFunctionBegin; 8041 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8042 PetscValidType(mat, 1); 8043 if (ia) PetscValidPointer(ia, 6); 8044 if (ja) PetscValidPointer(ja, 7); 8045 PetscValidBoolPointer(done, 8); 8046 MatCheckPreallocated(mat, 1); 8047 8048 if (!mat->ops->restorecolumnij) *done = PETSC_FALSE; 8049 else { 8050 *done = PETSC_TRUE; 8051 PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8052 if (n) *n = 0; 8053 if (ia) *ia = NULL; 8054 if (ja) *ja = NULL; 8055 } 8056 PetscFunctionReturn(PETSC_SUCCESS); 8057 } 8058 8059 /*@C 8060 MatColoringPatch -Used inside matrix coloring routines that use `MatGetRowIJ()` and/or `MatGetColumnIJ()`. 8061 8062 Collective 8063 8064 Input Parameters: 8065 + mat - the matrix 8066 . ncolors - maximum color value 8067 . n - number of entries in colorarray 8068 - colorarray - array indicating color for each column 8069 8070 Output Parameter: 8071 . iscoloring - coloring generated using colorarray information 8072 8073 Level: developer 8074 8075 .seealso: [](chapter_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()` 8076 @*/ 8077 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring) 8078 { 8079 PetscFunctionBegin; 8080 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8081 PetscValidType(mat, 1); 8082 PetscValidIntPointer(colorarray, 4); 8083 PetscValidPointer(iscoloring, 5); 8084 MatCheckPreallocated(mat, 1); 8085 8086 if (!mat->ops->coloringpatch) { 8087 PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring)); 8088 } else { 8089 PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring); 8090 } 8091 PetscFunctionReturn(PETSC_SUCCESS); 8092 } 8093 8094 /*@ 8095 MatSetUnfactored - Resets a factored matrix to be treated as unfactored. 8096 8097 Logically Collective 8098 8099 Input Parameter: 8100 . mat - the factored matrix to be reset 8101 8102 Level: developer 8103 8104 Notes: 8105 This routine should be used only with factored matrices formed by in-place 8106 factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE` 8107 format). This option can save memory, for example, when solving nonlinear 8108 systems with a matrix-free Newton-Krylov method and a matrix-based, in-place 8109 ILU(0) preconditioner. 8110 8111 One can specify in-place ILU(0) factorization by calling 8112 .vb 8113 PCType(pc,PCILU); 8114 PCFactorSeUseInPlace(pc); 8115 .ve 8116 or by using the options -pc_type ilu -pc_factor_in_place 8117 8118 In-place factorization ILU(0) can also be used as a local 8119 solver for the blocks within the block Jacobi or additive Schwarz 8120 methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc 8121 for details on setting local solver options. 8122 8123 Most users should employ the `KSP` interface for linear solvers 8124 instead of working directly with matrix algebra routines such as this. 8125 See, e.g., `KSPCreate()`. 8126 8127 .seealso: [](chapter_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()` 8128 @*/ 8129 PetscErrorCode MatSetUnfactored(Mat mat) 8130 { 8131 PetscFunctionBegin; 8132 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8133 PetscValidType(mat, 1); 8134 MatCheckPreallocated(mat, 1); 8135 mat->factortype = MAT_FACTOR_NONE; 8136 if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS); 8137 PetscUseTypeMethod(mat, setunfactored); 8138 PetscFunctionReturn(PETSC_SUCCESS); 8139 } 8140 8141 /*MC 8142 MatDenseGetArrayF90 - Accesses a matrix array from Fortran 8143 8144 Synopsis: 8145 MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8146 8147 Not Collective 8148 8149 Input Parameter: 8150 . x - matrix 8151 8152 Output Parameters: 8153 + xx_v - the Fortran pointer to the array 8154 - ierr - error code 8155 8156 Example of Usage: 8157 .vb 8158 PetscScalar, pointer xx_v(:,:) 8159 .... 8160 call MatDenseGetArrayF90(x,xx_v,ierr) 8161 a = xx_v(3) 8162 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8163 .ve 8164 8165 Level: advanced 8166 8167 .seealso: [](chapter_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()` 8168 M*/ 8169 8170 /*MC 8171 MatDenseRestoreArrayF90 - Restores a matrix array that has been 8172 accessed with `MatDenseGetArrayF90()`. 8173 8174 Synopsis: 8175 MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8176 8177 Not Collective 8178 8179 Input Parameters: 8180 + x - matrix 8181 - xx_v - the Fortran90 pointer to the array 8182 8183 Output Parameter: 8184 . ierr - error code 8185 8186 Example of Usage: 8187 .vb 8188 PetscScalar, pointer xx_v(:,:) 8189 .... 8190 call MatDenseGetArrayF90(x,xx_v,ierr) 8191 a = xx_v(3) 8192 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8193 .ve 8194 8195 Level: advanced 8196 8197 .seealso: [](chapter_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()` 8198 M*/ 8199 8200 /*MC 8201 MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran. 8202 8203 Synopsis: 8204 MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8205 8206 Not Collective 8207 8208 Input Parameter: 8209 . x - matrix 8210 8211 Output Parameters: 8212 + xx_v - the Fortran pointer to the array 8213 - ierr - error code 8214 8215 Example of Usage: 8216 .vb 8217 PetscScalar, pointer xx_v(:) 8218 .... 8219 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8220 a = xx_v(3) 8221 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8222 .ve 8223 8224 Level: advanced 8225 8226 .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()` 8227 M*/ 8228 8229 /*MC 8230 MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been 8231 accessed with `MatSeqAIJGetArrayF90()`. 8232 8233 Synopsis: 8234 MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8235 8236 Not Collective 8237 8238 Input Parameters: 8239 + x - matrix 8240 - xx_v - the Fortran90 pointer to the array 8241 8242 Output Parameter: 8243 . ierr - error code 8244 8245 Example of Usage: 8246 .vb 8247 PetscScalar, pointer xx_v(:) 8248 .... 8249 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8250 a = xx_v(3) 8251 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8252 .ve 8253 8254 Level: advanced 8255 8256 .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()` 8257 M*/ 8258 8259 /*@ 8260 MatCreateSubMatrix - Gets a single submatrix on the same number of processors 8261 as the original matrix. 8262 8263 Collective 8264 8265 Input Parameters: 8266 + mat - the original matrix 8267 . isrow - parallel `IS` containing the rows this processor should obtain 8268 . 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. 8269 - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 8270 8271 Output Parameter: 8272 . newmat - the new submatrix, of the same type as the original matrix 8273 8274 Level: advanced 8275 8276 Notes: 8277 The submatrix will be able to be multiplied with vectors using the same layout as `iscol`. 8278 8279 Some matrix types place restrictions on the row and column indices, such 8280 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; 8281 for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row. 8282 8283 The index sets may not have duplicate entries. 8284 8285 The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`, 8286 the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls 8287 to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX` 8288 will reuse the matrix generated the first time. You should call `MatDestroy()` on `newmat` when 8289 you are finished using it. 8290 8291 The communicator of the newly obtained matrix is ALWAYS the same as the communicator of 8292 the input matrix. 8293 8294 If `iscol` is `NULL` then all columns are obtained (not supported in Fortran). 8295 8296 Example usage: 8297 Consider the following 8x8 matrix with 34 non-zero values, that is 8298 assembled across 3 processors. Let's assume that proc0 owns 3 rows, 8299 proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 8300 as follows 8301 .vb 8302 1 2 0 | 0 3 0 | 0 4 8303 Proc0 0 5 6 | 7 0 0 | 8 0 8304 9 0 10 | 11 0 0 | 12 0 8305 ------------------------------------- 8306 13 0 14 | 15 16 17 | 0 0 8307 Proc1 0 18 0 | 19 20 21 | 0 0 8308 0 0 0 | 22 23 0 | 24 0 8309 ------------------------------------- 8310 Proc2 25 26 27 | 0 0 28 | 29 0 8311 30 0 0 | 31 32 33 | 0 34 8312 .ve 8313 8314 Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6]. The resulting submatrix is 8315 8316 .vb 8317 2 0 | 0 3 0 | 0 8318 Proc0 5 6 | 7 0 0 | 8 8319 ------------------------------- 8320 Proc1 18 0 | 19 20 21 | 0 8321 ------------------------------- 8322 Proc2 26 27 | 0 0 28 | 29 8323 0 0 | 31 32 33 | 0 8324 .ve 8325 8326 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()` 8327 @*/ 8328 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat) 8329 { 8330 PetscMPIInt size; 8331 Mat *local; 8332 IS iscoltmp; 8333 PetscBool flg; 8334 8335 PetscFunctionBegin; 8336 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8337 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 8338 if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 8339 PetscValidPointer(newmat, 5); 8340 if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5); 8341 PetscValidType(mat, 1); 8342 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8343 PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX"); 8344 8345 MatCheckPreallocated(mat, 1); 8346 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8347 8348 if (!iscol || isrow == iscol) { 8349 PetscBool stride; 8350 PetscMPIInt grabentirematrix = 0, grab; 8351 PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride)); 8352 if (stride) { 8353 PetscInt first, step, n, rstart, rend; 8354 PetscCall(ISStrideGetInfo(isrow, &first, &step)); 8355 if (step == 1) { 8356 PetscCall(MatGetOwnershipRange(mat, &rstart, &rend)); 8357 if (rstart == first) { 8358 PetscCall(ISGetLocalSize(isrow, &n)); 8359 if (n == rend - rstart) grabentirematrix = 1; 8360 } 8361 } 8362 } 8363 PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat))); 8364 if (grab) { 8365 PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n")); 8366 if (cll == MAT_INITIAL_MATRIX) { 8367 *newmat = mat; 8368 PetscCall(PetscObjectReference((PetscObject)mat)); 8369 } 8370 PetscFunctionReturn(PETSC_SUCCESS); 8371 } 8372 } 8373 8374 if (!iscol) { 8375 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp)); 8376 } else { 8377 iscoltmp = iscol; 8378 } 8379 8380 /* if original matrix is on just one processor then use submatrix generated */ 8381 if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) { 8382 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat)); 8383 goto setproperties; 8384 } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) { 8385 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local)); 8386 *newmat = *local; 8387 PetscCall(PetscFree(local)); 8388 goto setproperties; 8389 } else if (!mat->ops->createsubmatrix) { 8390 /* Create a new matrix type that implements the operation using the full matrix */ 8391 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8392 switch (cll) { 8393 case MAT_INITIAL_MATRIX: 8394 PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat)); 8395 break; 8396 case MAT_REUSE_MATRIX: 8397 PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp)); 8398 break; 8399 default: 8400 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX"); 8401 } 8402 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8403 goto setproperties; 8404 } 8405 8406 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8407 PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat); 8408 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8409 8410 setproperties: 8411 PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg)); 8412 if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat)); 8413 if (!iscol) PetscCall(ISDestroy(&iscoltmp)); 8414 if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat)); 8415 PetscFunctionReturn(PETSC_SUCCESS); 8416 } 8417 8418 /*@ 8419 MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix 8420 8421 Not Collective 8422 8423 Input Parameters: 8424 + A - the matrix we wish to propagate options from 8425 - B - the matrix we wish to propagate options to 8426 8427 Level: beginner 8428 8429 Note: 8430 Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL` 8431 8432 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, MatIsStructurallySymmetricKnown()` 8433 @*/ 8434 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B) 8435 { 8436 PetscFunctionBegin; 8437 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8438 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 8439 B->symmetry_eternal = A->symmetry_eternal; 8440 B->structural_symmetry_eternal = A->structural_symmetry_eternal; 8441 B->symmetric = A->symmetric; 8442 B->structurally_symmetric = A->structurally_symmetric; 8443 B->spd = A->spd; 8444 B->hermitian = A->hermitian; 8445 PetscFunctionReturn(PETSC_SUCCESS); 8446 } 8447 8448 /*@ 8449 MatStashSetInitialSize - sets the sizes of the matrix stash, that is 8450 used during the assembly process to store values that belong to 8451 other processors. 8452 8453 Not Collective 8454 8455 Input Parameters: 8456 + mat - the matrix 8457 . size - the initial size of the stash. 8458 - bsize - the initial size of the block-stash(if used). 8459 8460 Options Database Keys: 8461 + -matstash_initial_size <size> or <size0,size1,...sizep-1> 8462 - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1> 8463 8464 Level: intermediate 8465 8466 Notes: 8467 The block-stash is used for values set with `MatSetValuesBlocked()` while 8468 the stash is used for values set with `MatSetValues()` 8469 8470 Run with the option -info and look for output of the form 8471 MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs. 8472 to determine the appropriate value, MM, to use for size and 8473 MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs. 8474 to determine the value, BMM to use for bsize 8475 8476 .seealso: [](chapter_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()` 8477 @*/ 8478 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize) 8479 { 8480 PetscFunctionBegin; 8481 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8482 PetscValidType(mat, 1); 8483 PetscCall(MatStashSetInitialSize_Private(&mat->stash, size)); 8484 PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize)); 8485 PetscFunctionReturn(PETSC_SUCCESS); 8486 } 8487 8488 /*@ 8489 MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of 8490 the matrix 8491 8492 Neighbor-wise Collective 8493 8494 Input Parameters: 8495 + mat - the matrix 8496 . x - the vector to be multiplied by the interpolation operator 8497 - y - the vector to be added to the result 8498 8499 Output Parameter: 8500 . w - the resulting vector 8501 8502 Level: intermediate 8503 8504 Notes: 8505 `w` may be the same vector as `y`. 8506 8507 This allows one to use either the restriction or interpolation (its transpose) 8508 matrix to do the interpolation 8509 8510 .seealso: [](chapter_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8511 @*/ 8512 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w) 8513 { 8514 PetscInt M, N, Ny; 8515 8516 PetscFunctionBegin; 8517 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8518 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8519 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8520 PetscValidHeaderSpecific(w, VEC_CLASSID, 4); 8521 PetscCall(MatGetSize(A, &M, &N)); 8522 PetscCall(VecGetSize(y, &Ny)); 8523 if (M == Ny) { 8524 PetscCall(MatMultAdd(A, x, y, w)); 8525 } else { 8526 PetscCall(MatMultTransposeAdd(A, x, y, w)); 8527 } 8528 PetscFunctionReturn(PETSC_SUCCESS); 8529 } 8530 8531 /*@ 8532 MatInterpolate - y = A*x or A'*x depending on the shape of 8533 the matrix 8534 8535 Neighbor-wise Collective 8536 8537 Input Parameters: 8538 + mat - the matrix 8539 - x - the vector to be interpolated 8540 8541 Output Parameter: 8542 . y - the resulting vector 8543 8544 Level: intermediate 8545 8546 Note: 8547 This allows one to use either the restriction or interpolation (its transpose) 8548 matrix to do the interpolation 8549 8550 .seealso: [](chapter_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8551 @*/ 8552 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y) 8553 { 8554 PetscInt M, N, Ny; 8555 8556 PetscFunctionBegin; 8557 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8558 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8559 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8560 PetscCall(MatGetSize(A, &M, &N)); 8561 PetscCall(VecGetSize(y, &Ny)); 8562 if (M == Ny) { 8563 PetscCall(MatMult(A, x, y)); 8564 } else { 8565 PetscCall(MatMultTranspose(A, x, y)); 8566 } 8567 PetscFunctionReturn(PETSC_SUCCESS); 8568 } 8569 8570 /*@ 8571 MatRestrict - y = A*x or A'*x 8572 8573 Neighbor-wise Collective 8574 8575 Input Parameters: 8576 + mat - the matrix 8577 - x - the vector to be restricted 8578 8579 Output Parameter: 8580 . y - the resulting vector 8581 8582 Level: intermediate 8583 8584 Note: 8585 This allows one to use either the restriction or interpolation (its transpose) 8586 matrix to do the restriction 8587 8588 .seealso: [](chapter_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG` 8589 @*/ 8590 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y) 8591 { 8592 PetscInt M, N, Ny; 8593 8594 PetscFunctionBegin; 8595 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8596 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8597 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8598 PetscCall(MatGetSize(A, &M, &N)); 8599 PetscCall(VecGetSize(y, &Ny)); 8600 if (M == Ny) { 8601 PetscCall(MatMult(A, x, y)); 8602 } else { 8603 PetscCall(MatMultTranspose(A, x, y)); 8604 } 8605 PetscFunctionReturn(PETSC_SUCCESS); 8606 } 8607 8608 /*@ 8609 MatMatInterpolateAdd - Y = W + A*X or W + A'*X 8610 8611 Neighbor-wise Collective 8612 8613 Input Parameters: 8614 + mat - the matrix 8615 . x - the input dense matrix to be multiplied 8616 - w - the input dense matrix to be added to the result 8617 8618 Output Parameter: 8619 . y - the output dense matrix 8620 8621 Level: intermediate 8622 8623 Note: 8624 This allows one to use either the restriction or interpolation (its transpose) 8625 matrix to do the interpolation. y matrix can be reused if already created with the proper sizes, 8626 otherwise it will be recreated. y must be initialized to `NULL` if not supplied. 8627 8628 .seealso: [](chapter_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG` 8629 @*/ 8630 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y) 8631 { 8632 PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0; 8633 PetscBool trans = PETSC_TRUE; 8634 MatReuse reuse = MAT_INITIAL_MATRIX; 8635 8636 PetscFunctionBegin; 8637 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8638 PetscValidHeaderSpecific(x, MAT_CLASSID, 2); 8639 PetscValidType(x, 2); 8640 if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3); 8641 if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4); 8642 PetscCall(MatGetSize(A, &M, &N)); 8643 PetscCall(MatGetSize(x, &Mx, &Nx)); 8644 if (N == Mx) trans = PETSC_FALSE; 8645 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); 8646 Mo = trans ? N : M; 8647 if (*y) { 8648 PetscCall(MatGetSize(*y, &My, &Ny)); 8649 if (Mo == My && Nx == Ny) { 8650 reuse = MAT_REUSE_MATRIX; 8651 } else { 8652 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); 8653 PetscCall(MatDestroy(y)); 8654 } 8655 } 8656 8657 if (w && *y == w) { /* this is to minimize changes in PCMG */ 8658 PetscBool flg; 8659 8660 PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w)); 8661 if (w) { 8662 PetscInt My, Ny, Mw, Nw; 8663 8664 PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg)); 8665 PetscCall(MatGetSize(*y, &My, &Ny)); 8666 PetscCall(MatGetSize(w, &Mw, &Nw)); 8667 if (!flg || My != Mw || Ny != Nw) w = NULL; 8668 } 8669 if (!w) { 8670 PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w)); 8671 PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w)); 8672 PetscCall(PetscObjectDereference((PetscObject)w)); 8673 } else { 8674 PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN)); 8675 } 8676 } 8677 if (!trans) { 8678 PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8679 } else { 8680 PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8681 } 8682 if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN)); 8683 PetscFunctionReturn(PETSC_SUCCESS); 8684 } 8685 8686 /*@ 8687 MatMatInterpolate - Y = A*X or A'*X 8688 8689 Neighbor-wise Collective 8690 8691 Input Parameters: 8692 + mat - the matrix 8693 - x - the input dense matrix 8694 8695 Output Parameter: 8696 . y - the output dense matrix 8697 8698 Level: intermediate 8699 8700 Note: 8701 This allows one to use either the restriction or interpolation (its transpose) 8702 matrix to do the interpolation. y matrix can be reused if already created with the proper sizes, 8703 otherwise it will be recreated. y must be initialized to `NULL` if not supplied. 8704 8705 .seealso: [](chapter_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG` 8706 @*/ 8707 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y) 8708 { 8709 PetscFunctionBegin; 8710 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8711 PetscFunctionReturn(PETSC_SUCCESS); 8712 } 8713 8714 /*@ 8715 MatMatRestrict - Y = A*X or A'*X 8716 8717 Neighbor-wise Collective 8718 8719 Input Parameters: 8720 + mat - the matrix 8721 - x - the input dense matrix 8722 8723 Output Parameter: 8724 . y - the output dense matrix 8725 8726 Level: intermediate 8727 8728 Note: 8729 This allows one to use either the restriction or interpolation (its transpose) 8730 matrix to do the restriction. y matrix can be reused if already created with the proper sizes, 8731 otherwise it will be recreated. y must be initialized to `NULL` if not supplied. 8732 8733 .seealso: [](chapter_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG` 8734 @*/ 8735 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y) 8736 { 8737 PetscFunctionBegin; 8738 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8739 PetscFunctionReturn(PETSC_SUCCESS); 8740 } 8741 8742 /*@ 8743 MatGetNullSpace - retrieves the null space of a matrix. 8744 8745 Logically Collective 8746 8747 Input Parameters: 8748 + mat - the matrix 8749 - nullsp - the null space object 8750 8751 Level: developer 8752 8753 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace` 8754 @*/ 8755 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp) 8756 { 8757 PetscFunctionBegin; 8758 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8759 PetscValidPointer(nullsp, 2); 8760 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp; 8761 PetscFunctionReturn(PETSC_SUCCESS); 8762 } 8763 8764 /*@ 8765 MatSetNullSpace - attaches a null space to a matrix. 8766 8767 Logically Collective 8768 8769 Input Parameters: 8770 + mat - the matrix 8771 - nullsp - the null space object 8772 8773 Level: advanced 8774 8775 Notes: 8776 This null space is used by the `KSP` linear solvers to solve singular systems. 8777 8778 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` 8779 8780 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 8781 to zero but the linear system will still be solved in a least squares sense. 8782 8783 The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that 8784 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). 8785 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 8786 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 8787 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). 8788 This \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix. 8789 8790 If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called 8791 `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this 8792 routine also automatically calls `MatSetTransposeNullSpace()`. 8793 8794 The user should call `MatNullSpaceDestroy()`. 8795 8796 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, 8797 `KSPSetPCSide()` 8798 @*/ 8799 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp) 8800 { 8801 PetscFunctionBegin; 8802 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8803 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8804 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8805 PetscCall(MatNullSpaceDestroy(&mat->nullsp)); 8806 mat->nullsp = nullsp; 8807 if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp)); 8808 PetscFunctionReturn(PETSC_SUCCESS); 8809 } 8810 8811 /*@ 8812 MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix. 8813 8814 Logically Collective 8815 8816 Input Parameters: 8817 + mat - the matrix 8818 - nullsp - the null space object 8819 8820 Level: developer 8821 8822 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()` 8823 @*/ 8824 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp) 8825 { 8826 PetscFunctionBegin; 8827 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8828 PetscValidType(mat, 1); 8829 PetscValidPointer(nullsp, 2); 8830 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp; 8831 PetscFunctionReturn(PETSC_SUCCESS); 8832 } 8833 8834 /*@ 8835 MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix 8836 8837 Logically Collective 8838 8839 Input Parameters: 8840 + mat - the matrix 8841 - nullsp - the null space object 8842 8843 Level: advanced 8844 8845 Notes: 8846 This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning. 8847 8848 See `MatSetNullSpace()` 8849 8850 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()` 8851 @*/ 8852 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp) 8853 { 8854 PetscFunctionBegin; 8855 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8856 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8857 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8858 PetscCall(MatNullSpaceDestroy(&mat->transnullsp)); 8859 mat->transnullsp = nullsp; 8860 PetscFunctionReturn(PETSC_SUCCESS); 8861 } 8862 8863 /*@ 8864 MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions 8865 This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix. 8866 8867 Logically Collective 8868 8869 Input Parameters: 8870 + mat - the matrix 8871 - nullsp - the null space object 8872 8873 Level: advanced 8874 8875 Notes: 8876 Overwrites any previous near null space that may have been attached 8877 8878 You can remove the null space by calling this routine with an nullsp of `NULL` 8879 8880 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()` 8881 @*/ 8882 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp) 8883 { 8884 PetscFunctionBegin; 8885 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8886 PetscValidType(mat, 1); 8887 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8888 MatCheckPreallocated(mat, 1); 8889 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8890 PetscCall(MatNullSpaceDestroy(&mat->nearnullsp)); 8891 mat->nearnullsp = nullsp; 8892 PetscFunctionReturn(PETSC_SUCCESS); 8893 } 8894 8895 /*@ 8896 MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()` 8897 8898 Not Collective 8899 8900 Input Parameter: 8901 . mat - the matrix 8902 8903 Output Parameter: 8904 . nullsp - the null space object, `NULL` if not set 8905 8906 Level: advanced 8907 8908 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()` 8909 @*/ 8910 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp) 8911 { 8912 PetscFunctionBegin; 8913 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8914 PetscValidType(mat, 1); 8915 PetscValidPointer(nullsp, 2); 8916 MatCheckPreallocated(mat, 1); 8917 *nullsp = mat->nearnullsp; 8918 PetscFunctionReturn(PETSC_SUCCESS); 8919 } 8920 8921 /*@C 8922 MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix. 8923 8924 Collective 8925 8926 Input Parameters: 8927 + mat - the matrix 8928 . row - row/column permutation 8929 - info - information on desired factorization process 8930 8931 Level: developer 8932 8933 Notes: 8934 Probably really in-place only when level of fill is zero, otherwise allocates 8935 new space to store factored matrix and deletes previous memory. 8936 8937 Most users should employ the `KSP` interface for linear solvers 8938 instead of working directly with matrix algebra routines such as this. 8939 See, e.g., `KSPCreate()`. 8940 8941 Developer Note: 8942 The Fortran interface is not autogenerated as the 8943 interface definition cannot be generated correctly [due to `MatFactorInfo`] 8944 8945 .seealso: [](chapter_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 8946 @*/ 8947 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info) 8948 { 8949 PetscFunctionBegin; 8950 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8951 PetscValidType(mat, 1); 8952 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 8953 PetscValidPointer(info, 3); 8954 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 8955 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 8956 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8957 MatCheckPreallocated(mat, 1); 8958 PetscUseTypeMethod(mat, iccfactor, row, info); 8959 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 8960 PetscFunctionReturn(PETSC_SUCCESS); 8961 } 8962 8963 /*@ 8964 MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the 8965 ghosted ones. 8966 8967 Not Collective 8968 8969 Input Parameters: 8970 + mat - the matrix 8971 - diag - the diagonal values, including ghost ones 8972 8973 Level: developer 8974 8975 Notes: 8976 Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices 8977 8978 This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()` 8979 8980 .seealso: [](chapter_matrices), `Mat`, `MatDiagonalScale()` 8981 @*/ 8982 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag) 8983 { 8984 PetscMPIInt size; 8985 8986 PetscFunctionBegin; 8987 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8988 PetscValidHeaderSpecific(diag, VEC_CLASSID, 2); 8989 PetscValidType(mat, 1); 8990 8991 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled"); 8992 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 8993 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8994 if (size == 1) { 8995 PetscInt n, m; 8996 PetscCall(VecGetSize(diag, &n)); 8997 PetscCall(MatGetSize(mat, NULL, &m)); 8998 PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions"); 8999 PetscCall(MatDiagonalScale(mat, NULL, diag)); 9000 } else { 9001 PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag)); 9002 } 9003 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 9004 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9005 PetscFunctionReturn(PETSC_SUCCESS); 9006 } 9007 9008 /*@ 9009 MatGetInertia - Gets the inertia from a factored matrix 9010 9011 Collective 9012 9013 Input Parameter: 9014 . mat - the matrix 9015 9016 Output Parameters: 9017 + nneg - number of negative eigenvalues 9018 . nzero - number of zero eigenvalues 9019 - npos - number of positive eigenvalues 9020 9021 Level: advanced 9022 9023 Note: 9024 Matrix must have been factored by `MatCholeskyFactor()` 9025 9026 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()` 9027 @*/ 9028 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos) 9029 { 9030 PetscFunctionBegin; 9031 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9032 PetscValidType(mat, 1); 9033 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9034 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled"); 9035 PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos); 9036 PetscFunctionReturn(PETSC_SUCCESS); 9037 } 9038 9039 /*@C 9040 MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors 9041 9042 Neighbor-wise Collective 9043 9044 Input Parameters: 9045 + mat - the factored matrix obtained with `MatGetFactor()` 9046 - b - the right-hand-side vectors 9047 9048 Output Parameter: 9049 . x - the result vectors 9050 9051 Level: developer 9052 9053 Note: 9054 The vectors `b` and `x` cannot be the same. I.e., one cannot 9055 call `MatSolves`(A,x,x). 9056 9057 .seealso: [](chapter_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()` 9058 @*/ 9059 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x) 9060 { 9061 PetscFunctionBegin; 9062 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9063 PetscValidType(mat, 1); 9064 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 9065 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9066 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 9067 9068 MatCheckPreallocated(mat, 1); 9069 PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0)); 9070 PetscUseTypeMethod(mat, solves, b, x); 9071 PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0)); 9072 PetscFunctionReturn(PETSC_SUCCESS); 9073 } 9074 9075 /*@ 9076 MatIsSymmetric - Test whether a matrix is symmetric 9077 9078 Collective 9079 9080 Input Parameters: 9081 + A - the matrix to test 9082 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose) 9083 9084 Output Parameter: 9085 . flg - the result 9086 9087 Level: intermediate 9088 9089 Notes: 9090 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9091 9092 If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()` 9093 9094 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9095 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9096 9097 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`, 9098 `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()` 9099 @*/ 9100 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg) 9101 { 9102 PetscFunctionBegin; 9103 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9104 PetscValidBoolPointer(flg, 3); 9105 9106 if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE; 9107 else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE; 9108 else { 9109 PetscUseTypeMethod(A, issymmetric, tol, flg); 9110 if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg)); 9111 } 9112 PetscFunctionReturn(PETSC_SUCCESS); 9113 } 9114 9115 /*@ 9116 MatIsHermitian - Test whether a matrix is Hermitian 9117 9118 Collective 9119 9120 Input Parameters: 9121 + A - the matrix to test 9122 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian) 9123 9124 Output Parameter: 9125 . flg - the result 9126 9127 Level: intermediate 9128 9129 Notes: 9130 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9131 9132 If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()` 9133 9134 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9135 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`) 9136 9137 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, 9138 `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()` 9139 @*/ 9140 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg) 9141 { 9142 PetscFunctionBegin; 9143 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9144 PetscValidBoolPointer(flg, 3); 9145 9146 if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE; 9147 else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE; 9148 else { 9149 PetscUseTypeMethod(A, ishermitian, tol, flg); 9150 if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg)); 9151 } 9152 PetscFunctionReturn(PETSC_SUCCESS); 9153 } 9154 9155 /*@ 9156 MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state 9157 9158 Not Collective 9159 9160 Input Parameter: 9161 . A - the matrix to check 9162 9163 Output Parameters: 9164 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid) 9165 - flg - the result (only valid if set is `PETSC_TRUE`) 9166 9167 Level: advanced 9168 9169 Notes: 9170 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()` 9171 if you want it explicitly checked 9172 9173 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9174 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9175 9176 .seealso: [](chapter_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9177 @*/ 9178 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9179 { 9180 PetscFunctionBegin; 9181 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9182 PetscValidBoolPointer(set, 2); 9183 PetscValidBoolPointer(flg, 3); 9184 if (A->symmetric != PETSC_BOOL3_UNKNOWN) { 9185 *set = PETSC_TRUE; 9186 *flg = PetscBool3ToBool(A->symmetric); 9187 } else { 9188 *set = PETSC_FALSE; 9189 } 9190 PetscFunctionReturn(PETSC_SUCCESS); 9191 } 9192 9193 /*@ 9194 MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state 9195 9196 Not Collective 9197 9198 Input Parameter: 9199 . A - the matrix to check 9200 9201 Output Parameters: 9202 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid) 9203 - flg - the result (only valid if set is `PETSC_TRUE`) 9204 9205 Level: advanced 9206 9207 Notes: 9208 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). 9209 9210 One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD 9211 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`) 9212 9213 .seealso: [](chapter_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9214 @*/ 9215 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg) 9216 { 9217 PetscFunctionBegin; 9218 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9219 PetscValidBoolPointer(set, 2); 9220 PetscValidBoolPointer(flg, 3); 9221 if (A->spd != PETSC_BOOL3_UNKNOWN) { 9222 *set = PETSC_TRUE; 9223 *flg = PetscBool3ToBool(A->spd); 9224 } else { 9225 *set = PETSC_FALSE; 9226 } 9227 PetscFunctionReturn(PETSC_SUCCESS); 9228 } 9229 9230 /*@ 9231 MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state 9232 9233 Not Collective 9234 9235 Input Parameter: 9236 . A - the matrix to check 9237 9238 Output Parameters: 9239 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid) 9240 - flg - the result (only valid if set is `PETSC_TRUE`) 9241 9242 Level: advanced 9243 9244 Notes: 9245 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()` 9246 if you want it explicitly checked 9247 9248 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9249 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9250 9251 .seealso: [](chapter_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()` 9252 @*/ 9253 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg) 9254 { 9255 PetscFunctionBegin; 9256 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9257 PetscValidBoolPointer(set, 2); 9258 PetscValidBoolPointer(flg, 3); 9259 if (A->hermitian != PETSC_BOOL3_UNKNOWN) { 9260 *set = PETSC_TRUE; 9261 *flg = PetscBool3ToBool(A->hermitian); 9262 } else { 9263 *set = PETSC_FALSE; 9264 } 9265 PetscFunctionReturn(PETSC_SUCCESS); 9266 } 9267 9268 /*@ 9269 MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric 9270 9271 Collective 9272 9273 Input Parameter: 9274 . A - the matrix to test 9275 9276 Output Parameter: 9277 . flg - the result 9278 9279 Level: intermediate 9280 9281 Notes: 9282 If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()` 9283 9284 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 9285 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9286 9287 .seealso: [](chapter_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()` 9288 @*/ 9289 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg) 9290 { 9291 PetscFunctionBegin; 9292 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9293 PetscValidBoolPointer(flg, 2); 9294 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9295 *flg = PetscBool3ToBool(A->structurally_symmetric); 9296 } else { 9297 PetscUseTypeMethod(A, isstructurallysymmetric, flg); 9298 PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg)); 9299 } 9300 PetscFunctionReturn(PETSC_SUCCESS); 9301 } 9302 9303 /*@ 9304 MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state 9305 9306 Not Collective 9307 9308 Input Parameter: 9309 . A - the matrix to check 9310 9311 Output Parameters: 9312 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid) 9313 - flg - the result (only valid if set is PETSC_TRUE) 9314 9315 Level: advanced 9316 9317 Notes: 9318 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 9319 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9320 9321 Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation) 9322 9323 .seealso: [](chapter_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9324 @*/ 9325 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9326 { 9327 PetscFunctionBegin; 9328 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9329 PetscValidBoolPointer(set, 2); 9330 PetscValidBoolPointer(flg, 3); 9331 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9332 *set = PETSC_TRUE; 9333 *flg = PetscBool3ToBool(A->structurally_symmetric); 9334 } else { 9335 *set = PETSC_FALSE; 9336 } 9337 PetscFunctionReturn(PETSC_SUCCESS); 9338 } 9339 9340 /*@ 9341 MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need 9342 to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process 9343 9344 Not Collective 9345 9346 Input Parameter: 9347 . mat - the matrix 9348 9349 Output Parameters: 9350 + nstash - the size of the stash 9351 . reallocs - the number of additional mallocs incurred. 9352 . bnstash - the size of the block stash 9353 - breallocs - the number of additional mallocs incurred.in the block stash 9354 9355 Level: advanced 9356 9357 .seealso: [](chapter_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()` 9358 @*/ 9359 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs) 9360 { 9361 PetscFunctionBegin; 9362 PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs)); 9363 PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs)); 9364 PetscFunctionReturn(PETSC_SUCCESS); 9365 } 9366 9367 /*@C 9368 MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same 9369 parallel layout, `PetscLayout` for rows and columns 9370 9371 Collective 9372 9373 Input Parameter: 9374 . mat - the matrix 9375 9376 Output Parameters: 9377 + right - (optional) vector that the matrix can be multiplied against 9378 - left - (optional) vector that the matrix vector product can be stored in 9379 9380 Level: advanced 9381 9382 Notes: 9383 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()`. 9384 9385 These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed 9386 9387 .seealso: [](chapter_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()` 9388 @*/ 9389 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left) 9390 { 9391 PetscFunctionBegin; 9392 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9393 PetscValidType(mat, 1); 9394 if (mat->ops->getvecs) { 9395 PetscUseTypeMethod(mat, getvecs, right, left); 9396 } else { 9397 PetscInt rbs, cbs; 9398 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 9399 if (right) { 9400 PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup"); 9401 PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), right)); 9402 PetscCall(VecSetSizes(*right, mat->cmap->n, PETSC_DETERMINE)); 9403 PetscCall(VecSetBlockSize(*right, cbs)); 9404 PetscCall(VecSetType(*right, mat->defaultvectype)); 9405 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9406 if (mat->boundtocpu && mat->bindingpropagates) { 9407 PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE)); 9408 PetscCall(VecBindToCPU(*right, PETSC_TRUE)); 9409 } 9410 #endif 9411 PetscCall(PetscLayoutReference(mat->cmap, &(*right)->map)); 9412 } 9413 if (left) { 9414 PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup"); 9415 PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), left)); 9416 PetscCall(VecSetSizes(*left, mat->rmap->n, PETSC_DETERMINE)); 9417 PetscCall(VecSetBlockSize(*left, rbs)); 9418 PetscCall(VecSetType(*left, mat->defaultvectype)); 9419 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9420 if (mat->boundtocpu && mat->bindingpropagates) { 9421 PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE)); 9422 PetscCall(VecBindToCPU(*left, PETSC_TRUE)); 9423 } 9424 #endif 9425 PetscCall(PetscLayoutReference(mat->rmap, &(*left)->map)); 9426 } 9427 } 9428 PetscFunctionReturn(PETSC_SUCCESS); 9429 } 9430 9431 /*@C 9432 MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure 9433 with default values. 9434 9435 Not Collective 9436 9437 Input Parameter: 9438 . info - the `MatFactorInfo` data structure 9439 9440 Level: developer 9441 9442 Notes: 9443 The solvers are generally used through the `KSP` and `PC` objects, for example 9444 `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC` 9445 9446 Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed 9447 9448 Developer Note: 9449 The Fortran interface is not autogenerated as the 9450 interface definition cannot be generated correctly [due to `MatFactorInfo`] 9451 9452 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo` 9453 @*/ 9454 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info) 9455 { 9456 PetscFunctionBegin; 9457 PetscCall(PetscMemzero(info, sizeof(MatFactorInfo))); 9458 PetscFunctionReturn(PETSC_SUCCESS); 9459 } 9460 9461 /*@ 9462 MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed 9463 9464 Collective 9465 9466 Input Parameters: 9467 + mat - the factored matrix 9468 - is - the index set defining the Schur indices (0-based) 9469 9470 Level: advanced 9471 9472 Notes: 9473 Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system. 9474 9475 You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call. 9476 9477 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9478 9479 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`, 9480 `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9481 @*/ 9482 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is) 9483 { 9484 PetscErrorCode (*f)(Mat, IS); 9485 9486 PetscFunctionBegin; 9487 PetscValidType(mat, 1); 9488 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9489 PetscValidType(is, 2); 9490 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 9491 PetscCheckSameComm(mat, 1, is, 2); 9492 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 9493 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f)); 9494 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO"); 9495 PetscCall(MatDestroy(&mat->schur)); 9496 PetscCall((*f)(mat, is)); 9497 PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created"); 9498 PetscFunctionReturn(PETSC_SUCCESS); 9499 } 9500 9501 /*@ 9502 MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step 9503 9504 Logically Collective 9505 9506 Input Parameters: 9507 + F - the factored matrix obtained by calling `MatGetFactor()` 9508 . S - location where to return the Schur complement, can be `NULL` 9509 - status - the status of the Schur complement matrix, can be `NULL` 9510 9511 Level: advanced 9512 9513 Notes: 9514 You must call `MatFactorSetSchurIS()` before calling this routine. 9515 9516 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9517 9518 The routine provides a copy of the Schur matrix stored within the solver data structures. 9519 The caller must destroy the object when it is no longer needed. 9520 If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse. 9521 9522 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) 9523 9524 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9525 9526 Developer Note: 9527 The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc 9528 matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix. 9529 9530 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9531 @*/ 9532 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9533 { 9534 PetscFunctionBegin; 9535 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9536 if (S) PetscValidPointer(S, 2); 9537 if (status) PetscValidPointer(status, 3); 9538 if (S) { 9539 PetscErrorCode (*f)(Mat, Mat *); 9540 9541 PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f)); 9542 if (f) { 9543 PetscCall((*f)(F, S)); 9544 } else { 9545 PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S)); 9546 } 9547 } 9548 if (status) *status = F->schur_status; 9549 PetscFunctionReturn(PETSC_SUCCESS); 9550 } 9551 9552 /*@ 9553 MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix 9554 9555 Logically Collective 9556 9557 Input Parameters: 9558 + F - the factored matrix obtained by calling `MatGetFactor()` 9559 . *S - location where to return the Schur complement, can be `NULL` 9560 - status - the status of the Schur complement matrix, can be `NULL` 9561 9562 Level: advanced 9563 9564 Notes: 9565 You must call `MatFactorSetSchurIS()` before calling this routine. 9566 9567 Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS` 9568 9569 The routine returns a the Schur Complement stored within the data structures of the solver. 9570 9571 If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement. 9572 9573 The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed. 9574 9575 Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix 9576 9577 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9578 9579 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9580 @*/ 9581 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9582 { 9583 PetscFunctionBegin; 9584 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9585 if (S) PetscValidPointer(S, 2); 9586 if (status) PetscValidPointer(status, 3); 9587 if (S) *S = F->schur; 9588 if (status) *status = F->schur_status; 9589 PetscFunctionReturn(PETSC_SUCCESS); 9590 } 9591 9592 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F) 9593 { 9594 Mat S = F->schur; 9595 9596 PetscFunctionBegin; 9597 switch (F->schur_status) { 9598 case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through 9599 case MAT_FACTOR_SCHUR_INVERTED: 9600 if (S) { 9601 S->ops->solve = NULL; 9602 S->ops->matsolve = NULL; 9603 S->ops->solvetranspose = NULL; 9604 S->ops->matsolvetranspose = NULL; 9605 S->ops->solveadd = NULL; 9606 S->ops->solvetransposeadd = NULL; 9607 S->factortype = MAT_FACTOR_NONE; 9608 PetscCall(PetscFree(S->solvertype)); 9609 } 9610 case MAT_FACTOR_SCHUR_FACTORED: // fall-through 9611 break; 9612 default: 9613 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9614 } 9615 PetscFunctionReturn(PETSC_SUCCESS); 9616 } 9617 9618 /*@ 9619 MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()` 9620 9621 Logically Collective 9622 9623 Input Parameters: 9624 + F - the factored matrix obtained by calling `MatGetFactor()` 9625 . *S - location where the Schur complement is stored 9626 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`) 9627 9628 Level: advanced 9629 9630 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9631 @*/ 9632 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status) 9633 { 9634 PetscFunctionBegin; 9635 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9636 if (S) { 9637 PetscValidHeaderSpecific(*S, MAT_CLASSID, 2); 9638 *S = NULL; 9639 } 9640 F->schur_status = status; 9641 PetscCall(MatFactorUpdateSchurStatus_Private(F)); 9642 PetscFunctionReturn(PETSC_SUCCESS); 9643 } 9644 9645 /*@ 9646 MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step 9647 9648 Logically Collective 9649 9650 Input Parameters: 9651 + F - the factored matrix obtained by calling `MatGetFactor()` 9652 . rhs - location where the right hand side of the Schur complement system is stored 9653 - sol - location where the solution of the Schur complement system has to be returned 9654 9655 Level: advanced 9656 9657 Notes: 9658 The sizes of the vectors should match the size of the Schur complement 9659 9660 Must be called after `MatFactorSetSchurIS()` 9661 9662 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()` 9663 @*/ 9664 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol) 9665 { 9666 PetscFunctionBegin; 9667 PetscValidType(F, 1); 9668 PetscValidType(rhs, 2); 9669 PetscValidType(sol, 3); 9670 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9671 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9672 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9673 PetscCheckSameComm(F, 1, rhs, 2); 9674 PetscCheckSameComm(F, 1, sol, 3); 9675 PetscCall(MatFactorFactorizeSchurComplement(F)); 9676 switch (F->schur_status) { 9677 case MAT_FACTOR_SCHUR_FACTORED: 9678 PetscCall(MatSolveTranspose(F->schur, rhs, sol)); 9679 break; 9680 case MAT_FACTOR_SCHUR_INVERTED: 9681 PetscCall(MatMultTranspose(F->schur, rhs, sol)); 9682 break; 9683 default: 9684 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9685 } 9686 PetscFunctionReturn(PETSC_SUCCESS); 9687 } 9688 9689 /*@ 9690 MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step 9691 9692 Logically Collective 9693 9694 Input Parameters: 9695 + F - the factored matrix obtained by calling `MatGetFactor()` 9696 . rhs - location where the right hand side of the Schur complement system is stored 9697 - sol - location where the solution of the Schur complement system has to be returned 9698 9699 Level: advanced 9700 9701 Notes: 9702 The sizes of the vectors should match the size of the Schur complement 9703 9704 Must be called after `MatFactorSetSchurIS()` 9705 9706 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()` 9707 @*/ 9708 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol) 9709 { 9710 PetscFunctionBegin; 9711 PetscValidType(F, 1); 9712 PetscValidType(rhs, 2); 9713 PetscValidType(sol, 3); 9714 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9715 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9716 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9717 PetscCheckSameComm(F, 1, rhs, 2); 9718 PetscCheckSameComm(F, 1, sol, 3); 9719 PetscCall(MatFactorFactorizeSchurComplement(F)); 9720 switch (F->schur_status) { 9721 case MAT_FACTOR_SCHUR_FACTORED: 9722 PetscCall(MatSolve(F->schur, rhs, sol)); 9723 break; 9724 case MAT_FACTOR_SCHUR_INVERTED: 9725 PetscCall(MatMult(F->schur, rhs, sol)); 9726 break; 9727 default: 9728 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9729 } 9730 PetscFunctionReturn(PETSC_SUCCESS); 9731 } 9732 9733 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat); 9734 #if PetscDefined(HAVE_CUDA) 9735 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat); 9736 #endif 9737 9738 /* Schur status updated in the interface */ 9739 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F) 9740 { 9741 Mat S = F->schur; 9742 9743 PetscFunctionBegin; 9744 if (S) { 9745 PetscMPIInt size; 9746 PetscBool isdense, isdensecuda; 9747 9748 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size)); 9749 PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented"); 9750 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense)); 9751 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda)); 9752 PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name); 9753 PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0)); 9754 if (isdense) { 9755 PetscCall(MatSeqDenseInvertFactors_Private(S)); 9756 } else if (isdensecuda) { 9757 #if defined(PETSC_HAVE_CUDA) 9758 PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S)); 9759 #endif 9760 } 9761 // HIP?????????????? 9762 PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0)); 9763 } 9764 PetscFunctionReturn(PETSC_SUCCESS); 9765 } 9766 9767 /*@ 9768 MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step 9769 9770 Logically Collective 9771 9772 Input Parameter: 9773 . F - the factored matrix obtained by calling `MatGetFactor()` 9774 9775 Level: advanced 9776 9777 Notes: 9778 Must be called after `MatFactorSetSchurIS()`. 9779 9780 Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it. 9781 9782 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()` 9783 @*/ 9784 PetscErrorCode MatFactorInvertSchurComplement(Mat F) 9785 { 9786 PetscFunctionBegin; 9787 PetscValidType(F, 1); 9788 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9789 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS); 9790 PetscCall(MatFactorFactorizeSchurComplement(F)); 9791 PetscCall(MatFactorInvertSchurComplement_Private(F)); 9792 F->schur_status = MAT_FACTOR_SCHUR_INVERTED; 9793 PetscFunctionReturn(PETSC_SUCCESS); 9794 } 9795 9796 /*@ 9797 MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step 9798 9799 Logically Collective 9800 9801 Input Parameter: 9802 . F - the factored matrix obtained by calling `MatGetFactor()` 9803 9804 Level: advanced 9805 9806 Note: 9807 Must be called after `MatFactorSetSchurIS()` 9808 9809 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()` 9810 @*/ 9811 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F) 9812 { 9813 MatFactorInfo info; 9814 9815 PetscFunctionBegin; 9816 PetscValidType(F, 1); 9817 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9818 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS); 9819 PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0)); 9820 PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo))); 9821 if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */ 9822 PetscCall(MatCholeskyFactor(F->schur, NULL, &info)); 9823 } else { 9824 PetscCall(MatLUFactor(F->schur, NULL, NULL, &info)); 9825 } 9826 PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0)); 9827 F->schur_status = MAT_FACTOR_SCHUR_FACTORED; 9828 PetscFunctionReturn(PETSC_SUCCESS); 9829 } 9830 9831 /*@ 9832 MatPtAP - Creates the matrix product C = P^T * A * P 9833 9834 Neighbor-wise Collective 9835 9836 Input Parameters: 9837 + A - the matrix 9838 . P - the projection matrix 9839 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9840 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate 9841 if the result is a dense matrix this is irrelevant 9842 9843 Output Parameter: 9844 . C - the product matrix 9845 9846 Level: intermediate 9847 9848 Notes: 9849 C will be created and must be destroyed by the user with `MatDestroy()`. 9850 9851 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9852 9853 Developer Note: 9854 For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`. 9855 9856 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()` 9857 @*/ 9858 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C) 9859 { 9860 PetscFunctionBegin; 9861 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 9862 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9863 9864 if (scall == MAT_INITIAL_MATRIX) { 9865 PetscCall(MatProductCreate(A, P, NULL, C)); 9866 PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP)); 9867 PetscCall(MatProductSetAlgorithm(*C, "default")); 9868 PetscCall(MatProductSetFill(*C, fill)); 9869 9870 (*C)->product->api_user = PETSC_TRUE; 9871 PetscCall(MatProductSetFromOptions(*C)); 9872 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); 9873 PetscCall(MatProductSymbolic(*C)); 9874 } else { /* scall == MAT_REUSE_MATRIX */ 9875 PetscCall(MatProductReplaceMats(A, P, NULL, *C)); 9876 } 9877 9878 PetscCall(MatProductNumeric(*C)); 9879 (*C)->symmetric = A->symmetric; 9880 (*C)->spd = A->spd; 9881 PetscFunctionReturn(PETSC_SUCCESS); 9882 } 9883 9884 /*@ 9885 MatRARt - Creates the matrix product C = R * A * R^T 9886 9887 Neighbor-wise Collective 9888 9889 Input Parameters: 9890 + A - the matrix 9891 . R - the projection matrix 9892 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9893 - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate 9894 if the result is a dense matrix this is irrelevant 9895 9896 Output Parameter: 9897 . C - the product matrix 9898 9899 Level: intermediate 9900 9901 Notes: 9902 C will be created and must be destroyed by the user with `MatDestroy()`. 9903 9904 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9905 9906 This routine is currently only implemented for pairs of `MATAIJ` matrices and classes 9907 which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes, 9908 parallel MatRARt is implemented via explicit transpose of R, which could be very expensive. 9909 We recommend using MatPtAP(). 9910 9911 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()` 9912 @*/ 9913 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C) 9914 { 9915 PetscFunctionBegin; 9916 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 9917 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9918 9919 if (scall == MAT_INITIAL_MATRIX) { 9920 PetscCall(MatProductCreate(A, R, NULL, C)); 9921 PetscCall(MatProductSetType(*C, MATPRODUCT_RARt)); 9922 PetscCall(MatProductSetAlgorithm(*C, "default")); 9923 PetscCall(MatProductSetFill(*C, fill)); 9924 9925 (*C)->product->api_user = PETSC_TRUE; 9926 PetscCall(MatProductSetFromOptions(*C)); 9927 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); 9928 PetscCall(MatProductSymbolic(*C)); 9929 } else { /* scall == MAT_REUSE_MATRIX */ 9930 PetscCall(MatProductReplaceMats(A, R, NULL, *C)); 9931 } 9932 9933 PetscCall(MatProductNumeric(*C)); 9934 if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 9935 PetscFunctionReturn(PETSC_SUCCESS); 9936 } 9937 9938 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C) 9939 { 9940 PetscFunctionBegin; 9941 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9942 9943 if (scall == MAT_INITIAL_MATRIX) { 9944 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype])); 9945 PetscCall(MatProductCreate(A, B, NULL, C)); 9946 PetscCall(MatProductSetType(*C, ptype)); 9947 PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT)); 9948 PetscCall(MatProductSetFill(*C, fill)); 9949 9950 (*C)->product->api_user = PETSC_TRUE; 9951 PetscCall(MatProductSetFromOptions(*C)); 9952 PetscCall(MatProductSymbolic(*C)); 9953 } else { /* scall == MAT_REUSE_MATRIX */ 9954 Mat_Product *product = (*C)->product; 9955 PetscBool isdense; 9956 9957 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, "")); 9958 if (isdense && product && product->type != ptype) { 9959 PetscCall(MatProductClear(*C)); 9960 product = NULL; 9961 } 9962 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype])); 9963 if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */ 9964 PetscCheck(isdense, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first"); 9965 PetscCall(MatProductCreate_Private(A, B, NULL, *C)); 9966 product = (*C)->product; 9967 product->fill = fill; 9968 product->api_user = PETSC_TRUE; 9969 product->clear = PETSC_TRUE; 9970 9971 PetscCall(MatProductSetType(*C, ptype)); 9972 PetscCall(MatProductSetFromOptions(*C)); 9973 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); 9974 PetscCall(MatProductSymbolic(*C)); 9975 } else { /* user may change input matrices A or B when REUSE */ 9976 PetscCall(MatProductReplaceMats(A, B, NULL, *C)); 9977 } 9978 } 9979 PetscCall(MatProductNumeric(*C)); 9980 PetscFunctionReturn(PETSC_SUCCESS); 9981 } 9982 9983 /*@ 9984 MatMatMult - Performs matrix-matrix multiplication C=A*B. 9985 9986 Neighbor-wise Collective 9987 9988 Input Parameters: 9989 + A - the left matrix 9990 . B - the right matrix 9991 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9992 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate 9993 if the result is a dense matrix this is irrelevant 9994 9995 Output Parameter: 9996 . C - the product matrix 9997 9998 Notes: 9999 Unless scall is `MAT_REUSE_MATRIX` C will be created. 10000 10001 `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 10002 call to this function with `MAT_INITIAL_MATRIX`. 10003 10004 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed. 10005 10006 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`, 10007 rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse. 10008 10009 Example of Usage: 10010 .vb 10011 MatProductCreate(A,B,NULL,&C); 10012 MatProductSetType(C,MATPRODUCT_AB); 10013 MatProductSymbolic(C); 10014 MatProductNumeric(C); // compute C=A * B 10015 MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1 10016 MatProductNumeric(C); 10017 MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1 10018 MatProductNumeric(C); 10019 .ve 10020 10021 Level: intermediate 10022 10023 .seealso: [](chapter_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()` 10024 @*/ 10025 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10026 { 10027 PetscFunctionBegin; 10028 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C)); 10029 PetscFunctionReturn(PETSC_SUCCESS); 10030 } 10031 10032 /*@ 10033 MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T. 10034 10035 Neighbor-wise Collective 10036 10037 Input Parameters: 10038 + A - the left matrix 10039 . B - the right matrix 10040 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10041 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 10042 10043 Output Parameter: 10044 . C - the product matrix 10045 10046 Level: intermediate 10047 10048 Notes: 10049 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10050 10051 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call 10052 10053 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10054 actually needed. 10055 10056 This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class, 10057 and for pairs of `MATMPIDENSE` matrices. 10058 10059 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt` 10060 10061 Options Database Keys: 10062 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the 10063 first redundantly copies the transposed B matrix on each process and requiers O(log P) communication complexity; 10064 the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity. 10065 10066 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductCreate()`, `MatProductAlgorithm`, `MatProductType`, `MATPRODUCT_ABt` 10067 @*/ 10068 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10069 { 10070 PetscFunctionBegin; 10071 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C)); 10072 if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10073 PetscFunctionReturn(PETSC_SUCCESS); 10074 } 10075 10076 /*@ 10077 MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B. 10078 10079 Neighbor-wise Collective 10080 10081 Input Parameters: 10082 + A - the left matrix 10083 . B - the right matrix 10084 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10085 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 10086 10087 Output Parameter: 10088 . C - the product matrix 10089 10090 Level: intermediate 10091 10092 Notes: 10093 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10094 10095 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call. 10096 10097 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB` 10098 10099 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10100 actually needed. 10101 10102 This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes 10103 which inherit from `MATSEQAIJ`. C will be of the same type as the input matrices. 10104 10105 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()` 10106 @*/ 10107 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10108 { 10109 PetscFunctionBegin; 10110 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C)); 10111 PetscFunctionReturn(PETSC_SUCCESS); 10112 } 10113 10114 /*@ 10115 MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C. 10116 10117 Neighbor-wise Collective 10118 10119 Input Parameters: 10120 + A - the left matrix 10121 . B - the middle matrix 10122 . C - the right matrix 10123 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10124 - 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 10125 if the result is a dense matrix this is irrelevant 10126 10127 Output Parameter: 10128 . D - the product matrix 10129 10130 Level: intermediate 10131 10132 Notes: 10133 Unless scall is `MAT_REUSE_MATRIX` D will be created. 10134 10135 `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call 10136 10137 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC` 10138 10139 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10140 actually needed. 10141 10142 If you have many matrices with the same non-zero structure to multiply, you 10143 should use `MAT_REUSE_MATRIX` in all calls but the first 10144 10145 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()` 10146 @*/ 10147 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D) 10148 { 10149 PetscFunctionBegin; 10150 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6); 10151 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10152 10153 if (scall == MAT_INITIAL_MATRIX) { 10154 PetscCall(MatProductCreate(A, B, C, D)); 10155 PetscCall(MatProductSetType(*D, MATPRODUCT_ABC)); 10156 PetscCall(MatProductSetAlgorithm(*D, "default")); 10157 PetscCall(MatProductSetFill(*D, fill)); 10158 10159 (*D)->product->api_user = PETSC_TRUE; 10160 PetscCall(MatProductSetFromOptions(*D)); 10161 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, 10162 ((PetscObject)C)->type_name); 10163 PetscCall(MatProductSymbolic(*D)); 10164 } else { /* user may change input matrices when REUSE */ 10165 PetscCall(MatProductReplaceMats(A, B, C, *D)); 10166 } 10167 PetscCall(MatProductNumeric(*D)); 10168 PetscFunctionReturn(PETSC_SUCCESS); 10169 } 10170 10171 /*@ 10172 MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators. 10173 10174 Collective 10175 10176 Input Parameters: 10177 + mat - the matrix 10178 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices) 10179 . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used) 10180 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10181 10182 Output Parameter: 10183 . matredundant - redundant matrix 10184 10185 Level: advanced 10186 10187 Notes: 10188 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 10189 original matrix has not changed from that last call to MatCreateRedundantMatrix(). 10190 10191 This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before 10192 calling it. 10193 10194 `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be. 10195 10196 .seealso: [](chapter_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubComm` 10197 @*/ 10198 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant) 10199 { 10200 MPI_Comm comm; 10201 PetscMPIInt size; 10202 PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs; 10203 Mat_Redundant *redund = NULL; 10204 PetscSubcomm psubcomm = NULL; 10205 MPI_Comm subcomm_in = subcomm; 10206 Mat *matseq; 10207 IS isrow, iscol; 10208 PetscBool newsubcomm = PETSC_FALSE; 10209 10210 PetscFunctionBegin; 10211 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10212 if (nsubcomm && reuse == MAT_REUSE_MATRIX) { 10213 PetscValidPointer(*matredundant, 5); 10214 PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5); 10215 } 10216 10217 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10218 if (size == 1 || nsubcomm == 1) { 10219 if (reuse == MAT_INITIAL_MATRIX) { 10220 PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant)); 10221 } else { 10222 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"); 10223 PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN)); 10224 } 10225 PetscFunctionReturn(PETSC_SUCCESS); 10226 } 10227 10228 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10229 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10230 MatCheckPreallocated(mat, 1); 10231 10232 PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0)); 10233 if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */ 10234 /* create psubcomm, then get subcomm */ 10235 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10236 PetscCallMPI(MPI_Comm_size(comm, &size)); 10237 PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size); 10238 10239 PetscCall(PetscSubcommCreate(comm, &psubcomm)); 10240 PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm)); 10241 PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS)); 10242 PetscCall(PetscSubcommSetFromOptions(psubcomm)); 10243 PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL)); 10244 newsubcomm = PETSC_TRUE; 10245 PetscCall(PetscSubcommDestroy(&psubcomm)); 10246 } 10247 10248 /* get isrow, iscol and a local sequential matrix matseq[0] */ 10249 if (reuse == MAT_INITIAL_MATRIX) { 10250 mloc_sub = PETSC_DECIDE; 10251 nloc_sub = PETSC_DECIDE; 10252 if (bs < 1) { 10253 PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M)); 10254 PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N)); 10255 } else { 10256 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M)); 10257 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N)); 10258 } 10259 PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm)); 10260 rstart = rend - mloc_sub; 10261 PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow)); 10262 PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol)); 10263 } else { /* reuse == MAT_REUSE_MATRIX */ 10264 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"); 10265 /* retrieve subcomm */ 10266 PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm)); 10267 redund = (*matredundant)->redundant; 10268 isrow = redund->isrow; 10269 iscol = redund->iscol; 10270 matseq = redund->matseq; 10271 } 10272 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq)); 10273 10274 /* get matredundant over subcomm */ 10275 if (reuse == MAT_INITIAL_MATRIX) { 10276 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant)); 10277 10278 /* create a supporting struct and attach it to C for reuse */ 10279 PetscCall(PetscNew(&redund)); 10280 (*matredundant)->redundant = redund; 10281 redund->isrow = isrow; 10282 redund->iscol = iscol; 10283 redund->matseq = matseq; 10284 if (newsubcomm) { 10285 redund->subcomm = subcomm; 10286 } else { 10287 redund->subcomm = MPI_COMM_NULL; 10288 } 10289 } else { 10290 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant)); 10291 } 10292 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 10293 if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) { 10294 PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE)); 10295 PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE)); 10296 } 10297 #endif 10298 PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0)); 10299 PetscFunctionReturn(PETSC_SUCCESS); 10300 } 10301 10302 /*@C 10303 MatGetMultiProcBlock - Create multiple 'parallel submatrices' from 10304 a given `Mat`. Each submatrix can span multiple procs. 10305 10306 Collective 10307 10308 Input Parameters: 10309 + mat - the matrix 10310 . subcomm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))` 10311 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10312 10313 Output Parameter: 10314 . subMat - parallel sub-matrices each spanning a given `subcomm` 10315 10316 Level: advanced 10317 10318 Notes: 10319 The submatrix partition across processors is dictated by `subComm` a 10320 communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm` 10321 is not restricted to be grouped with consecutive original ranks. 10322 10323 Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices 10324 map directly to the layout of the original matrix [wrt the local 10325 row,col partitioning]. So the original 'DiagonalMat' naturally maps 10326 into the 'DiagonalMat' of the `subMat`, hence it is used directly from 10327 the `subMat`. However the offDiagMat looses some columns - and this is 10328 reconstructed with `MatSetValues()` 10329 10330 This is used by `PCBJACOBI` when a single block spans multiple MPI ranks 10331 10332 .seealso: [](chapter_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI` 10333 @*/ 10334 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) 10335 { 10336 PetscMPIInt commsize, subCommSize; 10337 10338 PetscFunctionBegin; 10339 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize)); 10340 PetscCallMPI(MPI_Comm_size(subComm, &subCommSize)); 10341 PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize); 10342 10343 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"); 10344 PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10345 PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat); 10346 PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10347 PetscFunctionReturn(PETSC_SUCCESS); 10348 } 10349 10350 /*@ 10351 MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering 10352 10353 Not Collective 10354 10355 Input Parameters: 10356 + mat - matrix to extract local submatrix from 10357 . isrow - local row indices for submatrix 10358 - iscol - local column indices for submatrix 10359 10360 Output Parameter: 10361 . submat - the submatrix 10362 10363 Level: intermediate 10364 10365 Notes: 10366 `submat` should be disposed of with `MatRestoreLocalSubMatrix()`. 10367 10368 Depending on the format of `mat`, the returned submat may not implement `MatMult()`. Its communicator may be 10369 the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of `mat`'s. 10370 10371 `submat` always implements `MatSetValuesLocal()`. If `isrow` and `iscol` have the same block size, then 10372 `MatSetValuesBlockedLocal()` will also be implemented. 10373 10374 `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`. 10375 Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided. 10376 10377 .seealso: [](chapter_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()` 10378 @*/ 10379 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10380 { 10381 PetscFunctionBegin; 10382 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10383 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10384 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10385 PetscCheckSameComm(isrow, 2, iscol, 3); 10386 PetscValidPointer(submat, 4); 10387 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call"); 10388 10389 if (mat->ops->getlocalsubmatrix) { 10390 PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat); 10391 } else { 10392 PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat)); 10393 } 10394 PetscFunctionReturn(PETSC_SUCCESS); 10395 } 10396 10397 /*@ 10398 MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()` 10399 10400 Not Collective 10401 10402 Input Parameters: 10403 + mat - matrix to extract local submatrix from 10404 . isrow - local row indices for submatrix 10405 . iscol - local column indices for submatrix 10406 - submat - the submatrix 10407 10408 Level: intermediate 10409 10410 .seealso: [](chapter_matrices), `Mat`, `MatGetLocalSubMatrix()` 10411 @*/ 10412 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10413 { 10414 PetscFunctionBegin; 10415 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10416 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10417 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10418 PetscCheckSameComm(isrow, 2, iscol, 3); 10419 PetscValidPointer(submat, 4); 10420 if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4); 10421 10422 if (mat->ops->restorelocalsubmatrix) { 10423 PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat); 10424 } else { 10425 PetscCall(MatDestroy(submat)); 10426 } 10427 *submat = NULL; 10428 PetscFunctionReturn(PETSC_SUCCESS); 10429 } 10430 10431 /*@ 10432 MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix 10433 10434 Collective 10435 10436 Input Parameter: 10437 . mat - the matrix 10438 10439 Output Parameter: 10440 . is - if any rows have zero diagonals this contains the list of them 10441 10442 Level: developer 10443 10444 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10445 @*/ 10446 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is) 10447 { 10448 PetscFunctionBegin; 10449 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10450 PetscValidType(mat, 1); 10451 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10452 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10453 10454 if (!mat->ops->findzerodiagonals) { 10455 Vec diag; 10456 const PetscScalar *a; 10457 PetscInt *rows; 10458 PetscInt rStart, rEnd, r, nrow = 0; 10459 10460 PetscCall(MatCreateVecs(mat, &diag, NULL)); 10461 PetscCall(MatGetDiagonal(mat, diag)); 10462 PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd)); 10463 PetscCall(VecGetArrayRead(diag, &a)); 10464 for (r = 0; r < rEnd - rStart; ++r) 10465 if (a[r] == 0.0) ++nrow; 10466 PetscCall(PetscMalloc1(nrow, &rows)); 10467 nrow = 0; 10468 for (r = 0; r < rEnd - rStart; ++r) 10469 if (a[r] == 0.0) rows[nrow++] = r + rStart; 10470 PetscCall(VecRestoreArrayRead(diag, &a)); 10471 PetscCall(VecDestroy(&diag)); 10472 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is)); 10473 } else { 10474 PetscUseTypeMethod(mat, findzerodiagonals, is); 10475 } 10476 PetscFunctionReturn(PETSC_SUCCESS); 10477 } 10478 10479 /*@ 10480 MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size) 10481 10482 Collective 10483 10484 Input Parameter: 10485 . mat - the matrix 10486 10487 Output Parameter: 10488 . is - contains the list of rows with off block diagonal entries 10489 10490 Level: developer 10491 10492 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10493 @*/ 10494 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is) 10495 { 10496 PetscFunctionBegin; 10497 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10498 PetscValidType(mat, 1); 10499 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10500 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10501 10502 PetscUseTypeMethod(mat, findoffblockdiagonalentries, is); 10503 PetscFunctionReturn(PETSC_SUCCESS); 10504 } 10505 10506 /*@C 10507 MatInvertBlockDiagonal - Inverts the block diagonal entries. 10508 10509 Collective; No Fortran Support 10510 10511 Input Parameter: 10512 . mat - the matrix 10513 10514 Output Parameter: 10515 . values - the block inverses in column major order (FORTRAN-like) 10516 10517 Level: advanced 10518 10519 Notes: 10520 The size of the blocks is determined by the block size of the matrix. 10521 10522 The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case 10523 10524 The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size 10525 10526 .seealso: [](chapter_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()` 10527 @*/ 10528 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values) 10529 { 10530 PetscFunctionBegin; 10531 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10532 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10533 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10534 PetscUseTypeMethod(mat, invertblockdiagonal, values); 10535 PetscFunctionReturn(PETSC_SUCCESS); 10536 } 10537 10538 /*@C 10539 MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries. 10540 10541 Collective; No Fortran Support 10542 10543 Input Parameters: 10544 + mat - the matrix 10545 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()` 10546 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()` 10547 10548 Output Parameter: 10549 . values - the block inverses in column major order (FORTRAN-like) 10550 10551 Level: advanced 10552 10553 Notes: 10554 Use `MatInvertBlockDiagonal()` if all blocks have the same size 10555 10556 The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case 10557 10558 .seealso: [](chapter_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()` 10559 @*/ 10560 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values) 10561 { 10562 PetscFunctionBegin; 10563 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10564 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10565 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10566 PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values); 10567 PetscFunctionReturn(PETSC_SUCCESS); 10568 } 10569 10570 /*@ 10571 MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A 10572 10573 Collective 10574 10575 Input Parameters: 10576 + A - the matrix 10577 - C - matrix with inverted block diagonal of `A`. This matrix should be created and may have its type set. 10578 10579 Level: advanced 10580 10581 Note: 10582 The blocksize of the matrix is used to determine the blocks on the diagonal of `C` 10583 10584 .seealso: [](chapter_matrices), `Mat`, `MatInvertBlockDiagonal()` 10585 @*/ 10586 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C) 10587 { 10588 const PetscScalar *vals; 10589 PetscInt *dnnz; 10590 PetscInt m, rstart, rend, bs, i, j; 10591 10592 PetscFunctionBegin; 10593 PetscCall(MatInvertBlockDiagonal(A, &vals)); 10594 PetscCall(MatGetBlockSize(A, &bs)); 10595 PetscCall(MatGetLocalSize(A, &m, NULL)); 10596 PetscCall(MatSetLayouts(C, A->rmap, A->cmap)); 10597 PetscCall(PetscMalloc1(m / bs, &dnnz)); 10598 for (j = 0; j < m / bs; j++) dnnz[j] = 1; 10599 PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL)); 10600 PetscCall(PetscFree(dnnz)); 10601 PetscCall(MatGetOwnershipRange(C, &rstart, &rend)); 10602 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE)); 10603 for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES)); 10604 PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 10605 PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 10606 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE)); 10607 PetscFunctionReturn(PETSC_SUCCESS); 10608 } 10609 10610 /*@C 10611 MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created 10612 via `MatTransposeColoringCreate()`. 10613 10614 Collective 10615 10616 Input Parameter: 10617 . c - coloring context 10618 10619 Level: intermediate 10620 10621 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringCreate()` 10622 @*/ 10623 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c) 10624 { 10625 MatTransposeColoring matcolor = *c; 10626 10627 PetscFunctionBegin; 10628 if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS); 10629 if (--((PetscObject)matcolor)->refct > 0) { 10630 matcolor = NULL; 10631 PetscFunctionReturn(PETSC_SUCCESS); 10632 } 10633 10634 PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow)); 10635 PetscCall(PetscFree(matcolor->rows)); 10636 PetscCall(PetscFree(matcolor->den2sp)); 10637 PetscCall(PetscFree(matcolor->colorforcol)); 10638 PetscCall(PetscFree(matcolor->columns)); 10639 if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart)); 10640 PetscCall(PetscHeaderDestroy(c)); 10641 PetscFunctionReturn(PETSC_SUCCESS); 10642 } 10643 10644 /*@C 10645 MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which 10646 a `MatTransposeColoring` context has been created, computes a dense B^T by applying 10647 `MatTransposeColoring` to sparse B. 10648 10649 Collective 10650 10651 Input Parameters: 10652 + coloring - coloring context created with `MatTransposeColoringCreate()` 10653 - B - sparse matrix 10654 10655 Output Parameter: 10656 . Btdense - dense matrix B^T 10657 10658 Level: developer 10659 10660 Note: 10661 These are used internally for some implementations of `MatRARt()` 10662 10663 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()` 10664 @*/ 10665 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense) 10666 { 10667 PetscFunctionBegin; 10668 PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10669 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 10670 PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3); 10671 10672 PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense)); 10673 PetscFunctionReturn(PETSC_SUCCESS); 10674 } 10675 10676 /*@C 10677 MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which 10678 a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense 10679 in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix 10680 `Csp` from `Cden`. 10681 10682 Collective 10683 10684 Input Parameters: 10685 + matcoloring - coloring context created with `MatTransposeColoringCreate()` 10686 - Cden - matrix product of a sparse matrix and a dense matrix Btdense 10687 10688 Output Parameter: 10689 . Csp - sparse matrix 10690 10691 Level: developer 10692 10693 Note: 10694 These are used internally for some implementations of `MatRARt()` 10695 10696 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()` 10697 @*/ 10698 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp) 10699 { 10700 PetscFunctionBegin; 10701 PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10702 PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2); 10703 PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3); 10704 10705 PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp)); 10706 PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY)); 10707 PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY)); 10708 PetscFunctionReturn(PETSC_SUCCESS); 10709 } 10710 10711 /*@C 10712 MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T. 10713 10714 Collective 10715 10716 Input Parameters: 10717 + mat - the matrix product C 10718 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()` 10719 10720 Output Parameter: 10721 . color - the new coloring context 10722 10723 Level: intermediate 10724 10725 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`, 10726 `MatTransColoringApplyDenToSp()` 10727 @*/ 10728 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color) 10729 { 10730 MatTransposeColoring c; 10731 MPI_Comm comm; 10732 10733 PetscFunctionBegin; 10734 PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10735 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10736 PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL)); 10737 10738 c->ctype = iscoloring->ctype; 10739 PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c); 10740 10741 *color = c; 10742 PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10743 PetscFunctionReturn(PETSC_SUCCESS); 10744 } 10745 10746 /*@ 10747 MatGetNonzeroState - Returns a 64 bit integer representing the current state of nonzeros in the matrix. If the 10748 matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the 10749 same, otherwise it will be larger 10750 10751 Not Collective 10752 10753 Input Parameter: 10754 . A - the matrix 10755 10756 Output Parameter: 10757 . state - the current state 10758 10759 Level: intermediate 10760 10761 Notes: 10762 You can only compare states from two different calls to the SAME matrix, you cannot compare calls between 10763 different matrices 10764 10765 Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix 10766 10767 Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers. 10768 10769 .seealso: [](chapter_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()` 10770 @*/ 10771 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state) 10772 { 10773 PetscFunctionBegin; 10774 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10775 *state = mat->nonzerostate; 10776 PetscFunctionReturn(PETSC_SUCCESS); 10777 } 10778 10779 /*@ 10780 MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential 10781 matrices from each processor 10782 10783 Collective 10784 10785 Input Parameters: 10786 + comm - the communicators the parallel matrix will live on 10787 . seqmat - the input sequential matrices 10788 . n - number of local columns (or `PETSC_DECIDE`) 10789 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10790 10791 Output Parameter: 10792 . mpimat - the parallel matrix generated 10793 10794 Level: developer 10795 10796 Note: 10797 The number of columns of the matrix in EACH processor MUST be the same. 10798 10799 .seealso: [](chapter_matrices), `Mat` 10800 @*/ 10801 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat) 10802 { 10803 PetscMPIInt size; 10804 10805 PetscFunctionBegin; 10806 PetscCallMPI(MPI_Comm_size(comm, &size)); 10807 if (size == 1) { 10808 if (reuse == MAT_INITIAL_MATRIX) { 10809 PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat)); 10810 } else { 10811 PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN)); 10812 } 10813 PetscFunctionReturn(PETSC_SUCCESS); 10814 } 10815 10816 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"); 10817 10818 PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0)); 10819 PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat)); 10820 PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0)); 10821 PetscFunctionReturn(PETSC_SUCCESS); 10822 } 10823 10824 /*@ 10825 MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent ranks' ownership ranges. 10826 10827 Collective 10828 10829 Input Parameters: 10830 + A - the matrix to create subdomains from 10831 - N - requested number of subdomains 10832 10833 Output Parameters: 10834 + n - number of subdomains resulting on this rank 10835 - iss - `IS` list with indices of subdomains on this rank 10836 10837 Level: advanced 10838 10839 Note: 10840 The number of subdomains must be smaller than the communicator size 10841 10842 .seealso: [](chapter_matrices), `Mat`, `IS` 10843 @*/ 10844 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[]) 10845 { 10846 MPI_Comm comm, subcomm; 10847 PetscMPIInt size, rank, color; 10848 PetscInt rstart, rend, k; 10849 10850 PetscFunctionBegin; 10851 PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 10852 PetscCallMPI(MPI_Comm_size(comm, &size)); 10853 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 10854 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); 10855 *n = 1; 10856 k = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */ 10857 color = rank / k; 10858 PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm)); 10859 PetscCall(PetscMalloc1(1, iss)); 10860 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 10861 PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0])); 10862 PetscCallMPI(MPI_Comm_free(&subcomm)); 10863 PetscFunctionReturn(PETSC_SUCCESS); 10864 } 10865 10866 /*@ 10867 MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection. 10868 10869 If the interpolation and restriction operators are the same, uses `MatPtAP()`. 10870 If they are not the same, uses `MatMatMatMult()`. 10871 10872 Once the coarse grid problem is constructed, correct for interpolation operators 10873 that are not of full rank, which can legitimately happen in the case of non-nested 10874 geometric multigrid. 10875 10876 Input Parameters: 10877 + restrct - restriction operator 10878 . dA - fine grid matrix 10879 . interpolate - interpolation operator 10880 . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10881 - fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate 10882 10883 Output Parameter: 10884 . A - the Galerkin coarse matrix 10885 10886 Options Database Key: 10887 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used 10888 10889 Level: developer 10890 10891 .seealso: [](chapter_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()` 10892 @*/ 10893 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A) 10894 { 10895 IS zerorows; 10896 Vec diag; 10897 10898 PetscFunctionBegin; 10899 PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10900 /* Construct the coarse grid matrix */ 10901 if (interpolate == restrct) { 10902 PetscCall(MatPtAP(dA, interpolate, reuse, fill, A)); 10903 } else { 10904 PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A)); 10905 } 10906 10907 /* If the interpolation matrix is not of full rank, A will have zero rows. 10908 This can legitimately happen in the case of non-nested geometric multigrid. 10909 In that event, we set the rows of the matrix to the rows of the identity, 10910 ignoring the equations (as the RHS will also be zero). */ 10911 10912 PetscCall(MatFindZeroRows(*A, &zerorows)); 10913 10914 if (zerorows != NULL) { /* if there are any zero rows */ 10915 PetscCall(MatCreateVecs(*A, &diag, NULL)); 10916 PetscCall(MatGetDiagonal(*A, diag)); 10917 PetscCall(VecISSet(diag, zerorows, 1.0)); 10918 PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES)); 10919 PetscCall(VecDestroy(&diag)); 10920 PetscCall(ISDestroy(&zerorows)); 10921 } 10922 PetscFunctionReturn(PETSC_SUCCESS); 10923 } 10924 10925 /*@C 10926 MatSetOperation - Allows user to set a matrix operation for any matrix type 10927 10928 Logically Collective 10929 10930 Input Parameters: 10931 + mat - the matrix 10932 . op - the name of the operation 10933 - f - the function that provides the operation 10934 10935 Level: developer 10936 10937 Usage: 10938 .vb 10939 extern PetscErrorCode usermult(Mat, Vec, Vec); 10940 10941 PetscCall(MatCreateXXX(comm, ..., &A)); 10942 PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFunction)usermult)); 10943 .ve 10944 10945 Notes: 10946 See the file `include/petscmat.h` for a complete list of matrix 10947 operations, which all have the form MATOP_<OPERATION>, where 10948 <OPERATION> is the name (in all capital letters) of the 10949 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 10950 10951 All user-provided functions (except for `MATOP_DESTROY`) should have the same calling 10952 sequence as the usual matrix interface routines, since they 10953 are intended to be accessed via the usual matrix interface 10954 routines, e.g., 10955 .vb 10956 MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec) 10957 .ve 10958 10959 In particular each function MUST return `PETSC_SUCCESS` on success and 10960 nonzero on failure. 10961 10962 This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type. 10963 10964 .seealso: [](chapter_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()` 10965 @*/ 10966 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void)) 10967 { 10968 PetscFunctionBegin; 10969 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10970 if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view; 10971 (((void (**)(void))mat->ops)[op]) = f; 10972 PetscFunctionReturn(PETSC_SUCCESS); 10973 } 10974 10975 /*@C 10976 MatGetOperation - Gets a matrix operation for any matrix type. 10977 10978 Not Collective 10979 10980 Input Parameters: 10981 + mat - the matrix 10982 - op - the name of the operation 10983 10984 Output Parameter: 10985 . f - the function that provides the operation 10986 10987 Level: developer 10988 10989 Usage: 10990 .vb 10991 PetscErrorCode (*usermult)(Mat, Vec, Vec); 10992 MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult); 10993 .ve 10994 10995 Notes: 10996 See the file include/petscmat.h for a complete list of matrix 10997 operations, which all have the form MATOP_<OPERATION>, where 10998 <OPERATION> is the name (in all capital letters) of the 10999 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11000 11001 This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type. 11002 11003 .seealso: [](chapter_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()` 11004 @*/ 11005 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void)) 11006 { 11007 PetscFunctionBegin; 11008 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11009 *f = (((void (**)(void))mat->ops)[op]); 11010 PetscFunctionReturn(PETSC_SUCCESS); 11011 } 11012 11013 /*@ 11014 MatHasOperation - Determines whether the given matrix supports the particular operation. 11015 11016 Not Collective 11017 11018 Input Parameters: 11019 + mat - the matrix 11020 - op - the operation, for example, `MATOP_GET_DIAGONAL` 11021 11022 Output Parameter: 11023 . has - either `PETSC_TRUE` or `PETSC_FALSE` 11024 11025 Level: advanced 11026 11027 Note: 11028 See `MatSetOperation()` for additional discussion on naming convention and usage of `op`. 11029 11030 .seealso: [](chapter_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()` 11031 @*/ 11032 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has) 11033 { 11034 PetscFunctionBegin; 11035 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11036 PetscValidBoolPointer(has, 3); 11037 if (mat->ops->hasoperation) { 11038 PetscUseTypeMethod(mat, hasoperation, op, has); 11039 } else { 11040 if (((void **)mat->ops)[op]) *has = PETSC_TRUE; 11041 else { 11042 *has = PETSC_FALSE; 11043 if (op == MATOP_CREATE_SUBMATRIX) { 11044 PetscMPIInt size; 11045 11046 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 11047 if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has)); 11048 } 11049 } 11050 } 11051 PetscFunctionReturn(PETSC_SUCCESS); 11052 } 11053 11054 /*@ 11055 MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent 11056 11057 Collective 11058 11059 Input Parameter: 11060 . mat - the matrix 11061 11062 Output Parameter: 11063 . cong - either `PETSC_TRUE` or `PETSC_FALSE` 11064 11065 Level: beginner 11066 11067 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout` 11068 @*/ 11069 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong) 11070 { 11071 PetscFunctionBegin; 11072 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11073 PetscValidType(mat, 1); 11074 PetscValidBoolPointer(cong, 2); 11075 if (!mat->rmap || !mat->cmap) { 11076 *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE; 11077 PetscFunctionReturn(PETSC_SUCCESS); 11078 } 11079 if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */ 11080 PetscCall(PetscLayoutSetUp(mat->rmap)); 11081 PetscCall(PetscLayoutSetUp(mat->cmap)); 11082 PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong)); 11083 if (*cong) mat->congruentlayouts = 1; 11084 else mat->congruentlayouts = 0; 11085 } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE; 11086 PetscFunctionReturn(PETSC_SUCCESS); 11087 } 11088 11089 PetscErrorCode MatSetInf(Mat A) 11090 { 11091 PetscFunctionBegin; 11092 PetscUseTypeMethod(A, setinf); 11093 PetscFunctionReturn(PETSC_SUCCESS); 11094 } 11095 11096 /*@C 11097 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 11098 and possibly removes small values from the graph structure. 11099 11100 Collective 11101 11102 Input Parameters: 11103 + A - the matrix 11104 . sym - `PETSC_TRUE` indicates that the graph should be symmetrized 11105 . scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry 11106 - filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value 11107 11108 Output Parameter: 11109 . graph - the resulting graph 11110 11111 Level: advanced 11112 11113 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `PCGAMG` 11114 @*/ 11115 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph) 11116 { 11117 PetscFunctionBegin; 11118 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11119 PetscValidType(A, 1); 11120 PetscValidLogicalCollectiveBool(A, scale, 3); 11121 PetscValidPointer(graph, 5); 11122 PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph); 11123 PetscFunctionReturn(PETSC_SUCCESS); 11124 } 11125 11126 /*@ 11127 MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place, 11128 meaning the same memory is used for the matrix, and no new memory is allocated. 11129 11130 Collective 11131 11132 Input Parameter: 11133 . A - the matrix 11134 11135 Level: intermediate 11136 11137 Developer Note: 11138 The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end 11139 of the arrays in the data structure are unneeded. 11140 11141 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatChop()` 11142 @*/ 11143 PetscErrorCode MatEliminateZeros(Mat A) 11144 { 11145 PetscFunctionBegin; 11146 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11147 PetscUseTypeMethod(A, eliminatezeros); 11148 PetscFunctionReturn(PETSC_SUCCESS); 11149 } 11150