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 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 Users usually access the factorization solvers via `KSP` 4706 4707 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4708 such as pastix, superlu, mumps etc. 4709 4710 PETSc must have been ./configure to use the external solver, using the option --download-package 4711 4712 Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption 4713 where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set 4714 call `MatSetOptionsPrefixFactor()` on the originating matrix or `MatSetOptionsPrefix()` on the resulting factor matrix. 4715 4716 Developer Note: 4717 This should actually be called `MatCreateFactor()` since it creates a new factor object 4718 4719 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, 4720 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4721 @*/ 4722 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f) 4723 { 4724 PetscBool foundtype, foundmtype; 4725 PetscErrorCode (*conv)(Mat, MatFactorType, Mat *); 4726 4727 PetscFunctionBegin; 4728 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4729 PetscValidType(mat, 1); 4730 4731 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4732 MatCheckPreallocated(mat, 1); 4733 4734 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv)); 4735 if (!foundtype) { 4736 if (type) { 4737 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], 4738 ((PetscObject)mat)->type_name, type); 4739 } else { 4740 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); 4741 } 4742 } 4743 PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name); 4744 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); 4745 4746 PetscCall((*conv)(mat, ftype, f)); 4747 if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix)); 4748 PetscFunctionReturn(PETSC_SUCCESS); 4749 } 4750 4751 /*@C 4752 MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type 4753 4754 Not Collective 4755 4756 Input Parameters: 4757 + mat - the matrix 4758 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4759 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4760 4761 Output Parameter: 4762 . flg - PETSC_TRUE if the factorization is available 4763 4764 Level: intermediate 4765 4766 Notes: 4767 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4768 such as pastix, superlu, mumps etc. 4769 4770 PETSc must have been ./configure to use the external solver, using the option --download-package 4771 4772 Developer Note: 4773 This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object 4774 4775 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactor()`, `MatSolverTypeRegister()`, 4776 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4777 @*/ 4778 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg) 4779 { 4780 PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *); 4781 4782 PetscFunctionBegin; 4783 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4784 PetscValidType(mat, 1); 4785 PetscValidBoolPointer(flg, 4); 4786 4787 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4788 MatCheckPreallocated(mat, 1); 4789 4790 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv)); 4791 *flg = gconv ? PETSC_TRUE : PETSC_FALSE; 4792 PetscFunctionReturn(PETSC_SUCCESS); 4793 } 4794 4795 /*@ 4796 MatDuplicate - Duplicates a matrix including the non-zero structure. 4797 4798 Collective 4799 4800 Input Parameters: 4801 + mat - the matrix 4802 - op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`. 4803 See the manual page for `MatDuplicateOption()` for an explanation of these options. 4804 4805 Output Parameter: 4806 . M - pointer to place new matrix 4807 4808 Level: intermediate 4809 4810 Notes: 4811 You cannot change the nonzero pattern for the parent or child matrix if you use `MAT_SHARE_NONZERO_PATTERN`. 4812 4813 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. 4814 4815 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 4816 is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated. 4817 User should not use `MatDuplicate()` to create new matrix M if M is intended to be reused as the product of matrix operation. 4818 4819 .seealso: [](chapter_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption` 4820 @*/ 4821 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M) 4822 { 4823 Mat B; 4824 VecType vtype; 4825 PetscInt i; 4826 PetscObject dm; 4827 void (*viewf)(void); 4828 4829 PetscFunctionBegin; 4830 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4831 PetscValidType(mat, 1); 4832 PetscValidPointer(M, 3); 4833 PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix"); 4834 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4835 MatCheckPreallocated(mat, 1); 4836 4837 *M = NULL; 4838 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4839 PetscUseTypeMethod(mat, duplicate, op, M); 4840 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4841 B = *M; 4842 4843 PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf)); 4844 if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf)); 4845 PetscCall(MatGetVecType(mat, &vtype)); 4846 PetscCall(MatSetVecType(B, vtype)); 4847 4848 B->stencil.dim = mat->stencil.dim; 4849 B->stencil.noc = mat->stencil.noc; 4850 for (i = 0; i <= mat->stencil.dim; i++) { 4851 B->stencil.dims[i] = mat->stencil.dims[i]; 4852 B->stencil.starts[i] = mat->stencil.starts[i]; 4853 } 4854 4855 B->nooffproczerorows = mat->nooffproczerorows; 4856 B->nooffprocentries = mat->nooffprocentries; 4857 4858 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm)); 4859 if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm)); 4860 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4861 PetscFunctionReturn(PETSC_SUCCESS); 4862 } 4863 4864 /*@ 4865 MatGetDiagonal - Gets the diagonal of a matrix as a `Vec` 4866 4867 Logically Collective 4868 4869 Input Parameter: 4870 . mat - the matrix 4871 4872 Output Parameter: 4873 . v - the diagonal of the matrix 4874 4875 Level: intermediate 4876 4877 Note: 4878 Currently only correct in parallel for square matrices. 4879 4880 .seealso: [](chapter_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()` 4881 @*/ 4882 PetscErrorCode MatGetDiagonal(Mat mat, Vec v) 4883 { 4884 PetscFunctionBegin; 4885 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4886 PetscValidType(mat, 1); 4887 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4888 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4889 MatCheckPreallocated(mat, 1); 4890 4891 PetscUseTypeMethod(mat, getdiagonal, v); 4892 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4893 PetscFunctionReturn(PETSC_SUCCESS); 4894 } 4895 4896 /*@C 4897 MatGetRowMin - Gets the minimum value (of the real part) of each 4898 row of the matrix 4899 4900 Logically Collective 4901 4902 Input Parameter: 4903 . mat - the matrix 4904 4905 Output Parameters: 4906 + v - the vector for storing the maximums 4907 - idx - the indices of the column found for each row (optional) 4908 4909 Level: intermediate 4910 4911 Note: 4912 The result of this call are the same as if one converted the matrix to dense format 4913 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 4914 4915 This code is only implemented for a couple of matrix formats. 4916 4917 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, 4918 `MatGetRowMax()` 4919 @*/ 4920 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[]) 4921 { 4922 PetscFunctionBegin; 4923 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4924 PetscValidType(mat, 1); 4925 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4926 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4927 4928 if (!mat->cmap->N) { 4929 PetscCall(VecSet(v, PETSC_MAX_REAL)); 4930 if (idx) { 4931 PetscInt i, m = mat->rmap->n; 4932 for (i = 0; i < m; i++) idx[i] = -1; 4933 } 4934 } else { 4935 MatCheckPreallocated(mat, 1); 4936 } 4937 PetscUseTypeMethod(mat, getrowmin, v, idx); 4938 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4939 PetscFunctionReturn(PETSC_SUCCESS); 4940 } 4941 4942 /*@C 4943 MatGetRowMinAbs - Gets the minimum value (in absolute value) of each 4944 row of the matrix 4945 4946 Logically Collective 4947 4948 Input Parameter: 4949 . mat - the matrix 4950 4951 Output Parameters: 4952 + v - the vector for storing the minimums 4953 - idx - the indices of the column found for each row (or `NULL` if not needed) 4954 4955 Level: intermediate 4956 4957 Notes: 4958 if a row is completely empty or has only 0.0 values then the idx[] value for that 4959 row is 0 (the first column). 4960 4961 This code is only implemented for a couple of matrix formats. 4962 4963 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()` 4964 @*/ 4965 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[]) 4966 { 4967 PetscFunctionBegin; 4968 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4969 PetscValidType(mat, 1); 4970 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4971 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4972 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4973 4974 if (!mat->cmap->N) { 4975 PetscCall(VecSet(v, 0.0)); 4976 if (idx) { 4977 PetscInt i, m = mat->rmap->n; 4978 for (i = 0; i < m; i++) idx[i] = -1; 4979 } 4980 } else { 4981 MatCheckPreallocated(mat, 1); 4982 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 4983 PetscUseTypeMethod(mat, getrowminabs, v, idx); 4984 } 4985 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4986 PetscFunctionReturn(PETSC_SUCCESS); 4987 } 4988 4989 /*@C 4990 MatGetRowMax - Gets the maximum value (of the real part) of each 4991 row of the matrix 4992 4993 Logically Collective 4994 4995 Input Parameter: 4996 . mat - the matrix 4997 4998 Output Parameters: 4999 + v - the vector for storing the maximums 5000 - idx - the indices of the column found for each row (optional) 5001 5002 Level: intermediate 5003 5004 Notes: 5005 The result of this call are the same as if one converted the matrix to dense format 5006 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5007 5008 This code is only implemented for a couple of matrix formats. 5009 5010 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5011 @*/ 5012 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[]) 5013 { 5014 PetscFunctionBegin; 5015 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5016 PetscValidType(mat, 1); 5017 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5018 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5019 5020 if (!mat->cmap->N) { 5021 PetscCall(VecSet(v, PETSC_MIN_REAL)); 5022 if (idx) { 5023 PetscInt i, m = mat->rmap->n; 5024 for (i = 0; i < m; i++) idx[i] = -1; 5025 } 5026 } else { 5027 MatCheckPreallocated(mat, 1); 5028 PetscUseTypeMethod(mat, getrowmax, v, idx); 5029 } 5030 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5031 PetscFunctionReturn(PETSC_SUCCESS); 5032 } 5033 5034 /*@C 5035 MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each 5036 row of the matrix 5037 5038 Logically Collective 5039 5040 Input Parameter: 5041 . mat - the matrix 5042 5043 Output Parameters: 5044 + v - the vector for storing the maximums 5045 - idx - the indices of the column found for each row (or `NULL` if not needed) 5046 5047 Level: intermediate 5048 5049 Notes: 5050 if a row is completely empty or has only 0.0 values then the idx[] value for that 5051 row is 0 (the first column). 5052 5053 This code is only implemented for a couple of matrix formats. 5054 5055 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5056 @*/ 5057 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[]) 5058 { 5059 PetscFunctionBegin; 5060 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5061 PetscValidType(mat, 1); 5062 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5063 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5064 5065 if (!mat->cmap->N) { 5066 PetscCall(VecSet(v, 0.0)); 5067 if (idx) { 5068 PetscInt i, m = mat->rmap->n; 5069 for (i = 0; i < m; i++) idx[i] = -1; 5070 } 5071 } else { 5072 MatCheckPreallocated(mat, 1); 5073 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5074 PetscUseTypeMethod(mat, getrowmaxabs, v, idx); 5075 } 5076 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5077 PetscFunctionReturn(PETSC_SUCCESS); 5078 } 5079 5080 /*@ 5081 MatGetRowSum - Gets the sum of each row of the matrix 5082 5083 Logically or Neighborhood Collective 5084 5085 Input Parameter: 5086 . mat - the matrix 5087 5088 Output Parameter: 5089 . v - the vector for storing the sum of rows 5090 5091 Level: intermediate 5092 5093 Notes: 5094 This code is slow since it is not currently specialized for different formats 5095 5096 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()` 5097 @*/ 5098 PetscErrorCode MatGetRowSum(Mat mat, Vec v) 5099 { 5100 Vec ones; 5101 5102 PetscFunctionBegin; 5103 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5104 PetscValidType(mat, 1); 5105 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5106 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5107 MatCheckPreallocated(mat, 1); 5108 PetscCall(MatCreateVecs(mat, &ones, NULL)); 5109 PetscCall(VecSet(ones, 1.)); 5110 PetscCall(MatMult(mat, ones, v)); 5111 PetscCall(VecDestroy(&ones)); 5112 PetscFunctionReturn(PETSC_SUCCESS); 5113 } 5114 5115 /*@ 5116 MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) 5117 when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B) 5118 5119 Collective 5120 5121 Input Parameter: 5122 . mat - the matrix to provide the transpose 5123 5124 Output Parameter: 5125 . 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 5126 5127 Level: advanced 5128 5129 Note: 5130 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 5131 routine allows bypassing that call. 5132 5133 .seealso: [](chapter_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5134 @*/ 5135 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B) 5136 { 5137 PetscContainer rB = NULL; 5138 MatParentState *rb = NULL; 5139 5140 PetscFunctionBegin; 5141 PetscCall(PetscNew(&rb)); 5142 rb->id = ((PetscObject)mat)->id; 5143 rb->state = 0; 5144 PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate)); 5145 PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB)); 5146 PetscCall(PetscContainerSetPointer(rB, rb)); 5147 PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault)); 5148 PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB)); 5149 PetscCall(PetscObjectDereference((PetscObject)rB)); 5150 PetscFunctionReturn(PETSC_SUCCESS); 5151 } 5152 5153 /*@ 5154 MatTranspose - Computes an in-place or out-of-place transpose of a matrix. 5155 5156 Collective 5157 5158 Input Parameters: 5159 + mat - the matrix to transpose 5160 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5161 5162 Output Parameter: 5163 . B - the transpose 5164 5165 Level: intermediate 5166 5167 Notes: 5168 If you use `MAT_INPLACE_MATRIX` then you must pass in &mat for B 5169 5170 `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 5171 transpose, call `MatTransposeSetPrecursor`(mat,B) before calling this routine. 5172 5173 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. 5174 5175 Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed. 5176 5177 If mat is unchanged from the last call this function returns immediately without recomputing the result 5178 5179 If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()` 5180 5181 .seealso: [](chapter_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`, 5182 `MatTransposeSymbolic()`, `MatCreateTranspose()` 5183 @*/ 5184 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B) 5185 { 5186 PetscContainer rB = NULL; 5187 MatParentState *rb = NULL; 5188 5189 PetscFunctionBegin; 5190 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5191 PetscValidType(mat, 1); 5192 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5193 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5194 PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first"); 5195 PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX"); 5196 MatCheckPreallocated(mat, 1); 5197 if (reuse == MAT_REUSE_MATRIX) { 5198 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5199 PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor()."); 5200 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5201 PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5202 if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS); 5203 } 5204 5205 PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0)); 5206 if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) { 5207 PetscUseTypeMethod(mat, transpose, reuse, B); 5208 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5209 } 5210 PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0)); 5211 5212 if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B)); 5213 if (reuse != MAT_INPLACE_MATRIX) { 5214 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5215 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5216 rb->state = ((PetscObject)mat)->state; 5217 rb->nonzerostate = mat->nonzerostate; 5218 } 5219 PetscFunctionReturn(PETSC_SUCCESS); 5220 } 5221 5222 /*@ 5223 MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix. 5224 5225 Collective 5226 5227 Input Parameter: 5228 . A - the matrix to transpose 5229 5230 Output Parameter: 5231 . 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 5232 numerical portion. 5233 5234 Level: intermediate 5235 5236 Note: 5237 This is not supported for many matrix types, use `MatTranspose()` in those cases 5238 5239 .seealso: [](chapter_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5240 @*/ 5241 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B) 5242 { 5243 PetscFunctionBegin; 5244 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5245 PetscValidType(A, 1); 5246 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5247 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5248 PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0)); 5249 PetscUseTypeMethod(A, transposesymbolic, B); 5250 PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0)); 5251 5252 PetscCall(MatTransposeSetPrecursor(A, *B)); 5253 PetscFunctionReturn(PETSC_SUCCESS); 5254 } 5255 5256 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B) 5257 { 5258 PetscContainer rB; 5259 MatParentState *rb; 5260 5261 PetscFunctionBegin; 5262 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5263 PetscValidType(A, 1); 5264 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5265 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5266 PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB)); 5267 PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()"); 5268 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5269 PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5270 PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure"); 5271 PetscFunctionReturn(PETSC_SUCCESS); 5272 } 5273 5274 /*@ 5275 MatIsTranspose - Test whether a matrix is another one's transpose, 5276 or its own, in which case it tests symmetry. 5277 5278 Collective 5279 5280 Input Parameters: 5281 + A - the matrix to test 5282 . B - the matrix to test against, this can equal the first parameter 5283 - tol - tolerance, differences between entries smaller than this are counted as zero 5284 5285 Output Parameter: 5286 . flg - the result 5287 5288 Level: intermediate 5289 5290 Notes: 5291 Only available for `MATAIJ` matrices. 5292 5293 The sequential algorithm has a running time of the order of the number of nonzeros; the parallel 5294 test involves parallel copies of the block-offdiagonal parts of the matrix. 5295 5296 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()` 5297 @*/ 5298 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5299 { 5300 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5301 5302 PetscFunctionBegin; 5303 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5304 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5305 PetscValidBoolPointer(flg, 4); 5306 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f)); 5307 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g)); 5308 *flg = PETSC_FALSE; 5309 if (f && g) { 5310 PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test"); 5311 PetscCall((*f)(A, B, tol, flg)); 5312 } else { 5313 MatType mattype; 5314 5315 PetscCall(MatGetType(f ? B : A, &mattype)); 5316 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype); 5317 } 5318 PetscFunctionReturn(PETSC_SUCCESS); 5319 } 5320 5321 /*@ 5322 MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate. 5323 5324 Collective 5325 5326 Input Parameters: 5327 + mat - the matrix to transpose and complex conjugate 5328 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5329 5330 Output Parameter: 5331 . B - the Hermitian transpose 5332 5333 Level: intermediate 5334 5335 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse` 5336 @*/ 5337 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B) 5338 { 5339 PetscFunctionBegin; 5340 PetscCall(MatTranspose(mat, reuse, B)); 5341 #if defined(PETSC_USE_COMPLEX) 5342 PetscCall(MatConjugate(*B)); 5343 #endif 5344 PetscFunctionReturn(PETSC_SUCCESS); 5345 } 5346 5347 /*@ 5348 MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose, 5349 5350 Collective 5351 5352 Input Parameters: 5353 + A - the matrix to test 5354 . B - the matrix to test against, this can equal the first parameter 5355 - tol - tolerance, differences between entries smaller than this are counted as zero 5356 5357 Output Parameter: 5358 . flg - the result 5359 5360 Level: intermediate 5361 5362 Notes: 5363 Only available for `MATAIJ` matrices. 5364 5365 The sequential algorithm 5366 has a running time of the order of the number of nonzeros; the parallel 5367 test involves parallel copies of the block-offdiagonal parts of the matrix. 5368 5369 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()` 5370 @*/ 5371 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5372 { 5373 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5374 5375 PetscFunctionBegin; 5376 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5377 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5378 PetscValidBoolPointer(flg, 4); 5379 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f)); 5380 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g)); 5381 if (f && g) { 5382 PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test"); 5383 PetscCall((*f)(A, B, tol, flg)); 5384 } 5385 PetscFunctionReturn(PETSC_SUCCESS); 5386 } 5387 5388 /*@ 5389 MatPermute - Creates a new matrix with rows and columns permuted from the 5390 original. 5391 5392 Collective 5393 5394 Input Parameters: 5395 + mat - the matrix to permute 5396 . row - row permutation, each processor supplies only the permutation for its rows 5397 - col - column permutation, each processor supplies only the permutation for its columns 5398 5399 Output Parameter: 5400 . B - the permuted matrix 5401 5402 Level: advanced 5403 5404 Note: 5405 The index sets map from row/col of permuted matrix to row/col of original matrix. 5406 The index sets should be on the same communicator as mat and have the same local sizes. 5407 5408 Developer Note: 5409 If you want to implement `MatPermute()` for a matrix type, and your approach doesn't 5410 exploit the fact that row and col are permutations, consider implementing the 5411 more general `MatCreateSubMatrix()` instead. 5412 5413 .seealso: [](chapter_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()` 5414 @*/ 5415 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B) 5416 { 5417 PetscFunctionBegin; 5418 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5419 PetscValidType(mat, 1); 5420 PetscValidHeaderSpecific(row, IS_CLASSID, 2); 5421 PetscValidHeaderSpecific(col, IS_CLASSID, 3); 5422 PetscValidPointer(B, 4); 5423 PetscCheckSameComm(mat, 1, row, 2); 5424 if (row != col) PetscCheckSameComm(row, 2, col, 3); 5425 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5426 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5427 PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name); 5428 MatCheckPreallocated(mat, 1); 5429 5430 if (mat->ops->permute) { 5431 PetscUseTypeMethod(mat, permute, row, col, B); 5432 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5433 } else { 5434 PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B)); 5435 } 5436 PetscFunctionReturn(PETSC_SUCCESS); 5437 } 5438 5439 /*@ 5440 MatEqual - Compares two matrices. 5441 5442 Collective 5443 5444 Input Parameters: 5445 + A - the first matrix 5446 - B - the second matrix 5447 5448 Output Parameter: 5449 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise. 5450 5451 Level: intermediate 5452 5453 .seealso: [](chapter_matrices), `Mat` 5454 @*/ 5455 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg) 5456 { 5457 PetscFunctionBegin; 5458 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5459 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5460 PetscValidType(A, 1); 5461 PetscValidType(B, 2); 5462 PetscValidBoolPointer(flg, 3); 5463 PetscCheckSameComm(A, 1, B, 2); 5464 MatCheckPreallocated(A, 1); 5465 MatCheckPreallocated(B, 2); 5466 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5467 PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5468 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, 5469 B->cmap->N); 5470 if (A->ops->equal && A->ops->equal == B->ops->equal) { 5471 PetscUseTypeMethod(A, equal, B, flg); 5472 } else { 5473 PetscCall(MatMultEqual(A, B, 10, flg)); 5474 } 5475 PetscFunctionReturn(PETSC_SUCCESS); 5476 } 5477 5478 /*@ 5479 MatDiagonalScale - Scales a matrix on the left and right by diagonal 5480 matrices that are stored as vectors. Either of the two scaling 5481 matrices can be `NULL`. 5482 5483 Collective 5484 5485 Input Parameters: 5486 + mat - the matrix to be scaled 5487 . l - the left scaling vector (or `NULL`) 5488 - r - the right scaling vector (or `NULL`) 5489 5490 Level: intermediate 5491 5492 Note: 5493 `MatDiagonalScale()` computes A = LAR, where 5494 L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector) 5495 The L scales the rows of the matrix, the R scales the columns of the matrix. 5496 5497 .seealso: [](chapter_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()` 5498 @*/ 5499 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r) 5500 { 5501 PetscFunctionBegin; 5502 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5503 PetscValidType(mat, 1); 5504 if (l) { 5505 PetscValidHeaderSpecific(l, VEC_CLASSID, 2); 5506 PetscCheckSameComm(mat, 1, l, 2); 5507 } 5508 if (r) { 5509 PetscValidHeaderSpecific(r, VEC_CLASSID, 3); 5510 PetscCheckSameComm(mat, 1, r, 3); 5511 } 5512 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5513 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5514 MatCheckPreallocated(mat, 1); 5515 if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS); 5516 5517 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5518 PetscUseTypeMethod(mat, diagonalscale, l, r); 5519 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5520 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5521 if (l != r) mat->symmetric = PETSC_BOOL3_FALSE; 5522 PetscFunctionReturn(PETSC_SUCCESS); 5523 } 5524 5525 /*@ 5526 MatScale - Scales all elements of a matrix by a given number. 5527 5528 Logically Collective 5529 5530 Input Parameters: 5531 + mat - the matrix to be scaled 5532 - a - the scaling value 5533 5534 Level: intermediate 5535 5536 .seealso: [](chapter_matrices), `Mat`, `MatDiagonalScale()` 5537 @*/ 5538 PetscErrorCode MatScale(Mat mat, PetscScalar a) 5539 { 5540 PetscFunctionBegin; 5541 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5542 PetscValidType(mat, 1); 5543 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5544 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5545 PetscValidLogicalCollectiveScalar(mat, a, 2); 5546 MatCheckPreallocated(mat, 1); 5547 5548 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5549 if (a != (PetscScalar)1.0) { 5550 PetscUseTypeMethod(mat, scale, a); 5551 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5552 } 5553 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5554 PetscFunctionReturn(PETSC_SUCCESS); 5555 } 5556 5557 /*@ 5558 MatNorm - Calculates various norms of a matrix. 5559 5560 Collective 5561 5562 Input Parameters: 5563 + mat - the matrix 5564 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY` 5565 5566 Output Parameter: 5567 . nrm - the resulting norm 5568 5569 Level: intermediate 5570 5571 .seealso: [](chapter_matrices), `Mat` 5572 @*/ 5573 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm) 5574 { 5575 PetscFunctionBegin; 5576 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5577 PetscValidType(mat, 1); 5578 PetscValidRealPointer(nrm, 3); 5579 5580 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5581 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5582 MatCheckPreallocated(mat, 1); 5583 5584 PetscUseTypeMethod(mat, norm, type, nrm); 5585 PetscFunctionReturn(PETSC_SUCCESS); 5586 } 5587 5588 /* 5589 This variable is used to prevent counting of MatAssemblyBegin() that 5590 are called from within a MatAssemblyEnd(). 5591 */ 5592 static PetscInt MatAssemblyEnd_InUse = 0; 5593 /*@ 5594 MatAssemblyBegin - Begins assembling the matrix. This routine should 5595 be called after completing all calls to `MatSetValues()`. 5596 5597 Collective 5598 5599 Input Parameters: 5600 + mat - the matrix 5601 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5602 5603 Level: beginner 5604 5605 Notes: 5606 `MatSetValues()` generally caches the values that belong to other MPI ranks. The matrix is ready to 5607 use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called. 5608 5609 Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES` 5610 in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before 5611 using the matrix. 5612 5613 ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the 5614 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 5615 a global collective operation requiring all processes that share the matrix. 5616 5617 Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed 5618 out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros 5619 before `MAT_FINAL_ASSEMBLY` so the space is not compressed out. 5620 5621 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()` 5622 @*/ 5623 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type) 5624 { 5625 PetscFunctionBegin; 5626 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5627 PetscValidType(mat, 1); 5628 MatCheckPreallocated(mat, 1); 5629 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?"); 5630 if (mat->assembled) { 5631 mat->was_assembled = PETSC_TRUE; 5632 mat->assembled = PETSC_FALSE; 5633 } 5634 5635 if (!MatAssemblyEnd_InUse) { 5636 PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0)); 5637 PetscTryTypeMethod(mat, assemblybegin, type); 5638 PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0)); 5639 } else PetscTryTypeMethod(mat, assemblybegin, type); 5640 PetscFunctionReturn(PETSC_SUCCESS); 5641 } 5642 5643 /*@ 5644 MatAssembled - Indicates if a matrix has been assembled and is ready for 5645 use; for example, in matrix-vector product. 5646 5647 Not Collective 5648 5649 Input Parameter: 5650 . mat - the matrix 5651 5652 Output Parameter: 5653 . assembled - `PETSC_TRUE` or `PETSC_FALSE` 5654 5655 Level: advanced 5656 5657 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()` 5658 @*/ 5659 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled) 5660 { 5661 PetscFunctionBegin; 5662 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5663 PetscValidBoolPointer(assembled, 2); 5664 *assembled = mat->assembled; 5665 PetscFunctionReturn(PETSC_SUCCESS); 5666 } 5667 5668 /*@ 5669 MatAssemblyEnd - Completes assembling the matrix. This routine should 5670 be called after `MatAssemblyBegin()`. 5671 5672 Collective 5673 5674 Input Parameters: 5675 + mat - the matrix 5676 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5677 5678 Options Database Keys: 5679 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatEndAssembly()` 5680 . -mat_view ::ascii_info_detail - Prints more detailed info 5681 . -mat_view - Prints matrix in ASCII format 5682 . -mat_view ::ascii_matlab - Prints matrix in Matlab format 5683 . -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 5684 . -display <name> - Sets display name (default is host) 5685 . -draw_pause <sec> - Sets number of seconds to pause after display 5686 . -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See [Using MATLAB with PETSc](ch_matlab)) 5687 . -viewer_socket_machine <machine> - Machine to use for socket 5688 . -viewer_socket_port <port> - Port number to use for socket 5689 - -mat_view binary:filename[:append] - Save matrix to file in binary format 5690 5691 Level: beginner 5692 5693 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()` 5694 @*/ 5695 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type) 5696 { 5697 static PetscInt inassm = 0; 5698 PetscBool flg = PETSC_FALSE; 5699 5700 PetscFunctionBegin; 5701 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5702 PetscValidType(mat, 1); 5703 5704 inassm++; 5705 MatAssemblyEnd_InUse++; 5706 if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */ 5707 PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0)); 5708 PetscTryTypeMethod(mat, assemblyend, type); 5709 PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0)); 5710 } else PetscTryTypeMethod(mat, assemblyend, type); 5711 5712 /* Flush assembly is not a true assembly */ 5713 if (type != MAT_FLUSH_ASSEMBLY) { 5714 if (mat->num_ass) { 5715 if (!mat->symmetry_eternal) { 5716 mat->symmetric = PETSC_BOOL3_UNKNOWN; 5717 mat->hermitian = PETSC_BOOL3_UNKNOWN; 5718 } 5719 if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN; 5720 if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN; 5721 } 5722 mat->num_ass++; 5723 mat->assembled = PETSC_TRUE; 5724 mat->ass_nonzerostate = mat->nonzerostate; 5725 } 5726 5727 mat->insertmode = NOT_SET_VALUES; 5728 MatAssemblyEnd_InUse--; 5729 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5730 if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) { 5731 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 5732 5733 if (mat->checksymmetryonassembly) { 5734 PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg)); 5735 if (flg) { 5736 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5737 } else { 5738 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5739 } 5740 } 5741 if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL)); 5742 } 5743 inassm--; 5744 PetscFunctionReturn(PETSC_SUCCESS); 5745 } 5746 5747 /*@ 5748 MatSetOption - Sets a parameter option for a matrix. Some options 5749 may be specific to certain storage formats. Some options 5750 determine how values will be inserted (or added). Sorted, 5751 row-oriented input will generally assemble the fastest. The default 5752 is row-oriented. 5753 5754 Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption` 5755 5756 Input Parameters: 5757 + mat - the matrix 5758 . option - the option, one of those listed below (and possibly others), 5759 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5760 5761 Options Describing Matrix Structure: 5762 + `MAT_SPD` - symmetric positive definite 5763 . `MAT_SYMMETRIC` - symmetric in terms of both structure and value 5764 . `MAT_HERMITIAN` - transpose is the complex conjugation 5765 . `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure 5766 . `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix 5767 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix 5768 - `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix 5769 5770 These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they 5771 do not need to be computed (usually at a high cost) 5772 5773 Options For Use with `MatSetValues()`: 5774 Insert a logically dense subblock, which can be 5775 . `MAT_ROW_ORIENTED` - row-oriented (default) 5776 5777 These options reflect the data you pass in with `MatSetValues()`; it has 5778 nothing to do with how the data is stored internally in the matrix 5779 data structure. 5780 5781 When (re)assembling a matrix, we can restrict the input for 5782 efficiency/debugging purposes. These options include 5783 + `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow) 5784 . `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated 5785 . `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries 5786 . `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry 5787 . `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly 5788 . `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if 5789 any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves 5790 performance for very large process counts. 5791 - `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset 5792 of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly 5793 functions, instead sending only neighbor messages. 5794 5795 Level: intermediate 5796 5797 Notes: 5798 Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg! 5799 5800 Some options are relevant only for particular matrix types and 5801 are thus ignored by others. Other options are not supported by 5802 certain matrix types and will generate an error message if set. 5803 5804 If using Fortran to compute a matrix, one may need to 5805 use the column-oriented option (or convert to the row-oriented 5806 format). 5807 5808 `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion 5809 that would generate a new entry in the nonzero structure is instead 5810 ignored. Thus, if memory has not already been allocated for this particular 5811 data, then the insertion is ignored. For dense matrices, in which 5812 the entire array is allocated, no entries are ever ignored. 5813 Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction 5814 5815 `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion 5816 that would generate a new entry in the nonzero structure instead produces 5817 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 5818 5819 `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion 5820 that would generate a new entry that has not been preallocated will 5821 instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats 5822 only.) This is a useful flag when debugging matrix memory preallocation. 5823 If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 5824 5825 `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for 5826 other processors should be dropped, rather than stashed. 5827 This is useful if you know that the "owning" processor is also 5828 always generating the correct matrix entries, so that PETSc need 5829 not transfer duplicate entries generated on another processor. 5830 5831 `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the 5832 searches during matrix assembly. When this flag is set, the hash table 5833 is created during the first matrix assembly. This hash table is 5834 used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()` 5835 to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag 5836 should be used with `MAT_USE_HASH_TABLE` flag. This option is currently 5837 supported by `MATMPIBAIJ` format only. 5838 5839 `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries 5840 are kept in the nonzero structure 5841 5842 `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating 5843 a zero location in the matrix 5844 5845 `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types 5846 5847 `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the 5848 zero row routines and thus improves performance for very large process counts. 5849 5850 `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular 5851 part of the matrix (since they should match the upper triangular part). 5852 5853 `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a 5854 single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common 5855 with finite difference schemes with non-periodic boundary conditions. 5856 5857 Developer Note: 5858 `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other 5859 places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRIC` or `MAT_SPD` would need to be changed back 5860 to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had 5861 not changed. 5862 5863 .seealso: [](chapter_matrices), `MatOption`, `Mat`, `MatGetOption()` 5864 @*/ 5865 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg) 5866 { 5867 PetscFunctionBegin; 5868 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5869 if (op > 0) { 5870 PetscValidLogicalCollectiveEnum(mat, op, 2); 5871 PetscValidLogicalCollectiveBool(mat, flg, 3); 5872 } 5873 5874 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); 5875 5876 switch (op) { 5877 case MAT_FORCE_DIAGONAL_ENTRIES: 5878 mat->force_diagonals = flg; 5879 PetscFunctionReturn(PETSC_SUCCESS); 5880 case MAT_NO_OFF_PROC_ENTRIES: 5881 mat->nooffprocentries = flg; 5882 PetscFunctionReturn(PETSC_SUCCESS); 5883 case MAT_SUBSET_OFF_PROC_ENTRIES: 5884 mat->assembly_subset = flg; 5885 if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */ 5886 #if !defined(PETSC_HAVE_MPIUNI) 5887 PetscCall(MatStashScatterDestroy_BTS(&mat->stash)); 5888 #endif 5889 mat->stash.first_assembly_done = PETSC_FALSE; 5890 } 5891 PetscFunctionReturn(PETSC_SUCCESS); 5892 case MAT_NO_OFF_PROC_ZERO_ROWS: 5893 mat->nooffproczerorows = flg; 5894 PetscFunctionReturn(PETSC_SUCCESS); 5895 case MAT_SPD: 5896 if (flg) { 5897 mat->spd = PETSC_BOOL3_TRUE; 5898 mat->symmetric = PETSC_BOOL3_TRUE; 5899 mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5900 } else { 5901 mat->spd = PETSC_BOOL3_FALSE; 5902 } 5903 break; 5904 case MAT_SYMMETRIC: 5905 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5906 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5907 #if !defined(PETSC_USE_COMPLEX) 5908 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5909 #endif 5910 break; 5911 case MAT_HERMITIAN: 5912 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5913 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5914 #if !defined(PETSC_USE_COMPLEX) 5915 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5916 #endif 5917 break; 5918 case MAT_STRUCTURALLY_SYMMETRIC: 5919 mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5920 break; 5921 case MAT_SYMMETRY_ETERNAL: 5922 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"); 5923 mat->symmetry_eternal = flg; 5924 if (flg) mat->structural_symmetry_eternal = PETSC_TRUE; 5925 break; 5926 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 5927 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"); 5928 mat->structural_symmetry_eternal = flg; 5929 break; 5930 case MAT_SPD_ETERNAL: 5931 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"); 5932 mat->spd_eternal = flg; 5933 if (flg) { 5934 mat->structural_symmetry_eternal = PETSC_TRUE; 5935 mat->symmetry_eternal = PETSC_TRUE; 5936 } 5937 break; 5938 case MAT_STRUCTURE_ONLY: 5939 mat->structure_only = flg; 5940 break; 5941 case MAT_SORTED_FULL: 5942 mat->sortedfull = flg; 5943 break; 5944 default: 5945 break; 5946 } 5947 PetscTryTypeMethod(mat, setoption, op, flg); 5948 PetscFunctionReturn(PETSC_SUCCESS); 5949 } 5950 5951 /*@ 5952 MatGetOption - Gets a parameter option that has been set for a matrix. 5953 5954 Logically Collective 5955 5956 Input Parameters: 5957 + mat - the matrix 5958 - option - the option, this only responds to certain options, check the code for which ones 5959 5960 Output Parameter: 5961 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5962 5963 Level: intermediate 5964 5965 Notes: 5966 Can only be called after `MatSetSizes()` and `MatSetType()` have been set. 5967 5968 Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or 5969 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 5970 5971 .seealso: [](chapter_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, 5972 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 5973 @*/ 5974 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg) 5975 { 5976 PetscFunctionBegin; 5977 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5978 PetscValidType(mat, 1); 5979 5980 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); 5981 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()"); 5982 5983 switch (op) { 5984 case MAT_NO_OFF_PROC_ENTRIES: 5985 *flg = mat->nooffprocentries; 5986 break; 5987 case MAT_NO_OFF_PROC_ZERO_ROWS: 5988 *flg = mat->nooffproczerorows; 5989 break; 5990 case MAT_SYMMETRIC: 5991 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()"); 5992 break; 5993 case MAT_HERMITIAN: 5994 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()"); 5995 break; 5996 case MAT_STRUCTURALLY_SYMMETRIC: 5997 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()"); 5998 break; 5999 case MAT_SPD: 6000 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()"); 6001 break; 6002 case MAT_SYMMETRY_ETERNAL: 6003 *flg = mat->symmetry_eternal; 6004 break; 6005 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6006 *flg = mat->symmetry_eternal; 6007 break; 6008 default: 6009 break; 6010 } 6011 PetscFunctionReturn(PETSC_SUCCESS); 6012 } 6013 6014 /*@ 6015 MatZeroEntries - Zeros all entries of a matrix. For sparse matrices 6016 this routine retains the old nonzero structure. 6017 6018 Logically Collective 6019 6020 Input Parameter: 6021 . mat - the matrix 6022 6023 Level: intermediate 6024 6025 Note: 6026 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. 6027 See the Performance chapter of the users manual for information on preallocating matrices. 6028 6029 .seealso: [](chapter_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()` 6030 @*/ 6031 PetscErrorCode MatZeroEntries(Mat mat) 6032 { 6033 PetscFunctionBegin; 6034 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6035 PetscValidType(mat, 1); 6036 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6037 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"); 6038 MatCheckPreallocated(mat, 1); 6039 6040 PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0)); 6041 PetscUseTypeMethod(mat, zeroentries); 6042 PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0)); 6043 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6044 PetscFunctionReturn(PETSC_SUCCESS); 6045 } 6046 6047 /*@ 6048 MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal) 6049 of a set of rows and columns of a matrix. 6050 6051 Collective 6052 6053 Input Parameters: 6054 + mat - the matrix 6055 . numRows - the number of rows/columns to zero 6056 . rows - the global row indices 6057 . diag - value put in the diagonal of the eliminated rows 6058 . x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call 6059 - b - optional vector of the right hand side, that will be adjusted by provided solution entries 6060 6061 Level: intermediate 6062 6063 Notes: 6064 This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6065 6066 For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`. 6067 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 6068 6069 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6070 Krylov method to take advantage of the known solution on the zeroed rows. 6071 6072 For the parallel case, all processes that share the matrix (i.e., 6073 those in the communicator used for matrix creation) MUST call this 6074 routine, regardless of whether any rows being zeroed are owned by 6075 them. 6076 6077 Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix. 6078 6079 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6080 list only rows local to itself). 6081 6082 The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine. 6083 6084 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6085 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6086 @*/ 6087 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6088 { 6089 PetscFunctionBegin; 6090 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6091 PetscValidType(mat, 1); 6092 if (numRows) PetscValidIntPointer(rows, 3); 6093 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6094 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6095 MatCheckPreallocated(mat, 1); 6096 6097 PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b); 6098 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6099 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6100 PetscFunctionReturn(PETSC_SUCCESS); 6101 } 6102 6103 /*@ 6104 MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal) 6105 of a set of rows and columns of a matrix. 6106 6107 Collective 6108 6109 Input Parameters: 6110 + mat - the matrix 6111 . is - the rows to zero 6112 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6113 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6114 - b - optional vector of right hand side, that will be adjusted by provided solution 6115 6116 Level: intermediate 6117 6118 Note: 6119 See `MatZeroRowsColumns()` for details on how this routine operates. 6120 6121 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6122 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()` 6123 @*/ 6124 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6125 { 6126 PetscInt numRows; 6127 const PetscInt *rows; 6128 6129 PetscFunctionBegin; 6130 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6131 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6132 PetscValidType(mat, 1); 6133 PetscValidType(is, 2); 6134 PetscCall(ISGetLocalSize(is, &numRows)); 6135 PetscCall(ISGetIndices(is, &rows)); 6136 PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b)); 6137 PetscCall(ISRestoreIndices(is, &rows)); 6138 PetscFunctionReturn(PETSC_SUCCESS); 6139 } 6140 6141 /*@ 6142 MatZeroRows - Zeros all entries (except possibly the main diagonal) 6143 of a set of rows of a matrix. 6144 6145 Collective 6146 6147 Input Parameters: 6148 + mat - the matrix 6149 . numRows - the number of rows to zero 6150 . rows - the global row indices 6151 . diag - value put in the diagonal of the zeroed rows 6152 . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call 6153 - b - optional vector of right hand side, that will be adjusted by provided solution entries 6154 6155 Level: intermediate 6156 6157 Notes: 6158 This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6159 6160 For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`. 6161 6162 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6163 Krylov method to take advantage of the known solution on the zeroed rows. 6164 6165 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) 6166 from the matrix. 6167 6168 Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix 6169 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 6170 formats this does not alter the nonzero structure. 6171 6172 If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure 6173 of the matrix is not changed the values are 6174 merely zeroed. 6175 6176 The user can set a value in the diagonal entry (or for the `MATAIJ` format 6177 formats can optionally remove the main diagonal entry from the 6178 nonzero structure as well, by passing 0.0 as the final argument). 6179 6180 For the parallel case, all processes that share the matrix (i.e., 6181 those in the communicator used for matrix creation) MUST call this 6182 routine, regardless of whether any rows being zeroed are owned by 6183 them. 6184 6185 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6186 list only rows local to itself). 6187 6188 You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it 6189 owns that are to be zeroed. This saves a global synchronization in the implementation. 6190 6191 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6192 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE` 6193 @*/ 6194 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6195 { 6196 PetscFunctionBegin; 6197 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6198 PetscValidType(mat, 1); 6199 if (numRows) PetscValidIntPointer(rows, 3); 6200 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6201 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6202 MatCheckPreallocated(mat, 1); 6203 6204 PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b); 6205 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6206 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6207 PetscFunctionReturn(PETSC_SUCCESS); 6208 } 6209 6210 /*@ 6211 MatZeroRowsIS - Zeros all entries (except possibly the main diagonal) 6212 of a set of rows of a matrix. 6213 6214 Collective 6215 6216 Input Parameters: 6217 + mat - the matrix 6218 . is - index set of rows to remove (if `NULL` then no row is removed) 6219 . diag - value put in all diagonals of eliminated rows 6220 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6221 - b - optional vector of right hand side, that will be adjusted by provided solution 6222 6223 Level: intermediate 6224 6225 Note: 6226 See `MatZeroRows()` for details on how this routine operates. 6227 6228 .seealso: [](chapter_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6229 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6230 @*/ 6231 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6232 { 6233 PetscInt numRows = 0; 6234 const PetscInt *rows = NULL; 6235 6236 PetscFunctionBegin; 6237 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6238 PetscValidType(mat, 1); 6239 if (is) { 6240 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6241 PetscCall(ISGetLocalSize(is, &numRows)); 6242 PetscCall(ISGetIndices(is, &rows)); 6243 } 6244 PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b)); 6245 if (is) PetscCall(ISRestoreIndices(is, &rows)); 6246 PetscFunctionReturn(PETSC_SUCCESS); 6247 } 6248 6249 /*@ 6250 MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal) 6251 of a set of rows of a matrix. These rows must be local to the process. 6252 6253 Collective 6254 6255 Input Parameters: 6256 + mat - the matrix 6257 . numRows - the number of rows to remove 6258 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6259 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6260 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6261 - b - optional vector of right hand side, that will be adjusted by provided solution 6262 6263 Level: intermediate 6264 6265 Notes: 6266 See `MatZeroRows()` for details on how this routine operates. 6267 6268 The grid coordinates are across the entire grid, not just the local portion 6269 6270 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6271 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6272 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6273 `DM_BOUNDARY_PERIODIC` boundary type. 6274 6275 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 6276 a single value per point) you can skip filling those indices. 6277 6278 Fortran Note: 6279 `idxm` and `idxn` should be declared as 6280 $ MatStencil idxm(4,m) 6281 and the values inserted using 6282 .vb 6283 idxm(MatStencil_i,1) = i 6284 idxm(MatStencil_j,1) = j 6285 idxm(MatStencil_k,1) = k 6286 idxm(MatStencil_c,1) = c 6287 etc 6288 .ve 6289 6290 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6291 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6292 @*/ 6293 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6294 { 6295 PetscInt dim = mat->stencil.dim; 6296 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6297 PetscInt *dims = mat->stencil.dims + 1; 6298 PetscInt *starts = mat->stencil.starts; 6299 PetscInt *dxm = (PetscInt *)rows; 6300 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6301 6302 PetscFunctionBegin; 6303 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6304 PetscValidType(mat, 1); 6305 if (numRows) PetscValidPointer(rows, 3); 6306 6307 PetscCall(PetscMalloc1(numRows, &jdxm)); 6308 for (i = 0; i < numRows; ++i) { 6309 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6310 for (j = 0; j < 3 - sdim; ++j) dxm++; 6311 /* Local index in X dir */ 6312 tmp = *dxm++ - starts[0]; 6313 /* Loop over remaining dimensions */ 6314 for (j = 0; j < dim - 1; ++j) { 6315 /* If nonlocal, set index to be negative */ 6316 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6317 /* Update local index */ 6318 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6319 } 6320 /* Skip component slot if necessary */ 6321 if (mat->stencil.noc) dxm++; 6322 /* Local row number */ 6323 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6324 } 6325 PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b)); 6326 PetscCall(PetscFree(jdxm)); 6327 PetscFunctionReturn(PETSC_SUCCESS); 6328 } 6329 6330 /*@ 6331 MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal) 6332 of a set of rows and columns of a matrix. 6333 6334 Collective 6335 6336 Input Parameters: 6337 + mat - the matrix 6338 . numRows - the number of rows/columns to remove 6339 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6340 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6341 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6342 - b - optional vector of right hand side, that will be adjusted by provided solution 6343 6344 Level: intermediate 6345 6346 Notes: 6347 See `MatZeroRowsColumns()` for details on how this routine operates. 6348 6349 The grid coordinates are across the entire grid, not just the local portion 6350 6351 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6352 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6353 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6354 `DM_BOUNDARY_PERIODIC` boundary type. 6355 6356 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 6357 a single value per point) you can skip filling those indices. 6358 6359 Fortran Note: 6360 `idxm` and `idxn` should be declared as 6361 $ MatStencil idxm(4,m) 6362 and the values inserted using 6363 .vb 6364 idxm(MatStencil_i,1) = i 6365 idxm(MatStencil_j,1) = j 6366 idxm(MatStencil_k,1) = k 6367 idxm(MatStencil_c,1) = c 6368 etc 6369 .ve 6370 6371 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6372 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()` 6373 @*/ 6374 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6375 { 6376 PetscInt dim = mat->stencil.dim; 6377 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6378 PetscInt *dims = mat->stencil.dims + 1; 6379 PetscInt *starts = mat->stencil.starts; 6380 PetscInt *dxm = (PetscInt *)rows; 6381 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6382 6383 PetscFunctionBegin; 6384 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6385 PetscValidType(mat, 1); 6386 if (numRows) PetscValidPointer(rows, 3); 6387 6388 PetscCall(PetscMalloc1(numRows, &jdxm)); 6389 for (i = 0; i < numRows; ++i) { 6390 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6391 for (j = 0; j < 3 - sdim; ++j) dxm++; 6392 /* Local index in X dir */ 6393 tmp = *dxm++ - starts[0]; 6394 /* Loop over remaining dimensions */ 6395 for (j = 0; j < dim - 1; ++j) { 6396 /* If nonlocal, set index to be negative */ 6397 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6398 /* Update local index */ 6399 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6400 } 6401 /* Skip component slot if necessary */ 6402 if (mat->stencil.noc) dxm++; 6403 /* Local row number */ 6404 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6405 } 6406 PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b)); 6407 PetscCall(PetscFree(jdxm)); 6408 PetscFunctionReturn(PETSC_SUCCESS); 6409 } 6410 6411 /*@C 6412 MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal) 6413 of a set of rows of a matrix; using local numbering of rows. 6414 6415 Collective 6416 6417 Input Parameters: 6418 + mat - the matrix 6419 . numRows - the number of rows to remove 6420 . rows - the local row indices 6421 . diag - value put in all diagonals of eliminated rows 6422 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6423 - b - optional vector of right hand side, that will be adjusted by provided solution 6424 6425 Level: intermediate 6426 6427 Notes: 6428 Before calling `MatZeroRowsLocal()`, the user must first set the 6429 local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`. 6430 6431 See `MatZeroRows()` for details on how this routine operates. 6432 6433 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`, 6434 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6435 @*/ 6436 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6437 { 6438 PetscFunctionBegin; 6439 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6440 PetscValidType(mat, 1); 6441 if (numRows) PetscValidIntPointer(rows, 3); 6442 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6443 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6444 MatCheckPreallocated(mat, 1); 6445 6446 if (mat->ops->zerorowslocal) { 6447 PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b); 6448 } else { 6449 IS is, newis; 6450 const PetscInt *newRows; 6451 6452 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6453 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6454 PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis)); 6455 PetscCall(ISGetIndices(newis, &newRows)); 6456 PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b); 6457 PetscCall(ISRestoreIndices(newis, &newRows)); 6458 PetscCall(ISDestroy(&newis)); 6459 PetscCall(ISDestroy(&is)); 6460 } 6461 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6462 PetscFunctionReturn(PETSC_SUCCESS); 6463 } 6464 6465 /*@ 6466 MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal) 6467 of a set of rows of a matrix; using local numbering of rows. 6468 6469 Collective 6470 6471 Input Parameters: 6472 + mat - the matrix 6473 . is - index set of rows to remove 6474 . diag - value put in all diagonals of eliminated rows 6475 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6476 - b - optional vector of right hand side, that will be adjusted by provided solution 6477 6478 Level: intermediate 6479 6480 Notes: 6481 Before calling `MatZeroRowsLocalIS()`, the user must first set the 6482 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6483 6484 See `MatZeroRows()` for details on how this routine operates. 6485 6486 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6487 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6488 @*/ 6489 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6490 { 6491 PetscInt numRows; 6492 const PetscInt *rows; 6493 6494 PetscFunctionBegin; 6495 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6496 PetscValidType(mat, 1); 6497 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6498 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6499 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6500 MatCheckPreallocated(mat, 1); 6501 6502 PetscCall(ISGetLocalSize(is, &numRows)); 6503 PetscCall(ISGetIndices(is, &rows)); 6504 PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b)); 6505 PetscCall(ISRestoreIndices(is, &rows)); 6506 PetscFunctionReturn(PETSC_SUCCESS); 6507 } 6508 6509 /*@ 6510 MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal) 6511 of a set of rows and columns of a matrix; using local numbering of rows. 6512 6513 Collective 6514 6515 Input Parameters: 6516 + mat - the matrix 6517 . numRows - the number of rows to remove 6518 . rows - the global row indices 6519 . diag - value put in all diagonals of eliminated rows 6520 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6521 - b - optional vector of right hand side, that will be adjusted by provided solution 6522 6523 Level: intermediate 6524 6525 Notes: 6526 Before calling `MatZeroRowsColumnsLocal()`, the user must first set the 6527 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6528 6529 See `MatZeroRowsColumns()` for details on how this routine operates. 6530 6531 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6532 `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6533 @*/ 6534 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6535 { 6536 IS is, newis; 6537 const PetscInt *newRows; 6538 6539 PetscFunctionBegin; 6540 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6541 PetscValidType(mat, 1); 6542 if (numRows) PetscValidIntPointer(rows, 3); 6543 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6544 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6545 MatCheckPreallocated(mat, 1); 6546 6547 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6548 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6549 PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis)); 6550 PetscCall(ISGetIndices(newis, &newRows)); 6551 PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b); 6552 PetscCall(ISRestoreIndices(newis, &newRows)); 6553 PetscCall(ISDestroy(&newis)); 6554 PetscCall(ISDestroy(&is)); 6555 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6556 PetscFunctionReturn(PETSC_SUCCESS); 6557 } 6558 6559 /*@ 6560 MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal) 6561 of a set of rows and columns of a matrix; using local numbering of rows. 6562 6563 Collective 6564 6565 Input Parameters: 6566 + mat - the matrix 6567 . is - index set of rows to remove 6568 . diag - value put in all diagonals of eliminated rows 6569 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6570 - b - optional vector of right hand side, that will be adjusted by provided solution 6571 6572 Level: intermediate 6573 6574 Notes: 6575 Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the 6576 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6577 6578 See `MatZeroRowsColumns()` for details on how this routine operates. 6579 6580 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6581 `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6582 @*/ 6583 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6584 { 6585 PetscInt numRows; 6586 const PetscInt *rows; 6587 6588 PetscFunctionBegin; 6589 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6590 PetscValidType(mat, 1); 6591 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6592 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6593 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6594 MatCheckPreallocated(mat, 1); 6595 6596 PetscCall(ISGetLocalSize(is, &numRows)); 6597 PetscCall(ISGetIndices(is, &rows)); 6598 PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b)); 6599 PetscCall(ISRestoreIndices(is, &rows)); 6600 PetscFunctionReturn(PETSC_SUCCESS); 6601 } 6602 6603 /*@C 6604 MatGetSize - Returns the numbers of rows and columns in a matrix. 6605 6606 Not Collective 6607 6608 Input Parameter: 6609 . mat - the matrix 6610 6611 Output Parameters: 6612 + m - the number of global rows 6613 - n - the number of global columns 6614 6615 Level: beginner 6616 6617 Note: 6618 Both output parameters can be `NULL` on input. 6619 6620 .seealso: [](chapter_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()` 6621 @*/ 6622 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n) 6623 { 6624 PetscFunctionBegin; 6625 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6626 if (m) *m = mat->rmap->N; 6627 if (n) *n = mat->cmap->N; 6628 PetscFunctionReturn(PETSC_SUCCESS); 6629 } 6630 6631 /*@C 6632 MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns 6633 of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`. 6634 6635 Not Collective 6636 6637 Input Parameter: 6638 . mat - the matrix 6639 6640 Output Parameters: 6641 + m - the number of local rows, use `NULL` to not obtain this value 6642 - n - the number of local columns, use `NULL` to not obtain this value 6643 6644 Level: beginner 6645 6646 .seealso: [](chapter_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()` 6647 @*/ 6648 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n) 6649 { 6650 PetscFunctionBegin; 6651 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6652 if (m) PetscValidIntPointer(m, 2); 6653 if (n) PetscValidIntPointer(n, 3); 6654 if (m) *m = mat->rmap->n; 6655 if (n) *n = mat->cmap->n; 6656 PetscFunctionReturn(PETSC_SUCCESS); 6657 } 6658 6659 /*@C 6660 MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by 6661 this processor. (The columns of the "diagonal block" for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts. 6662 6663 Not Collective, unless matrix has not been allocated, then collective 6664 6665 Input Parameter: 6666 . mat - the matrix 6667 6668 Output Parameters: 6669 + m - the global index of the first local column, use `NULL` to not obtain this value 6670 - n - one more than the global index of the last local column, use `NULL` to not obtain this value 6671 6672 Level: developer 6673 6674 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout` 6675 @*/ 6676 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n) 6677 { 6678 PetscFunctionBegin; 6679 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6680 PetscValidType(mat, 1); 6681 if (m) PetscValidIntPointer(m, 2); 6682 if (n) PetscValidIntPointer(n, 3); 6683 MatCheckPreallocated(mat, 1); 6684 if (m) *m = mat->cmap->rstart; 6685 if (n) *n = mat->cmap->rend; 6686 PetscFunctionReturn(PETSC_SUCCESS); 6687 } 6688 6689 /*@C 6690 MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6691 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 6692 vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts 6693 6694 Not Collective 6695 6696 Input Parameter: 6697 . mat - the matrix 6698 6699 Output Parameters: 6700 + m - the global index of the first local row, use `NULL` to not obtain this value 6701 - n - one more than the global index of the last local row, use `NULL` to not obtain this value 6702 6703 Level: beginner 6704 6705 Note: 6706 This function requires that the matrix be preallocated. If you have not preallocated, consider using 6707 `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N) 6708 and then `MPI_Scan()` to calculate prefix sums of the local sizes. 6709 6710 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, 6711 `PetscLayout` 6712 @*/ 6713 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n) 6714 { 6715 PetscFunctionBegin; 6716 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6717 PetscValidType(mat, 1); 6718 if (m) PetscValidIntPointer(m, 2); 6719 if (n) PetscValidIntPointer(n, 3); 6720 MatCheckPreallocated(mat, 1); 6721 if (m) *m = mat->rmap->rstart; 6722 if (n) *n = mat->rmap->rend; 6723 PetscFunctionReturn(PETSC_SUCCESS); 6724 } 6725 6726 /*@C 6727 MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6728 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 6729 vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts 6730 6731 Not Collective, unless matrix has not been allocated 6732 6733 Input Parameter: 6734 . mat - the matrix 6735 6736 Output Parameter: 6737 . ranges - start of each processors portion plus one more than the total length at the end 6738 6739 Level: beginner 6740 6741 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout` 6742 @*/ 6743 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges) 6744 { 6745 PetscFunctionBegin; 6746 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6747 PetscValidType(mat, 1); 6748 MatCheckPreallocated(mat, 1); 6749 PetscCall(PetscLayoutGetRanges(mat->rmap, ranges)); 6750 PetscFunctionReturn(PETSC_SUCCESS); 6751 } 6752 6753 /*@C 6754 MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by 6755 each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts. 6756 6757 Not Collective, unless matrix has not been allocated 6758 6759 Input Parameter: 6760 . mat - the matrix 6761 6762 Output Parameter: 6763 . ranges - start of each processors portion plus one more then the total length at the end 6764 6765 Level: beginner 6766 6767 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()` 6768 @*/ 6769 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges) 6770 { 6771 PetscFunctionBegin; 6772 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6773 PetscValidType(mat, 1); 6774 MatCheckPreallocated(mat, 1); 6775 PetscCall(PetscLayoutGetRanges(mat->cmap, ranges)); 6776 PetscFunctionReturn(PETSC_SUCCESS); 6777 } 6778 6779 /*@C 6780 MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this 6781 corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership 6782 is more complicated. See :any:`<sec_matlayout>` for details on matrix layouts. 6783 6784 Not Collective 6785 6786 Input Parameter: 6787 . A - matrix 6788 6789 Output Parameters: 6790 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value 6791 - cols - columns in which this process owns elements, use `NULL` to not obtain this value 6792 6793 Level: intermediate 6794 6795 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK`` 6796 @*/ 6797 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols) 6798 { 6799 PetscErrorCode (*f)(Mat, IS *, IS *); 6800 6801 PetscFunctionBegin; 6802 MatCheckPreallocated(A, 1); 6803 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f)); 6804 if (f) { 6805 PetscCall((*f)(A, rows, cols)); 6806 } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */ 6807 if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows)); 6808 if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols)); 6809 } 6810 PetscFunctionReturn(PETSC_SUCCESS); 6811 } 6812 6813 /*@C 6814 MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()` 6815 Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()` 6816 to complete the factorization. 6817 6818 Collective 6819 6820 Input Parameters: 6821 + fact - the factorized matrix obtained with `MatGetFactor()` 6822 . mat - the matrix 6823 . row - row permutation 6824 . col - column permutation 6825 - info - structure containing 6826 .vb 6827 levels - number of levels of fill. 6828 expected fill - as ratio of original fill. 6829 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 6830 missing diagonal entries) 6831 .ve 6832 6833 Level: developer 6834 6835 Notes: 6836 See [Matrix Factorization](sec_matfactor) for additional information. 6837 6838 Most users should employ the `KSP` interface for linear solvers 6839 instead of working directly with matrix algebra routines such as this. 6840 See, e.g., `KSPCreate()`. 6841 6842 Uses the definition of level of fill as in Y. Saad, 2003 6843 6844 Developer Note: 6845 The Fortran interface is not autogenerated as the 6846 interface definition cannot be generated correctly [due to `MatFactorInfo`] 6847 6848 References: 6849 . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003 6850 6851 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 6852 `MatGetOrdering()`, `MatFactorInfo` 6853 @*/ 6854 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 6855 { 6856 PetscFunctionBegin; 6857 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 6858 PetscValidType(mat, 2); 6859 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 6860 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 6861 PetscValidPointer(info, 5); 6862 PetscValidPointer(fact, 1); 6863 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels); 6864 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 6865 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6866 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6867 MatCheckPreallocated(mat, 2); 6868 6869 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0)); 6870 PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info); 6871 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0)); 6872 PetscFunctionReturn(PETSC_SUCCESS); 6873 } 6874 6875 /*@C 6876 MatICCFactorSymbolic - Performs symbolic incomplete 6877 Cholesky factorization for a symmetric matrix. Use 6878 `MatCholeskyFactorNumeric()` to complete the factorization. 6879 6880 Collective 6881 6882 Input Parameters: 6883 + fact - the factorized matrix obtained with `MatGetFactor()` 6884 . mat - the matrix to be factored 6885 . perm - row and column permutation 6886 - info - structure containing 6887 .vb 6888 levels - number of levels of fill. 6889 expected fill - as ratio of original fill. 6890 .ve 6891 6892 Level: developer 6893 6894 Notes: 6895 Most users should employ the `KSP` interface for linear solvers 6896 instead of working directly with matrix algebra routines such as this. 6897 See, e.g., `KSPCreate()`. 6898 6899 This uses the definition of level of fill as in Y. Saad, 2003 6900 6901 Developer Note: 6902 The Fortran interface is not autogenerated as the 6903 interface definition cannot be generated correctly [due to `MatFactorInfo`] 6904 6905 References: 6906 . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003 6907 6908 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 6909 @*/ 6910 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 6911 { 6912 PetscFunctionBegin; 6913 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 6914 PetscValidType(mat, 2); 6915 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 6916 PetscValidPointer(info, 4); 6917 PetscValidPointer(fact, 1); 6918 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6919 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels); 6920 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 6921 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6922 MatCheckPreallocated(mat, 2); 6923 6924 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 6925 PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info); 6926 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 6927 PetscFunctionReturn(PETSC_SUCCESS); 6928 } 6929 6930 /*@C 6931 MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat 6932 points to an array of valid matrices, they may be reused to store the new 6933 submatrices. 6934 6935 Collective 6936 6937 Input Parameters: 6938 + mat - the matrix 6939 . n - the number of submatrixes to be extracted (on this processor, may be zero) 6940 . irow - index set of rows to extract 6941 . icol - index set of columns to extract 6942 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 6943 6944 Output Parameter: 6945 . submat - the array of submatrices 6946 6947 Level: advanced 6948 6949 Notes: 6950 `MatCreateSubMatrices()` can extract ONLY sequential submatrices 6951 (from both sequential and parallel matrices). Use `MatCreateSubMatrix()` 6952 to extract a parallel submatrix. 6953 6954 Some matrix types place restrictions on the row and column 6955 indices, such as that they be sorted or that they be equal to each other. 6956 6957 The index sets may not have duplicate entries. 6958 6959 When extracting submatrices from a parallel matrix, each processor can 6960 form a different submatrix by setting the rows and columns of its 6961 individual index sets according to the local submatrix desired. 6962 6963 When finished using the submatrices, the user should destroy 6964 them with `MatDestroySubMatrices()`. 6965 6966 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 6967 original matrix has not changed from that last call to `MatCreateSubMatrices()`. 6968 6969 This routine creates the matrices in submat; you should NOT create them before 6970 calling it. It also allocates the array of matrix pointers submat. 6971 6972 For `MATBAIJ` matrices the index sets must respect the block structure, that is if they 6973 request one row/column in a block, they must request all rows/columns that are in 6974 that block. For example, if the block size is 2 you cannot request just row 0 and 6975 column 0. 6976 6977 Fortran Note: 6978 The Fortran interface is slightly different from that given below; it 6979 requires one to pass in as `submat` a `Mat` (integer) array of size at least n+1. 6980 6981 .seealso: [](chapter_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 6982 @*/ 6983 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 6984 { 6985 PetscInt i; 6986 PetscBool eq; 6987 6988 PetscFunctionBegin; 6989 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6990 PetscValidType(mat, 1); 6991 if (n) { 6992 PetscValidPointer(irow, 3); 6993 for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3); 6994 PetscValidPointer(icol, 4); 6995 for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4); 6996 } 6997 PetscValidPointer(submat, 6); 6998 if (n && scall == MAT_REUSE_MATRIX) { 6999 PetscValidPointer(*submat, 6); 7000 for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6); 7001 } 7002 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7003 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7004 MatCheckPreallocated(mat, 1); 7005 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7006 PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat); 7007 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7008 for (i = 0; i < n; i++) { 7009 (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */ 7010 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7011 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7012 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 7013 if (mat->boundtocpu && mat->bindingpropagates) { 7014 PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE)); 7015 PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE)); 7016 } 7017 #endif 7018 } 7019 PetscFunctionReturn(PETSC_SUCCESS); 7020 } 7021 7022 /*@C 7023 MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms). 7024 7025 Collective 7026 7027 Input Parameters: 7028 + mat - the matrix 7029 . n - the number of submatrixes to be extracted 7030 . irow - index set of rows to extract 7031 . icol - index set of columns to extract 7032 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7033 7034 Output Parameter: 7035 . submat - the array of submatrices 7036 7037 Level: advanced 7038 7039 Note: 7040 This is used by `PCGASM` 7041 7042 .seealso: [](chapter_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7043 @*/ 7044 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7045 { 7046 PetscInt i; 7047 PetscBool eq; 7048 7049 PetscFunctionBegin; 7050 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7051 PetscValidType(mat, 1); 7052 if (n) { 7053 PetscValidPointer(irow, 3); 7054 PetscValidHeaderSpecific(*irow, IS_CLASSID, 3); 7055 PetscValidPointer(icol, 4); 7056 PetscValidHeaderSpecific(*icol, IS_CLASSID, 4); 7057 } 7058 PetscValidPointer(submat, 6); 7059 if (n && scall == MAT_REUSE_MATRIX) { 7060 PetscValidPointer(*submat, 6); 7061 PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6); 7062 } 7063 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7064 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7065 MatCheckPreallocated(mat, 1); 7066 7067 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7068 PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat); 7069 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7070 for (i = 0; i < n; i++) { 7071 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7072 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7073 } 7074 PetscFunctionReturn(PETSC_SUCCESS); 7075 } 7076 7077 /*@C 7078 MatDestroyMatrices - Destroys an array of matrices. 7079 7080 Collective 7081 7082 Input Parameters: 7083 + n - the number of local matrices 7084 - mat - the matrices (this is a pointer to the array of matrices) 7085 7086 Level: advanced 7087 7088 Note: 7089 Frees not only the matrices, but also the array that contains the matrices 7090 7091 Fortran Note: 7092 This does not free the array. 7093 7094 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()` 7095 @*/ 7096 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[]) 7097 { 7098 PetscInt i; 7099 7100 PetscFunctionBegin; 7101 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7102 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7103 PetscValidPointer(mat, 2); 7104 7105 for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i])); 7106 7107 /* memory is allocated even if n = 0 */ 7108 PetscCall(PetscFree(*mat)); 7109 PetscFunctionReturn(PETSC_SUCCESS); 7110 } 7111 7112 /*@C 7113 MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`. 7114 7115 Collective 7116 7117 Input Parameters: 7118 + n - the number of local matrices 7119 - mat - the matrices (this is a pointer to the array of matrices, just to match the calling 7120 sequence of `MatCreateSubMatrices()`) 7121 7122 Level: advanced 7123 7124 Note: 7125 Frees not only the matrices, but also the array that contains the matrices 7126 7127 Fortran Note: 7128 This does not free the array. 7129 7130 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7131 @*/ 7132 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[]) 7133 { 7134 Mat mat0; 7135 7136 PetscFunctionBegin; 7137 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7138 /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */ 7139 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7140 PetscValidPointer(mat, 2); 7141 7142 mat0 = (*mat)[0]; 7143 if (mat0 && mat0->ops->destroysubmatrices) { 7144 PetscCall((*mat0->ops->destroysubmatrices)(n, mat)); 7145 } else { 7146 PetscCall(MatDestroyMatrices(n, mat)); 7147 } 7148 PetscFunctionReturn(PETSC_SUCCESS); 7149 } 7150 7151 /*@C 7152 MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process 7153 7154 Collective 7155 7156 Input Parameter: 7157 . mat - the matrix 7158 7159 Output Parameter: 7160 . matstruct - the sequential matrix with the nonzero structure of mat 7161 7162 Level: developer 7163 7164 .seealso: [](chapter_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7165 @*/ 7166 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct) 7167 { 7168 PetscFunctionBegin; 7169 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7170 PetscValidPointer(matstruct, 2); 7171 7172 PetscValidType(mat, 1); 7173 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7174 MatCheckPreallocated(mat, 1); 7175 7176 PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7177 PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct); 7178 PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7179 PetscFunctionReturn(PETSC_SUCCESS); 7180 } 7181 7182 /*@C 7183 MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`. 7184 7185 Collective 7186 7187 Input Parameter: 7188 . mat - the matrix (this is a pointer to the array of matrices, just to match the calling 7189 sequence of `MatGetSequentialNonzeroStructure()`) 7190 7191 Level: advanced 7192 7193 Note: 7194 Frees not only the matrices, but also the array that contains the matrices 7195 7196 .seealso: [](chapter_matrices), `Mat`, `MatGetSeqNonzeroStructure()` 7197 @*/ 7198 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat) 7199 { 7200 PetscFunctionBegin; 7201 PetscValidPointer(mat, 1); 7202 PetscCall(MatDestroy(mat)); 7203 PetscFunctionReturn(PETSC_SUCCESS); 7204 } 7205 7206 /*@ 7207 MatIncreaseOverlap - Given a set of submatrices indicated by index sets, 7208 replaces the index sets by larger ones that represent submatrices with 7209 additional overlap. 7210 7211 Collective 7212 7213 Input Parameters: 7214 + mat - the matrix 7215 . n - the number of index sets 7216 . is - the array of index sets (these index sets will changed during the call) 7217 - ov - the additional overlap requested 7218 7219 Options Database Key: 7220 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7221 7222 Level: developer 7223 7224 Note: 7225 The computed overlap preserves the matrix block sizes when the blocks are square. 7226 That is: if a matrix nonzero for a given block would increase the overlap all columns associated with 7227 that block are included in the overlap regardless of whether each specific column would increase the overlap. 7228 7229 .seealso: [](chapter_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()` 7230 @*/ 7231 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov) 7232 { 7233 PetscInt i, bs, cbs; 7234 7235 PetscFunctionBegin; 7236 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7237 PetscValidType(mat, 1); 7238 PetscValidLogicalCollectiveInt(mat, n, 2); 7239 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7240 if (n) { 7241 PetscValidPointer(is, 3); 7242 for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3); 7243 } 7244 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7245 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7246 MatCheckPreallocated(mat, 1); 7247 7248 if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS); 7249 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7250 PetscUseTypeMethod(mat, increaseoverlap, n, is, ov); 7251 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7252 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 7253 if (bs == cbs) { 7254 for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs)); 7255 } 7256 PetscFunctionReturn(PETSC_SUCCESS); 7257 } 7258 7259 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt); 7260 7261 /*@ 7262 MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across 7263 a sub communicator, replaces the index sets by larger ones that represent submatrices with 7264 additional overlap. 7265 7266 Collective 7267 7268 Input Parameters: 7269 + mat - the matrix 7270 . n - the number of index sets 7271 . is - the array of index sets (these index sets will changed during the call) 7272 - ov - the additional overlap requested 7273 7274 ` Options Database Key: 7275 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7276 7277 Level: developer 7278 7279 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()` 7280 @*/ 7281 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov) 7282 { 7283 PetscInt i; 7284 7285 PetscFunctionBegin; 7286 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7287 PetscValidType(mat, 1); 7288 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7289 if (n) { 7290 PetscValidPointer(is, 3); 7291 PetscValidHeaderSpecific(*is, IS_CLASSID, 3); 7292 } 7293 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7294 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7295 MatCheckPreallocated(mat, 1); 7296 if (!ov) PetscFunctionReturn(PETSC_SUCCESS); 7297 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7298 for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov)); 7299 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7300 PetscFunctionReturn(PETSC_SUCCESS); 7301 } 7302 7303 /*@ 7304 MatGetBlockSize - Returns the matrix block size. 7305 7306 Not Collective 7307 7308 Input Parameter: 7309 . mat - the matrix 7310 7311 Output Parameter: 7312 . bs - block size 7313 7314 Level: intermediate 7315 7316 Notes: 7317 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7318 7319 If the block size has not been set yet this routine returns 1. 7320 7321 .seealso: [](chapter_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()` 7322 @*/ 7323 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs) 7324 { 7325 PetscFunctionBegin; 7326 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7327 PetscValidIntPointer(bs, 2); 7328 *bs = PetscAbs(mat->rmap->bs); 7329 PetscFunctionReturn(PETSC_SUCCESS); 7330 } 7331 7332 /*@ 7333 MatGetBlockSizes - Returns the matrix block row and column sizes. 7334 7335 Not Collective 7336 7337 Input Parameter: 7338 . mat - the matrix 7339 7340 Output Parameters: 7341 + rbs - row block size 7342 - cbs - column block size 7343 7344 Level: intermediate 7345 7346 Notes: 7347 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7348 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7349 7350 If a block size has not been set yet this routine returns 1. 7351 7352 .seealso: [](chapter_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()` 7353 @*/ 7354 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs) 7355 { 7356 PetscFunctionBegin; 7357 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7358 if (rbs) PetscValidIntPointer(rbs, 2); 7359 if (cbs) PetscValidIntPointer(cbs, 3); 7360 if (rbs) *rbs = PetscAbs(mat->rmap->bs); 7361 if (cbs) *cbs = PetscAbs(mat->cmap->bs); 7362 PetscFunctionReturn(PETSC_SUCCESS); 7363 } 7364 7365 /*@ 7366 MatSetBlockSize - Sets the matrix block size. 7367 7368 Logically Collective 7369 7370 Input Parameters: 7371 + mat - the matrix 7372 - bs - block size 7373 7374 Level: intermediate 7375 7376 Notes: 7377 Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix. 7378 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7379 7380 For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size 7381 is compatible with the matrix local sizes. 7382 7383 .seealso: [](chapter_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()` 7384 @*/ 7385 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs) 7386 { 7387 PetscFunctionBegin; 7388 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7389 PetscValidLogicalCollectiveInt(mat, bs, 2); 7390 PetscCall(MatSetBlockSizes(mat, bs, bs)); 7391 PetscFunctionReturn(PETSC_SUCCESS); 7392 } 7393 7394 typedef struct { 7395 PetscInt n; 7396 IS *is; 7397 Mat *mat; 7398 PetscObjectState nonzerostate; 7399 Mat C; 7400 } EnvelopeData; 7401 7402 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata) 7403 { 7404 for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i])); 7405 PetscCall(PetscFree(edata->is)); 7406 PetscCall(PetscFree(edata)); 7407 return PETSC_SUCCESS; 7408 } 7409 7410 /* 7411 MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores 7412 the sizes of these blocks in the matrix. An individual block may lie over several processes. 7413 7414 Collective 7415 7416 Input Parameter: 7417 . mat - the matrix 7418 7419 Notes: 7420 There can be zeros within the blocks 7421 7422 The blocks can overlap between processes, including laying on more than two processes 7423 7424 .seealso: [](chapter_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()` 7425 */ 7426 static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat) 7427 { 7428 PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend; 7429 PetscInt *diag, *odiag, sc; 7430 VecScatter scatter; 7431 PetscScalar *seqv; 7432 const PetscScalar *parv; 7433 const PetscInt *ia, *ja; 7434 PetscBool set, flag, done; 7435 Mat AA = mat, A; 7436 MPI_Comm comm; 7437 PetscMPIInt rank, size, tag; 7438 MPI_Status status; 7439 PetscContainer container; 7440 EnvelopeData *edata; 7441 Vec seq, par; 7442 IS isglobal; 7443 7444 PetscFunctionBegin; 7445 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7446 PetscCall(MatIsSymmetricKnown(mat, &set, &flag)); 7447 if (!set || !flag) { 7448 /* TOO: only needs nonzero structure of transpose */ 7449 PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA)); 7450 PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN)); 7451 } 7452 PetscCall(MatAIJGetLocalMat(AA, &A)); 7453 PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7454 PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix"); 7455 7456 PetscCall(MatGetLocalSize(mat, &n, NULL)); 7457 PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag)); 7458 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 7459 PetscCallMPI(MPI_Comm_size(comm, &size)); 7460 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7461 7462 PetscCall(PetscMalloc2(n, &sizes, n, &starts)); 7463 7464 if (rank > 0) { 7465 PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7466 PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7467 } 7468 PetscCall(MatGetOwnershipRange(mat, &rstart, NULL)); 7469 for (i = 0; i < n; i++) { 7470 env = PetscMax(env, ja[ia[i + 1] - 1]); 7471 II = rstart + i; 7472 if (env == II) { 7473 starts[lblocks] = tbs; 7474 sizes[lblocks++] = 1 + II - tbs; 7475 tbs = 1 + II; 7476 } 7477 } 7478 if (rank < size - 1) { 7479 PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm)); 7480 PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm)); 7481 } 7482 7483 PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7484 if (!set || !flag) PetscCall(MatDestroy(&AA)); 7485 PetscCall(MatDestroy(&A)); 7486 7487 PetscCall(PetscNew(&edata)); 7488 PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate)); 7489 edata->n = lblocks; 7490 /* create IS needed for extracting blocks from the original matrix */ 7491 PetscCall(PetscMalloc1(lblocks, &edata->is)); 7492 for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i])); 7493 7494 /* Create the resulting inverse matrix structure with preallocation information */ 7495 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C)); 7496 PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 7497 PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat)); 7498 PetscCall(MatSetType(edata->C, MATAIJ)); 7499 7500 /* Communicate the start and end of each row, from each block to the correct rank */ 7501 /* TODO: Use PetscSF instead of VecScatter */ 7502 for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i]; 7503 PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq)); 7504 PetscCall(VecGetArrayWrite(seq, &seqv)); 7505 for (PetscInt i = 0; i < lblocks; i++) { 7506 for (PetscInt j = 0; j < sizes[i]; j++) { 7507 seqv[cnt] = starts[i]; 7508 seqv[cnt + 1] = starts[i] + sizes[i]; 7509 cnt += 2; 7510 } 7511 } 7512 PetscCall(VecRestoreArrayWrite(seq, &seqv)); 7513 PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 7514 sc -= cnt; 7515 PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par)); 7516 PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal)); 7517 PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter)); 7518 PetscCall(ISDestroy(&isglobal)); 7519 PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7520 PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7521 PetscCall(VecScatterDestroy(&scatter)); 7522 PetscCall(VecDestroy(&seq)); 7523 PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend)); 7524 PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag)); 7525 PetscCall(VecGetArrayRead(par, &parv)); 7526 cnt = 0; 7527 PetscCall(MatGetSize(mat, NULL, &n)); 7528 for (PetscInt i = 0; i < mat->rmap->n; i++) { 7529 PetscInt start, end, d = 0, od = 0; 7530 7531 start = (PetscInt)PetscRealPart(parv[cnt]); 7532 end = (PetscInt)PetscRealPart(parv[cnt + 1]); 7533 cnt += 2; 7534 7535 if (start < cstart) { 7536 od += cstart - start + n - cend; 7537 d += cend - cstart; 7538 } else if (start < cend) { 7539 od += n - cend; 7540 d += cend - start; 7541 } else od += n - start; 7542 if (end <= cstart) { 7543 od -= cstart - end + n - cend; 7544 d -= cend - cstart; 7545 } else if (end < cend) { 7546 od -= n - cend; 7547 d -= cend - end; 7548 } else od -= n - end; 7549 7550 odiag[i] = od; 7551 diag[i] = d; 7552 } 7553 PetscCall(VecRestoreArrayRead(par, &parv)); 7554 PetscCall(VecDestroy(&par)); 7555 PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL)); 7556 PetscCall(PetscFree2(diag, odiag)); 7557 PetscCall(PetscFree2(sizes, starts)); 7558 7559 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container)); 7560 PetscCall(PetscContainerSetPointer(container, edata)); 7561 PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy)); 7562 PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container)); 7563 PetscCall(PetscObjectDereference((PetscObject)container)); 7564 PetscFunctionReturn(PETSC_SUCCESS); 7565 } 7566 7567 /*@ 7568 MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A 7569 7570 Collective 7571 7572 Input Parameters: 7573 + A - the matrix 7574 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine 7575 7576 Output Parameter: 7577 . C - matrix with inverted block diagonal of `A` 7578 7579 Level: advanced 7580 7581 Note: 7582 For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal. 7583 7584 .seealso: [](chapter_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()` 7585 @*/ 7586 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C) 7587 { 7588 PetscContainer container; 7589 EnvelopeData *edata; 7590 PetscObjectState nonzerostate; 7591 7592 PetscFunctionBegin; 7593 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7594 if (!container) { 7595 PetscCall(MatComputeVariableBlockEnvelope(A)); 7596 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7597 } 7598 PetscCall(PetscContainerGetPointer(container, (void **)&edata)); 7599 PetscCall(MatGetNonzeroState(A, &nonzerostate)); 7600 PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure"); 7601 PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output"); 7602 7603 PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat)); 7604 *C = edata->C; 7605 7606 for (PetscInt i = 0; i < edata->n; i++) { 7607 Mat D; 7608 PetscScalar *dvalues; 7609 7610 PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D)); 7611 PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE)); 7612 PetscCall(MatSeqDenseInvert(D)); 7613 PetscCall(MatDenseGetArray(D, &dvalues)); 7614 PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES)); 7615 PetscCall(MatDestroy(&D)); 7616 } 7617 PetscCall(MatDestroySubMatrices(edata->n, &edata->mat)); 7618 PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY)); 7619 PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY)); 7620 PetscFunctionReturn(PETSC_SUCCESS); 7621 } 7622 7623 /*@ 7624 MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size 7625 7626 Logically Collective 7627 7628 Input Parameters: 7629 + mat - the matrix 7630 . nblocks - the number of blocks on this process, each block can only exist on a single process 7631 - bsizes - the block sizes 7632 7633 Level: intermediate 7634 7635 Notes: 7636 Currently used by `PCVPBJACOBI` for `MATAIJ` matrices 7637 7638 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. 7639 7640 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, 7641 `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI` 7642 @*/ 7643 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes) 7644 { 7645 PetscInt i, ncnt = 0, nlocal; 7646 7647 PetscFunctionBegin; 7648 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7649 PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero"); 7650 PetscCall(MatGetLocalSize(mat, &nlocal, NULL)); 7651 for (i = 0; i < nblocks; i++) ncnt += bsizes[i]; 7652 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); 7653 PetscCall(PetscFree(mat->bsizes)); 7654 mat->nblocks = nblocks; 7655 PetscCall(PetscMalloc1(nblocks, &mat->bsizes)); 7656 PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks)); 7657 PetscFunctionReturn(PETSC_SUCCESS); 7658 } 7659 7660 /*@C 7661 MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size 7662 7663 Logically Collective; No Fortran Support 7664 7665 Input Parameter: 7666 . mat - the matrix 7667 7668 Output Parameters: 7669 + nblocks - the number of blocks on this process 7670 - bsizes - the block sizes 7671 7672 Level: intermediate 7673 7674 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()` 7675 @*/ 7676 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes) 7677 { 7678 PetscFunctionBegin; 7679 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7680 *nblocks = mat->nblocks; 7681 *bsizes = mat->bsizes; 7682 PetscFunctionReturn(PETSC_SUCCESS); 7683 } 7684 7685 /*@ 7686 MatSetBlockSizes - Sets the matrix block row and column sizes. 7687 7688 Logically Collective 7689 7690 Input Parameters: 7691 + mat - the matrix 7692 . rbs - row block size 7693 - cbs - column block size 7694 7695 Level: intermediate 7696 7697 Notes: 7698 Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix. 7699 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7700 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7701 7702 For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes 7703 are compatible with the matrix local sizes. 7704 7705 The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`. 7706 7707 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()` 7708 @*/ 7709 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs) 7710 { 7711 PetscFunctionBegin; 7712 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7713 PetscValidLogicalCollectiveInt(mat, rbs, 2); 7714 PetscValidLogicalCollectiveInt(mat, cbs, 3); 7715 PetscTryTypeMethod(mat, setblocksizes, rbs, cbs); 7716 if (mat->rmap->refcnt) { 7717 ISLocalToGlobalMapping l2g = NULL; 7718 PetscLayout nmap = NULL; 7719 7720 PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap)); 7721 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g)); 7722 PetscCall(PetscLayoutDestroy(&mat->rmap)); 7723 mat->rmap = nmap; 7724 mat->rmap->mapping = l2g; 7725 } 7726 if (mat->cmap->refcnt) { 7727 ISLocalToGlobalMapping l2g = NULL; 7728 PetscLayout nmap = NULL; 7729 7730 PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap)); 7731 if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g)); 7732 PetscCall(PetscLayoutDestroy(&mat->cmap)); 7733 mat->cmap = nmap; 7734 mat->cmap->mapping = l2g; 7735 } 7736 PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs)); 7737 PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs)); 7738 PetscFunctionReturn(PETSC_SUCCESS); 7739 } 7740 7741 /*@ 7742 MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices 7743 7744 Logically Collective 7745 7746 Input Parameters: 7747 + mat - the matrix 7748 . fromRow - matrix from which to copy row block size 7749 - fromCol - matrix from which to copy column block size (can be same as fromRow) 7750 7751 Level: developer 7752 7753 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()` 7754 @*/ 7755 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol) 7756 { 7757 PetscFunctionBegin; 7758 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7759 PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2); 7760 PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3); 7761 if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs)); 7762 if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs)); 7763 PetscFunctionReturn(PETSC_SUCCESS); 7764 } 7765 7766 /*@ 7767 MatResidual - Default routine to calculate the residual r = b - Ax 7768 7769 Collective 7770 7771 Input Parameters: 7772 + mat - the matrix 7773 . b - the right-hand-side 7774 - x - the approximate solution 7775 7776 Output Parameter: 7777 . r - location to store the residual 7778 7779 Level: developer 7780 7781 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()` 7782 @*/ 7783 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r) 7784 { 7785 PetscFunctionBegin; 7786 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7787 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 7788 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 7789 PetscValidHeaderSpecific(r, VEC_CLASSID, 4); 7790 PetscValidType(mat, 1); 7791 MatCheckPreallocated(mat, 1); 7792 PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0)); 7793 if (!mat->ops->residual) { 7794 PetscCall(MatMult(mat, x, r)); 7795 PetscCall(VecAYPX(r, -1.0, b)); 7796 } else { 7797 PetscUseTypeMethod(mat, residual, b, x, r); 7798 } 7799 PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0)); 7800 PetscFunctionReturn(PETSC_SUCCESS); 7801 } 7802 7803 /*MC 7804 MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix 7805 7806 Synopsis: 7807 MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 7808 7809 Not Collective 7810 7811 Input Parameters: 7812 + A - the matrix 7813 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7814 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7815 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7816 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7817 always used. 7818 7819 Output Parameters: 7820 + n - number of local rows in the (possibly compressed) matrix 7821 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 7822 . ja - the column indices 7823 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7824 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7825 7826 Level: developer 7827 7828 Note: 7829 Use `MatRestoreRowIJF90()` when you no longer need access to the data 7830 7831 .seealso: [](chapter_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()` 7832 M*/ 7833 7834 /*MC 7835 MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()` 7836 7837 Synopsis: 7838 MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 7839 7840 Not Collective 7841 7842 Input Parameters: 7843 + A - the matrix 7844 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7845 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7846 inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7847 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7848 always used. 7849 . n - number of local rows in the (possibly compressed) matrix 7850 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 7851 . ja - the column indices 7852 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7853 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7854 7855 Level: developer 7856 7857 .seealso: [](chapter_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()` 7858 M*/ 7859 7860 /*@C 7861 MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix 7862 7863 Collective 7864 7865 Input Parameters: 7866 + mat - the matrix 7867 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7868 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7869 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7870 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7871 always used. 7872 7873 Output Parameters: 7874 + n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed 7875 . 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 7876 . ja - the column indices, use `NULL` if not needed 7877 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7878 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7879 7880 Level: developer 7881 7882 Notes: 7883 You CANNOT change any of the ia[] or ja[] values. 7884 7885 Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values. 7886 7887 Fortran Notes: 7888 Use 7889 .vb 7890 PetscInt, pointer :: ia(:),ja(:) 7891 call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr) 7892 ! Access the ith and jth entries via ia(i) and ja(j) 7893 .ve 7894 `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()` 7895 7896 .seealso: [](chapter_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()` 7897 @*/ 7898 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7899 { 7900 PetscFunctionBegin; 7901 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7902 PetscValidType(mat, 1); 7903 if (n) PetscValidIntPointer(n, 5); 7904 if (ia) PetscValidPointer(ia, 6); 7905 if (ja) PetscValidPointer(ja, 7); 7906 if (done) PetscValidBoolPointer(done, 8); 7907 MatCheckPreallocated(mat, 1); 7908 if (!mat->ops->getrowij && done) *done = PETSC_FALSE; 7909 else { 7910 if (done) *done = PETSC_TRUE; 7911 PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0)); 7912 PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done); 7913 PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0)); 7914 } 7915 PetscFunctionReturn(PETSC_SUCCESS); 7916 } 7917 7918 /*@C 7919 MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices. 7920 7921 Collective 7922 7923 Input Parameters: 7924 + mat - the matrix 7925 . shift - 1 or zero indicating we want the indices starting at 0 or 1 7926 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be 7927 symmetrized 7928 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7929 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7930 always used. 7931 . n - number of columns in the (possibly compressed) matrix 7932 . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix 7933 - ja - the row indices 7934 7935 Output Parameter: 7936 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned 7937 7938 Level: developer 7939 7940 .seealso: [](chapter_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 7941 @*/ 7942 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7943 { 7944 PetscFunctionBegin; 7945 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7946 PetscValidType(mat, 1); 7947 PetscValidIntPointer(n, 5); 7948 if (ia) PetscValidPointer(ia, 6); 7949 if (ja) PetscValidPointer(ja, 7); 7950 PetscValidBoolPointer(done, 8); 7951 MatCheckPreallocated(mat, 1); 7952 if (!mat->ops->getcolumnij) *done = PETSC_FALSE; 7953 else { 7954 *done = PETSC_TRUE; 7955 PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 7956 } 7957 PetscFunctionReturn(PETSC_SUCCESS); 7958 } 7959 7960 /*@C 7961 MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`. 7962 7963 Collective 7964 7965 Input Parameters: 7966 + mat - the matrix 7967 . shift - 1 or zero indicating we want the indices starting at 0 or 1 7968 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7969 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7970 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7971 always used. 7972 . n - size of (possibly compressed) matrix 7973 . ia - the row pointers 7974 - ja - the column indices 7975 7976 Output Parameter: 7977 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 7978 7979 Level: developer 7980 7981 Note: 7982 This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental 7983 us of the array after it has been restored. If you pass `NULL`, it will 7984 not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid. 7985 7986 Fortran Note: 7987 `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()` 7988 7989 .seealso: [](chapter_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()` 7990 @*/ 7991 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7992 { 7993 PetscFunctionBegin; 7994 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7995 PetscValidType(mat, 1); 7996 if (ia) PetscValidPointer(ia, 6); 7997 if (ja) PetscValidPointer(ja, 7); 7998 if (done) PetscValidBoolPointer(done, 8); 7999 MatCheckPreallocated(mat, 1); 8000 8001 if (!mat->ops->restorerowij && done) *done = PETSC_FALSE; 8002 else { 8003 if (done) *done = PETSC_TRUE; 8004 PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8005 if (n) *n = 0; 8006 if (ia) *ia = NULL; 8007 if (ja) *ja = NULL; 8008 } 8009 PetscFunctionReturn(PETSC_SUCCESS); 8010 } 8011 8012 /*@C 8013 MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`. 8014 8015 Collective 8016 8017 Input Parameters: 8018 + mat - the matrix 8019 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8020 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8021 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8022 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8023 always used. 8024 8025 Output Parameters: 8026 + n - size of (possibly compressed) matrix 8027 . ia - the column pointers 8028 . ja - the row indices 8029 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8030 8031 Level: developer 8032 8033 .seealso: [](chapter_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()` 8034 @*/ 8035 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8036 { 8037 PetscFunctionBegin; 8038 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8039 PetscValidType(mat, 1); 8040 if (ia) PetscValidPointer(ia, 6); 8041 if (ja) PetscValidPointer(ja, 7); 8042 PetscValidBoolPointer(done, 8); 8043 MatCheckPreallocated(mat, 1); 8044 8045 if (!mat->ops->restorecolumnij) *done = PETSC_FALSE; 8046 else { 8047 *done = PETSC_TRUE; 8048 PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8049 if (n) *n = 0; 8050 if (ia) *ia = NULL; 8051 if (ja) *ja = NULL; 8052 } 8053 PetscFunctionReturn(PETSC_SUCCESS); 8054 } 8055 8056 /*@C 8057 MatColoringPatch -Used inside matrix coloring routines that use `MatGetRowIJ()` and/or `MatGetColumnIJ()`. 8058 8059 Collective 8060 8061 Input Parameters: 8062 + mat - the matrix 8063 . ncolors - maximum color value 8064 . n - number of entries in colorarray 8065 - colorarray - array indicating color for each column 8066 8067 Output Parameter: 8068 . iscoloring - coloring generated using colorarray information 8069 8070 Level: developer 8071 8072 .seealso: [](chapter_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()` 8073 @*/ 8074 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring) 8075 { 8076 PetscFunctionBegin; 8077 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8078 PetscValidType(mat, 1); 8079 PetscValidIntPointer(colorarray, 4); 8080 PetscValidPointer(iscoloring, 5); 8081 MatCheckPreallocated(mat, 1); 8082 8083 if (!mat->ops->coloringpatch) { 8084 PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring)); 8085 } else { 8086 PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring); 8087 } 8088 PetscFunctionReturn(PETSC_SUCCESS); 8089 } 8090 8091 /*@ 8092 MatSetUnfactored - Resets a factored matrix to be treated as unfactored. 8093 8094 Logically Collective 8095 8096 Input Parameter: 8097 . mat - the factored matrix to be reset 8098 8099 Level: developer 8100 8101 Notes: 8102 This routine should be used only with factored matrices formed by in-place 8103 factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE` 8104 format). This option can save memory, for example, when solving nonlinear 8105 systems with a matrix-free Newton-Krylov method and a matrix-based, in-place 8106 ILU(0) preconditioner. 8107 8108 One can specify in-place ILU(0) factorization by calling 8109 .vb 8110 PCType(pc,PCILU); 8111 PCFactorSeUseInPlace(pc); 8112 .ve 8113 or by using the options -pc_type ilu -pc_factor_in_place 8114 8115 In-place factorization ILU(0) can also be used as a local 8116 solver for the blocks within the block Jacobi or additive Schwarz 8117 methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc 8118 for details on setting local solver options. 8119 8120 Most users should employ the `KSP` interface for linear solvers 8121 instead of working directly with matrix algebra routines such as this. 8122 See, e.g., `KSPCreate()`. 8123 8124 .seealso: [](chapter_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()` 8125 @*/ 8126 PetscErrorCode MatSetUnfactored(Mat mat) 8127 { 8128 PetscFunctionBegin; 8129 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8130 PetscValidType(mat, 1); 8131 MatCheckPreallocated(mat, 1); 8132 mat->factortype = MAT_FACTOR_NONE; 8133 if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS); 8134 PetscUseTypeMethod(mat, setunfactored); 8135 PetscFunctionReturn(PETSC_SUCCESS); 8136 } 8137 8138 /*MC 8139 MatDenseGetArrayF90 - Accesses a matrix array from Fortran 8140 8141 Synopsis: 8142 MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8143 8144 Not Collective 8145 8146 Input Parameter: 8147 . x - matrix 8148 8149 Output Parameters: 8150 + xx_v - the Fortran pointer to the array 8151 - ierr - error code 8152 8153 Example of Usage: 8154 .vb 8155 PetscScalar, pointer xx_v(:,:) 8156 .... 8157 call MatDenseGetArrayF90(x,xx_v,ierr) 8158 a = xx_v(3) 8159 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8160 .ve 8161 8162 Level: advanced 8163 8164 .seealso: [](chapter_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()` 8165 M*/ 8166 8167 /*MC 8168 MatDenseRestoreArrayF90 - Restores a matrix array that has been 8169 accessed with `MatDenseGetArrayF90()`. 8170 8171 Synopsis: 8172 MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8173 8174 Not Collective 8175 8176 Input Parameters: 8177 + x - matrix 8178 - xx_v - the Fortran90 pointer to the array 8179 8180 Output Parameter: 8181 . ierr - error code 8182 8183 Example of Usage: 8184 .vb 8185 PetscScalar, pointer xx_v(:,:) 8186 .... 8187 call MatDenseGetArrayF90(x,xx_v,ierr) 8188 a = xx_v(3) 8189 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8190 .ve 8191 8192 Level: advanced 8193 8194 .seealso: [](chapter_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()` 8195 M*/ 8196 8197 /*MC 8198 MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran. 8199 8200 Synopsis: 8201 MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8202 8203 Not Collective 8204 8205 Input Parameter: 8206 . x - matrix 8207 8208 Output Parameters: 8209 + xx_v - the Fortran pointer to the array 8210 - ierr - error code 8211 8212 Example of Usage: 8213 .vb 8214 PetscScalar, pointer xx_v(:) 8215 .... 8216 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8217 a = xx_v(3) 8218 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8219 .ve 8220 8221 Level: advanced 8222 8223 .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()` 8224 M*/ 8225 8226 /*MC 8227 MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been 8228 accessed with `MatSeqAIJGetArrayF90()`. 8229 8230 Synopsis: 8231 MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8232 8233 Not Collective 8234 8235 Input Parameters: 8236 + x - matrix 8237 - xx_v - the Fortran90 pointer to the array 8238 8239 Output Parameter: 8240 . ierr - error code 8241 8242 Example of Usage: 8243 .vb 8244 PetscScalar, pointer xx_v(:) 8245 .... 8246 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8247 a = xx_v(3) 8248 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8249 .ve 8250 8251 Level: advanced 8252 8253 .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()` 8254 M*/ 8255 8256 /*@ 8257 MatCreateSubMatrix - Gets a single submatrix on the same number of processors 8258 as the original matrix. 8259 8260 Collective 8261 8262 Input Parameters: 8263 + mat - the original matrix 8264 . isrow - parallel `IS` containing the rows this processor should obtain 8265 . 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. 8266 - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 8267 8268 Output Parameter: 8269 . newmat - the new submatrix, of the same type as the original matrix 8270 8271 Level: advanced 8272 8273 Notes: 8274 The submatrix will be able to be multiplied with vectors using the same layout as `iscol`. 8275 8276 Some matrix types place restrictions on the row and column indices, such 8277 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; 8278 for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row. 8279 8280 The index sets may not have duplicate entries. 8281 8282 The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`, 8283 the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls 8284 to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX` 8285 will reuse the matrix generated the first time. You should call `MatDestroy()` on `newmat` when 8286 you are finished using it. 8287 8288 The communicator of the newly obtained matrix is ALWAYS the same as the communicator of 8289 the input matrix. 8290 8291 If `iscol` is `NULL` then all columns are obtained (not supported in Fortran). 8292 8293 Example usage: 8294 Consider the following 8x8 matrix with 34 non-zero values, that is 8295 assembled across 3 processors. Let's assume that proc0 owns 3 rows, 8296 proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 8297 as follows 8298 .vb 8299 1 2 0 | 0 3 0 | 0 4 8300 Proc0 0 5 6 | 7 0 0 | 8 0 8301 9 0 10 | 11 0 0 | 12 0 8302 ------------------------------------- 8303 13 0 14 | 15 16 17 | 0 0 8304 Proc1 0 18 0 | 19 20 21 | 0 0 8305 0 0 0 | 22 23 0 | 24 0 8306 ------------------------------------- 8307 Proc2 25 26 27 | 0 0 28 | 29 0 8308 30 0 0 | 31 32 33 | 0 34 8309 .ve 8310 8311 Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6]. The resulting submatrix is 8312 8313 .vb 8314 2 0 | 0 3 0 | 0 8315 Proc0 5 6 | 7 0 0 | 8 8316 ------------------------------- 8317 Proc1 18 0 | 19 20 21 | 0 8318 ------------------------------- 8319 Proc2 26 27 | 0 0 28 | 29 8320 0 0 | 31 32 33 | 0 8321 .ve 8322 8323 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()` 8324 @*/ 8325 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat) 8326 { 8327 PetscMPIInt size; 8328 Mat *local; 8329 IS iscoltmp; 8330 PetscBool flg; 8331 8332 PetscFunctionBegin; 8333 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8334 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 8335 if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 8336 PetscValidPointer(newmat, 5); 8337 if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5); 8338 PetscValidType(mat, 1); 8339 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8340 PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX"); 8341 8342 MatCheckPreallocated(mat, 1); 8343 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8344 8345 if (!iscol || isrow == iscol) { 8346 PetscBool stride; 8347 PetscMPIInt grabentirematrix = 0, grab; 8348 PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride)); 8349 if (stride) { 8350 PetscInt first, step, n, rstart, rend; 8351 PetscCall(ISStrideGetInfo(isrow, &first, &step)); 8352 if (step == 1) { 8353 PetscCall(MatGetOwnershipRange(mat, &rstart, &rend)); 8354 if (rstart == first) { 8355 PetscCall(ISGetLocalSize(isrow, &n)); 8356 if (n == rend - rstart) grabentirematrix = 1; 8357 } 8358 } 8359 } 8360 PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat))); 8361 if (grab) { 8362 PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n")); 8363 if (cll == MAT_INITIAL_MATRIX) { 8364 *newmat = mat; 8365 PetscCall(PetscObjectReference((PetscObject)mat)); 8366 } 8367 PetscFunctionReturn(PETSC_SUCCESS); 8368 } 8369 } 8370 8371 if (!iscol) { 8372 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp)); 8373 } else { 8374 iscoltmp = iscol; 8375 } 8376 8377 /* if original matrix is on just one processor then use submatrix generated */ 8378 if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) { 8379 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat)); 8380 goto setproperties; 8381 } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) { 8382 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local)); 8383 *newmat = *local; 8384 PetscCall(PetscFree(local)); 8385 goto setproperties; 8386 } else if (!mat->ops->createsubmatrix) { 8387 /* Create a new matrix type that implements the operation using the full matrix */ 8388 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8389 switch (cll) { 8390 case MAT_INITIAL_MATRIX: 8391 PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat)); 8392 break; 8393 case MAT_REUSE_MATRIX: 8394 PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp)); 8395 break; 8396 default: 8397 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX"); 8398 } 8399 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8400 goto setproperties; 8401 } 8402 8403 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8404 PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat); 8405 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8406 8407 setproperties: 8408 PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg)); 8409 if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat)); 8410 if (!iscol) PetscCall(ISDestroy(&iscoltmp)); 8411 if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat)); 8412 PetscFunctionReturn(PETSC_SUCCESS); 8413 } 8414 8415 /*@ 8416 MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix 8417 8418 Not Collective 8419 8420 Input Parameters: 8421 + A - the matrix we wish to propagate options from 8422 - B - the matrix we wish to propagate options to 8423 8424 Level: beginner 8425 8426 Note: 8427 Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL` 8428 8429 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, MatIsStructurallySymmetricKnown()` 8430 @*/ 8431 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B) 8432 { 8433 PetscFunctionBegin; 8434 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8435 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 8436 B->symmetry_eternal = A->symmetry_eternal; 8437 B->structural_symmetry_eternal = A->structural_symmetry_eternal; 8438 B->symmetric = A->symmetric; 8439 B->structurally_symmetric = A->structurally_symmetric; 8440 B->spd = A->spd; 8441 B->hermitian = A->hermitian; 8442 PetscFunctionReturn(PETSC_SUCCESS); 8443 } 8444 8445 /*@ 8446 MatStashSetInitialSize - sets the sizes of the matrix stash, that is 8447 used during the assembly process to store values that belong to 8448 other processors. 8449 8450 Not Collective 8451 8452 Input Parameters: 8453 + mat - the matrix 8454 . size - the initial size of the stash. 8455 - bsize - the initial size of the block-stash(if used). 8456 8457 Options Database Keys: 8458 + -matstash_initial_size <size> or <size0,size1,...sizep-1> 8459 - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1> 8460 8461 Level: intermediate 8462 8463 Notes: 8464 The block-stash is used for values set with `MatSetValuesBlocked()` while 8465 the stash is used for values set with `MatSetValues()` 8466 8467 Run with the option -info and look for output of the form 8468 MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs. 8469 to determine the appropriate value, MM, to use for size and 8470 MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs. 8471 to determine the value, BMM to use for bsize 8472 8473 .seealso: [](chapter_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()` 8474 @*/ 8475 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize) 8476 { 8477 PetscFunctionBegin; 8478 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8479 PetscValidType(mat, 1); 8480 PetscCall(MatStashSetInitialSize_Private(&mat->stash, size)); 8481 PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize)); 8482 PetscFunctionReturn(PETSC_SUCCESS); 8483 } 8484 8485 /*@ 8486 MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of 8487 the matrix 8488 8489 Neighbor-wise Collective 8490 8491 Input Parameters: 8492 + mat - the matrix 8493 . x - the vector to be multiplied by the interpolation operator 8494 - y - the vector to be added to the result 8495 8496 Output Parameter: 8497 . w - the resulting vector 8498 8499 Level: intermediate 8500 8501 Notes: 8502 `w` may be the same vector as `y`. 8503 8504 This allows one to use either the restriction or interpolation (its transpose) 8505 matrix to do the interpolation 8506 8507 .seealso: [](chapter_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8508 @*/ 8509 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w) 8510 { 8511 PetscInt M, N, Ny; 8512 8513 PetscFunctionBegin; 8514 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8515 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8516 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8517 PetscValidHeaderSpecific(w, VEC_CLASSID, 4); 8518 PetscCall(MatGetSize(A, &M, &N)); 8519 PetscCall(VecGetSize(y, &Ny)); 8520 if (M == Ny) { 8521 PetscCall(MatMultAdd(A, x, y, w)); 8522 } else { 8523 PetscCall(MatMultTransposeAdd(A, x, y, w)); 8524 } 8525 PetscFunctionReturn(PETSC_SUCCESS); 8526 } 8527 8528 /*@ 8529 MatInterpolate - y = A*x or A'*x depending on the shape of 8530 the matrix 8531 8532 Neighbor-wise Collective 8533 8534 Input Parameters: 8535 + mat - the matrix 8536 - x - the vector to be interpolated 8537 8538 Output Parameter: 8539 . y - the resulting vector 8540 8541 Level: intermediate 8542 8543 Note: 8544 This allows one to use either the restriction or interpolation (its transpose) 8545 matrix to do the interpolation 8546 8547 .seealso: [](chapter_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8548 @*/ 8549 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y) 8550 { 8551 PetscInt M, N, Ny; 8552 8553 PetscFunctionBegin; 8554 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8555 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8556 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8557 PetscCall(MatGetSize(A, &M, &N)); 8558 PetscCall(VecGetSize(y, &Ny)); 8559 if (M == Ny) { 8560 PetscCall(MatMult(A, x, y)); 8561 } else { 8562 PetscCall(MatMultTranspose(A, x, y)); 8563 } 8564 PetscFunctionReturn(PETSC_SUCCESS); 8565 } 8566 8567 /*@ 8568 MatRestrict - y = A*x or A'*x 8569 8570 Neighbor-wise Collective 8571 8572 Input Parameters: 8573 + mat - the matrix 8574 - x - the vector to be restricted 8575 8576 Output Parameter: 8577 . y - the resulting vector 8578 8579 Level: intermediate 8580 8581 Note: 8582 This allows one to use either the restriction or interpolation (its transpose) 8583 matrix to do the restriction 8584 8585 .seealso: [](chapter_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG` 8586 @*/ 8587 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y) 8588 { 8589 PetscInt M, N, Ny; 8590 8591 PetscFunctionBegin; 8592 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8593 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8594 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8595 PetscCall(MatGetSize(A, &M, &N)); 8596 PetscCall(VecGetSize(y, &Ny)); 8597 if (M == Ny) { 8598 PetscCall(MatMult(A, x, y)); 8599 } else { 8600 PetscCall(MatMultTranspose(A, x, y)); 8601 } 8602 PetscFunctionReturn(PETSC_SUCCESS); 8603 } 8604 8605 /*@ 8606 MatMatInterpolateAdd - Y = W + A*X or W + A'*X 8607 8608 Neighbor-wise Collective 8609 8610 Input Parameters: 8611 + mat - the matrix 8612 . x - the input dense matrix to be multiplied 8613 - w - the input dense matrix to be added to the result 8614 8615 Output Parameter: 8616 . y - the output dense matrix 8617 8618 Level: intermediate 8619 8620 Note: 8621 This allows one to use either the restriction or interpolation (its transpose) 8622 matrix to do the interpolation. y matrix can be reused if already created with the proper sizes, 8623 otherwise it will be recreated. y must be initialized to `NULL` if not supplied. 8624 8625 .seealso: [](chapter_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG` 8626 @*/ 8627 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y) 8628 { 8629 PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0; 8630 PetscBool trans = PETSC_TRUE; 8631 MatReuse reuse = MAT_INITIAL_MATRIX; 8632 8633 PetscFunctionBegin; 8634 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8635 PetscValidHeaderSpecific(x, MAT_CLASSID, 2); 8636 PetscValidType(x, 2); 8637 if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3); 8638 if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4); 8639 PetscCall(MatGetSize(A, &M, &N)); 8640 PetscCall(MatGetSize(x, &Mx, &Nx)); 8641 if (N == Mx) trans = PETSC_FALSE; 8642 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); 8643 Mo = trans ? N : M; 8644 if (*y) { 8645 PetscCall(MatGetSize(*y, &My, &Ny)); 8646 if (Mo == My && Nx == Ny) { 8647 reuse = MAT_REUSE_MATRIX; 8648 } else { 8649 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); 8650 PetscCall(MatDestroy(y)); 8651 } 8652 } 8653 8654 if (w && *y == w) { /* this is to minimize changes in PCMG */ 8655 PetscBool flg; 8656 8657 PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w)); 8658 if (w) { 8659 PetscInt My, Ny, Mw, Nw; 8660 8661 PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg)); 8662 PetscCall(MatGetSize(*y, &My, &Ny)); 8663 PetscCall(MatGetSize(w, &Mw, &Nw)); 8664 if (!flg || My != Mw || Ny != Nw) w = NULL; 8665 } 8666 if (!w) { 8667 PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w)); 8668 PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w)); 8669 PetscCall(PetscObjectDereference((PetscObject)w)); 8670 } else { 8671 PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN)); 8672 } 8673 } 8674 if (!trans) { 8675 PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8676 } else { 8677 PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8678 } 8679 if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN)); 8680 PetscFunctionReturn(PETSC_SUCCESS); 8681 } 8682 8683 /*@ 8684 MatMatInterpolate - Y = A*X or A'*X 8685 8686 Neighbor-wise Collective 8687 8688 Input Parameters: 8689 + mat - the matrix 8690 - x - the input dense matrix 8691 8692 Output Parameter: 8693 . y - the output dense matrix 8694 8695 Level: intermediate 8696 8697 Note: 8698 This allows one to use either the restriction or interpolation (its transpose) 8699 matrix to do the interpolation. y matrix can be reused if already created with the proper sizes, 8700 otherwise it will be recreated. y must be initialized to `NULL` if not supplied. 8701 8702 .seealso: [](chapter_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG` 8703 @*/ 8704 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y) 8705 { 8706 PetscFunctionBegin; 8707 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8708 PetscFunctionReturn(PETSC_SUCCESS); 8709 } 8710 8711 /*@ 8712 MatMatRestrict - Y = A*X or A'*X 8713 8714 Neighbor-wise Collective 8715 8716 Input Parameters: 8717 + mat - the matrix 8718 - x - the input dense matrix 8719 8720 Output Parameter: 8721 . y - the output dense matrix 8722 8723 Level: intermediate 8724 8725 Note: 8726 This allows one to use either the restriction or interpolation (its transpose) 8727 matrix to do the restriction. y matrix can be reused if already created with the proper sizes, 8728 otherwise it will be recreated. y must be initialized to `NULL` if not supplied. 8729 8730 .seealso: [](chapter_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG` 8731 @*/ 8732 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y) 8733 { 8734 PetscFunctionBegin; 8735 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8736 PetscFunctionReturn(PETSC_SUCCESS); 8737 } 8738 8739 /*@ 8740 MatGetNullSpace - retrieves the null space of a matrix. 8741 8742 Logically Collective 8743 8744 Input Parameters: 8745 + mat - the matrix 8746 - nullsp - the null space object 8747 8748 Level: developer 8749 8750 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace` 8751 @*/ 8752 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp) 8753 { 8754 PetscFunctionBegin; 8755 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8756 PetscValidPointer(nullsp, 2); 8757 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp; 8758 PetscFunctionReturn(PETSC_SUCCESS); 8759 } 8760 8761 /*@ 8762 MatSetNullSpace - attaches a null space to a matrix. 8763 8764 Logically Collective 8765 8766 Input Parameters: 8767 + mat - the matrix 8768 - nullsp - the null space object 8769 8770 Level: advanced 8771 8772 Notes: 8773 This null space is used by the `KSP` linear solvers to solve singular systems. 8774 8775 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` 8776 8777 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 8778 to zero but the linear system will still be solved in a least squares sense. 8779 8780 The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that 8781 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). 8782 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 8783 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 8784 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). 8785 This \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix. 8786 8787 If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called 8788 `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this 8789 routine also automatically calls `MatSetTransposeNullSpace()`. 8790 8791 The user should call `MatNullSpaceDestroy()`. 8792 8793 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, 8794 `KSPSetPCSide()` 8795 @*/ 8796 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp) 8797 { 8798 PetscFunctionBegin; 8799 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8800 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8801 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8802 PetscCall(MatNullSpaceDestroy(&mat->nullsp)); 8803 mat->nullsp = nullsp; 8804 if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp)); 8805 PetscFunctionReturn(PETSC_SUCCESS); 8806 } 8807 8808 /*@ 8809 MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix. 8810 8811 Logically Collective 8812 8813 Input Parameters: 8814 + mat - the matrix 8815 - nullsp - the null space object 8816 8817 Level: developer 8818 8819 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()` 8820 @*/ 8821 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp) 8822 { 8823 PetscFunctionBegin; 8824 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8825 PetscValidType(mat, 1); 8826 PetscValidPointer(nullsp, 2); 8827 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp; 8828 PetscFunctionReturn(PETSC_SUCCESS); 8829 } 8830 8831 /*@ 8832 MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix 8833 8834 Logically Collective 8835 8836 Input Parameters: 8837 + mat - the matrix 8838 - nullsp - the null space object 8839 8840 Level: advanced 8841 8842 Notes: 8843 This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning. 8844 8845 See `MatSetNullSpace()` 8846 8847 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()` 8848 @*/ 8849 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp) 8850 { 8851 PetscFunctionBegin; 8852 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8853 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8854 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8855 PetscCall(MatNullSpaceDestroy(&mat->transnullsp)); 8856 mat->transnullsp = nullsp; 8857 PetscFunctionReturn(PETSC_SUCCESS); 8858 } 8859 8860 /*@ 8861 MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions 8862 This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix. 8863 8864 Logically Collective 8865 8866 Input Parameters: 8867 + mat - the matrix 8868 - nullsp - the null space object 8869 8870 Level: advanced 8871 8872 Notes: 8873 Overwrites any previous near null space that may have been attached 8874 8875 You can remove the null space by calling this routine with an nullsp of `NULL` 8876 8877 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()` 8878 @*/ 8879 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp) 8880 { 8881 PetscFunctionBegin; 8882 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8883 PetscValidType(mat, 1); 8884 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8885 MatCheckPreallocated(mat, 1); 8886 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8887 PetscCall(MatNullSpaceDestroy(&mat->nearnullsp)); 8888 mat->nearnullsp = nullsp; 8889 PetscFunctionReturn(PETSC_SUCCESS); 8890 } 8891 8892 /*@ 8893 MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()` 8894 8895 Not Collective 8896 8897 Input Parameter: 8898 . mat - the matrix 8899 8900 Output Parameter: 8901 . nullsp - the null space object, `NULL` if not set 8902 8903 Level: advanced 8904 8905 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()` 8906 @*/ 8907 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp) 8908 { 8909 PetscFunctionBegin; 8910 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8911 PetscValidType(mat, 1); 8912 PetscValidPointer(nullsp, 2); 8913 MatCheckPreallocated(mat, 1); 8914 *nullsp = mat->nearnullsp; 8915 PetscFunctionReturn(PETSC_SUCCESS); 8916 } 8917 8918 /*@C 8919 MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix. 8920 8921 Collective 8922 8923 Input Parameters: 8924 + mat - the matrix 8925 . row - row/column permutation 8926 - info - information on desired factorization process 8927 8928 Level: developer 8929 8930 Notes: 8931 Probably really in-place only when level of fill is zero, otherwise allocates 8932 new space to store factored matrix and deletes previous memory. 8933 8934 Most users should employ the `KSP` interface for linear solvers 8935 instead of working directly with matrix algebra routines such as this. 8936 See, e.g., `KSPCreate()`. 8937 8938 Developer Note: 8939 The Fortran interface is not autogenerated as the 8940 interface definition cannot be generated correctly [due to `MatFactorInfo`] 8941 8942 .seealso: [](chapter_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 8943 @*/ 8944 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info) 8945 { 8946 PetscFunctionBegin; 8947 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8948 PetscValidType(mat, 1); 8949 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 8950 PetscValidPointer(info, 3); 8951 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 8952 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 8953 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8954 MatCheckPreallocated(mat, 1); 8955 PetscUseTypeMethod(mat, iccfactor, row, info); 8956 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 8957 PetscFunctionReturn(PETSC_SUCCESS); 8958 } 8959 8960 /*@ 8961 MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the 8962 ghosted ones. 8963 8964 Not Collective 8965 8966 Input Parameters: 8967 + mat - the matrix 8968 - diag - the diagonal values, including ghost ones 8969 8970 Level: developer 8971 8972 Notes: 8973 Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices 8974 8975 This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()` 8976 8977 .seealso: [](chapter_matrices), `Mat`, `MatDiagonalScale()` 8978 @*/ 8979 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag) 8980 { 8981 PetscMPIInt size; 8982 8983 PetscFunctionBegin; 8984 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8985 PetscValidHeaderSpecific(diag, VEC_CLASSID, 2); 8986 PetscValidType(mat, 1); 8987 8988 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled"); 8989 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 8990 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8991 if (size == 1) { 8992 PetscInt n, m; 8993 PetscCall(VecGetSize(diag, &n)); 8994 PetscCall(MatGetSize(mat, NULL, &m)); 8995 PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions"); 8996 PetscCall(MatDiagonalScale(mat, NULL, diag)); 8997 } else { 8998 PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag)); 8999 } 9000 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 9001 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9002 PetscFunctionReturn(PETSC_SUCCESS); 9003 } 9004 9005 /*@ 9006 MatGetInertia - Gets the inertia from a factored matrix 9007 9008 Collective 9009 9010 Input Parameter: 9011 . mat - the matrix 9012 9013 Output Parameters: 9014 + nneg - number of negative eigenvalues 9015 . nzero - number of zero eigenvalues 9016 - npos - number of positive eigenvalues 9017 9018 Level: advanced 9019 9020 Note: 9021 Matrix must have been factored by `MatCholeskyFactor()` 9022 9023 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()` 9024 @*/ 9025 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos) 9026 { 9027 PetscFunctionBegin; 9028 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9029 PetscValidType(mat, 1); 9030 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9031 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled"); 9032 PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos); 9033 PetscFunctionReturn(PETSC_SUCCESS); 9034 } 9035 9036 /*@C 9037 MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors 9038 9039 Neighbor-wise Collective 9040 9041 Input Parameters: 9042 + mat - the factored matrix obtained with `MatGetFactor()` 9043 - b - the right-hand-side vectors 9044 9045 Output Parameter: 9046 . x - the result vectors 9047 9048 Level: developer 9049 9050 Note: 9051 The vectors `b` and `x` cannot be the same. I.e., one cannot 9052 call `MatSolves`(A,x,x). 9053 9054 .seealso: [](chapter_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()` 9055 @*/ 9056 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x) 9057 { 9058 PetscFunctionBegin; 9059 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9060 PetscValidType(mat, 1); 9061 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 9062 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9063 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 9064 9065 MatCheckPreallocated(mat, 1); 9066 PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0)); 9067 PetscUseTypeMethod(mat, solves, b, x); 9068 PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0)); 9069 PetscFunctionReturn(PETSC_SUCCESS); 9070 } 9071 9072 /*@ 9073 MatIsSymmetric - Test whether a matrix is symmetric 9074 9075 Collective 9076 9077 Input Parameters: 9078 + A - the matrix to test 9079 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose) 9080 9081 Output Parameter: 9082 . flg - the result 9083 9084 Level: intermediate 9085 9086 Notes: 9087 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9088 9089 If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()` 9090 9091 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9092 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9093 9094 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`, 9095 `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()` 9096 @*/ 9097 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg) 9098 { 9099 PetscFunctionBegin; 9100 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9101 PetscValidBoolPointer(flg, 3); 9102 9103 if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE; 9104 else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE; 9105 else { 9106 PetscUseTypeMethod(A, issymmetric, tol, flg); 9107 if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg)); 9108 } 9109 PetscFunctionReturn(PETSC_SUCCESS); 9110 } 9111 9112 /*@ 9113 MatIsHermitian - Test whether a matrix is Hermitian 9114 9115 Collective 9116 9117 Input Parameters: 9118 + A - the matrix to test 9119 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian) 9120 9121 Output Parameter: 9122 . flg - the result 9123 9124 Level: intermediate 9125 9126 Notes: 9127 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9128 9129 If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()` 9130 9131 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9132 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`) 9133 9134 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, 9135 `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()` 9136 @*/ 9137 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg) 9138 { 9139 PetscFunctionBegin; 9140 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9141 PetscValidBoolPointer(flg, 3); 9142 9143 if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE; 9144 else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE; 9145 else { 9146 PetscUseTypeMethod(A, ishermitian, tol, flg); 9147 if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg)); 9148 } 9149 PetscFunctionReturn(PETSC_SUCCESS); 9150 } 9151 9152 /*@ 9153 MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state 9154 9155 Not Collective 9156 9157 Input Parameter: 9158 . A - the matrix to check 9159 9160 Output Parameters: 9161 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid) 9162 - flg - the result (only valid if set is `PETSC_TRUE`) 9163 9164 Level: advanced 9165 9166 Notes: 9167 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()` 9168 if you want it explicitly checked 9169 9170 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9171 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9172 9173 .seealso: [](chapter_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9174 @*/ 9175 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9176 { 9177 PetscFunctionBegin; 9178 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9179 PetscValidBoolPointer(set, 2); 9180 PetscValidBoolPointer(flg, 3); 9181 if (A->symmetric != PETSC_BOOL3_UNKNOWN) { 9182 *set = PETSC_TRUE; 9183 *flg = PetscBool3ToBool(A->symmetric); 9184 } else { 9185 *set = PETSC_FALSE; 9186 } 9187 PetscFunctionReturn(PETSC_SUCCESS); 9188 } 9189 9190 /*@ 9191 MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state 9192 9193 Not Collective 9194 9195 Input Parameter: 9196 . A - the matrix to check 9197 9198 Output Parameters: 9199 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid) 9200 - flg - the result (only valid if set is `PETSC_TRUE`) 9201 9202 Level: advanced 9203 9204 Notes: 9205 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). 9206 9207 One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD 9208 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`) 9209 9210 .seealso: [](chapter_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9211 @*/ 9212 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg) 9213 { 9214 PetscFunctionBegin; 9215 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9216 PetscValidBoolPointer(set, 2); 9217 PetscValidBoolPointer(flg, 3); 9218 if (A->spd != PETSC_BOOL3_UNKNOWN) { 9219 *set = PETSC_TRUE; 9220 *flg = PetscBool3ToBool(A->spd); 9221 } else { 9222 *set = PETSC_FALSE; 9223 } 9224 PetscFunctionReturn(PETSC_SUCCESS); 9225 } 9226 9227 /*@ 9228 MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state 9229 9230 Not Collective 9231 9232 Input Parameter: 9233 . A - the matrix to check 9234 9235 Output Parameters: 9236 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid) 9237 - flg - the result (only valid if set is `PETSC_TRUE`) 9238 9239 Level: advanced 9240 9241 Notes: 9242 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()` 9243 if you want it explicitly checked 9244 9245 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9246 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9247 9248 .seealso: [](chapter_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()` 9249 @*/ 9250 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg) 9251 { 9252 PetscFunctionBegin; 9253 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9254 PetscValidBoolPointer(set, 2); 9255 PetscValidBoolPointer(flg, 3); 9256 if (A->hermitian != PETSC_BOOL3_UNKNOWN) { 9257 *set = PETSC_TRUE; 9258 *flg = PetscBool3ToBool(A->hermitian); 9259 } else { 9260 *set = PETSC_FALSE; 9261 } 9262 PetscFunctionReturn(PETSC_SUCCESS); 9263 } 9264 9265 /*@ 9266 MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric 9267 9268 Collective 9269 9270 Input Parameter: 9271 . A - the matrix to test 9272 9273 Output Parameter: 9274 . flg - the result 9275 9276 Level: intermediate 9277 9278 Notes: 9279 If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()` 9280 9281 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 9282 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9283 9284 .seealso: [](chapter_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()` 9285 @*/ 9286 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg) 9287 { 9288 PetscFunctionBegin; 9289 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9290 PetscValidBoolPointer(flg, 2); 9291 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9292 *flg = PetscBool3ToBool(A->structurally_symmetric); 9293 } else { 9294 PetscUseTypeMethod(A, isstructurallysymmetric, flg); 9295 PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg)); 9296 } 9297 PetscFunctionReturn(PETSC_SUCCESS); 9298 } 9299 9300 /*@ 9301 MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state 9302 9303 Not Collective 9304 9305 Input Parameter: 9306 . A - the matrix to check 9307 9308 Output Parameters: 9309 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid) 9310 - flg - the result (only valid if set is PETSC_TRUE) 9311 9312 Level: advanced 9313 9314 Notes: 9315 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 9316 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9317 9318 Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation) 9319 9320 .seealso: [](chapter_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9321 @*/ 9322 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9323 { 9324 PetscFunctionBegin; 9325 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9326 PetscValidBoolPointer(set, 2); 9327 PetscValidBoolPointer(flg, 3); 9328 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9329 *set = PETSC_TRUE; 9330 *flg = PetscBool3ToBool(A->structurally_symmetric); 9331 } else { 9332 *set = PETSC_FALSE; 9333 } 9334 PetscFunctionReturn(PETSC_SUCCESS); 9335 } 9336 9337 /*@ 9338 MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need 9339 to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process 9340 9341 Not Collective 9342 9343 Input Parameter: 9344 . mat - the matrix 9345 9346 Output Parameters: 9347 + nstash - the size of the stash 9348 . reallocs - the number of additional mallocs incurred. 9349 . bnstash - the size of the block stash 9350 - breallocs - the number of additional mallocs incurred.in the block stash 9351 9352 Level: advanced 9353 9354 .seealso: [](chapter_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()` 9355 @*/ 9356 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs) 9357 { 9358 PetscFunctionBegin; 9359 PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs)); 9360 PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs)); 9361 PetscFunctionReturn(PETSC_SUCCESS); 9362 } 9363 9364 /*@C 9365 MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same 9366 parallel layout, `PetscLayout` for rows and columns 9367 9368 Collective 9369 9370 Input Parameter: 9371 . mat - the matrix 9372 9373 Output Parameters: 9374 + right - (optional) vector that the matrix can be multiplied against 9375 - left - (optional) vector that the matrix vector product can be stored in 9376 9377 Level: advanced 9378 9379 Notes: 9380 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()`. 9381 9382 These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed 9383 9384 .seealso: [](chapter_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()` 9385 @*/ 9386 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left) 9387 { 9388 PetscFunctionBegin; 9389 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9390 PetscValidType(mat, 1); 9391 if (mat->ops->getvecs) { 9392 PetscUseTypeMethod(mat, getvecs, right, left); 9393 } else { 9394 PetscInt rbs, cbs; 9395 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 9396 if (right) { 9397 PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup"); 9398 PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), right)); 9399 PetscCall(VecSetSizes(*right, mat->cmap->n, PETSC_DETERMINE)); 9400 PetscCall(VecSetBlockSize(*right, cbs)); 9401 PetscCall(VecSetType(*right, mat->defaultvectype)); 9402 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9403 if (mat->boundtocpu && mat->bindingpropagates) { 9404 PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE)); 9405 PetscCall(VecBindToCPU(*right, PETSC_TRUE)); 9406 } 9407 #endif 9408 PetscCall(PetscLayoutReference(mat->cmap, &(*right)->map)); 9409 } 9410 if (left) { 9411 PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup"); 9412 PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), left)); 9413 PetscCall(VecSetSizes(*left, mat->rmap->n, PETSC_DETERMINE)); 9414 PetscCall(VecSetBlockSize(*left, rbs)); 9415 PetscCall(VecSetType(*left, mat->defaultvectype)); 9416 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9417 if (mat->boundtocpu && mat->bindingpropagates) { 9418 PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE)); 9419 PetscCall(VecBindToCPU(*left, PETSC_TRUE)); 9420 } 9421 #endif 9422 PetscCall(PetscLayoutReference(mat->rmap, &(*left)->map)); 9423 } 9424 } 9425 PetscFunctionReturn(PETSC_SUCCESS); 9426 } 9427 9428 /*@C 9429 MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure 9430 with default values. 9431 9432 Not Collective 9433 9434 Input Parameter: 9435 . info - the `MatFactorInfo` data structure 9436 9437 Level: developer 9438 9439 Notes: 9440 The solvers are generally used through the `KSP` and `PC` objects, for example 9441 `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC` 9442 9443 Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed 9444 9445 Developer Note: 9446 The Fortran interface is not autogenerated as the 9447 interface definition cannot be generated correctly [due to `MatFactorInfo`] 9448 9449 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo` 9450 @*/ 9451 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info) 9452 { 9453 PetscFunctionBegin; 9454 PetscCall(PetscMemzero(info, sizeof(MatFactorInfo))); 9455 PetscFunctionReturn(PETSC_SUCCESS); 9456 } 9457 9458 /*@ 9459 MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed 9460 9461 Collective 9462 9463 Input Parameters: 9464 + mat - the factored matrix 9465 - is - the index set defining the Schur indices (0-based) 9466 9467 Level: advanced 9468 9469 Notes: 9470 Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system. 9471 9472 You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call. 9473 9474 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9475 9476 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`, 9477 `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9478 @*/ 9479 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is) 9480 { 9481 PetscErrorCode (*f)(Mat, IS); 9482 9483 PetscFunctionBegin; 9484 PetscValidType(mat, 1); 9485 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9486 PetscValidType(is, 2); 9487 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 9488 PetscCheckSameComm(mat, 1, is, 2); 9489 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 9490 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f)); 9491 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO"); 9492 PetscCall(MatDestroy(&mat->schur)); 9493 PetscCall((*f)(mat, is)); 9494 PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created"); 9495 PetscFunctionReturn(PETSC_SUCCESS); 9496 } 9497 9498 /*@ 9499 MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step 9500 9501 Logically Collective 9502 9503 Input Parameters: 9504 + F - the factored matrix obtained by calling `MatGetFactor()` 9505 . S - location where to return the Schur complement, can be `NULL` 9506 - status - the status of the Schur complement matrix, can be `NULL` 9507 9508 Level: advanced 9509 9510 Notes: 9511 You must call `MatFactorSetSchurIS()` before calling this routine. 9512 9513 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9514 9515 The routine provides a copy of the Schur matrix stored within the solver data structures. 9516 The caller must destroy the object when it is no longer needed. 9517 If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse. 9518 9519 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) 9520 9521 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9522 9523 Developer Note: 9524 The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc 9525 matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix. 9526 9527 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9528 @*/ 9529 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9530 { 9531 PetscFunctionBegin; 9532 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9533 if (S) PetscValidPointer(S, 2); 9534 if (status) PetscValidPointer(status, 3); 9535 if (S) { 9536 PetscErrorCode (*f)(Mat, Mat *); 9537 9538 PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f)); 9539 if (f) { 9540 PetscCall((*f)(F, S)); 9541 } else { 9542 PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S)); 9543 } 9544 } 9545 if (status) *status = F->schur_status; 9546 PetscFunctionReturn(PETSC_SUCCESS); 9547 } 9548 9549 /*@ 9550 MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix 9551 9552 Logically Collective 9553 9554 Input Parameters: 9555 + F - the factored matrix obtained by calling `MatGetFactor()` 9556 . *S - location where to return the Schur complement, can be `NULL` 9557 - status - the status of the Schur complement matrix, can be `NULL` 9558 9559 Level: advanced 9560 9561 Notes: 9562 You must call `MatFactorSetSchurIS()` before calling this routine. 9563 9564 Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS` 9565 9566 The routine returns a the Schur Complement stored within the data structures of the solver. 9567 9568 If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement. 9569 9570 The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed. 9571 9572 Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix 9573 9574 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9575 9576 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9577 @*/ 9578 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9579 { 9580 PetscFunctionBegin; 9581 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9582 if (S) PetscValidPointer(S, 2); 9583 if (status) PetscValidPointer(status, 3); 9584 if (S) *S = F->schur; 9585 if (status) *status = F->schur_status; 9586 PetscFunctionReturn(PETSC_SUCCESS); 9587 } 9588 9589 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F) 9590 { 9591 Mat S = F->schur; 9592 9593 PetscFunctionBegin; 9594 switch (F->schur_status) { 9595 case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through 9596 case MAT_FACTOR_SCHUR_INVERTED: 9597 if (S) { 9598 S->ops->solve = NULL; 9599 S->ops->matsolve = NULL; 9600 S->ops->solvetranspose = NULL; 9601 S->ops->matsolvetranspose = NULL; 9602 S->ops->solveadd = NULL; 9603 S->ops->solvetransposeadd = NULL; 9604 S->factortype = MAT_FACTOR_NONE; 9605 PetscCall(PetscFree(S->solvertype)); 9606 } 9607 case MAT_FACTOR_SCHUR_FACTORED: // fall-through 9608 break; 9609 default: 9610 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9611 } 9612 PetscFunctionReturn(PETSC_SUCCESS); 9613 } 9614 9615 /*@ 9616 MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()` 9617 9618 Logically Collective 9619 9620 Input Parameters: 9621 + F - the factored matrix obtained by calling `MatGetFactor()` 9622 . *S - location where the Schur complement is stored 9623 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`) 9624 9625 Level: advanced 9626 9627 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9628 @*/ 9629 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status) 9630 { 9631 PetscFunctionBegin; 9632 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9633 if (S) { 9634 PetscValidHeaderSpecific(*S, MAT_CLASSID, 2); 9635 *S = NULL; 9636 } 9637 F->schur_status = status; 9638 PetscCall(MatFactorUpdateSchurStatus_Private(F)); 9639 PetscFunctionReturn(PETSC_SUCCESS); 9640 } 9641 9642 /*@ 9643 MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step 9644 9645 Logically Collective 9646 9647 Input Parameters: 9648 + F - the factored matrix obtained by calling `MatGetFactor()` 9649 . rhs - location where the right hand side of the Schur complement system is stored 9650 - sol - location where the solution of the Schur complement system has to be returned 9651 9652 Level: advanced 9653 9654 Notes: 9655 The sizes of the vectors should match the size of the Schur complement 9656 9657 Must be called after `MatFactorSetSchurIS()` 9658 9659 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()` 9660 @*/ 9661 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol) 9662 { 9663 PetscFunctionBegin; 9664 PetscValidType(F, 1); 9665 PetscValidType(rhs, 2); 9666 PetscValidType(sol, 3); 9667 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9668 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9669 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9670 PetscCheckSameComm(F, 1, rhs, 2); 9671 PetscCheckSameComm(F, 1, sol, 3); 9672 PetscCall(MatFactorFactorizeSchurComplement(F)); 9673 switch (F->schur_status) { 9674 case MAT_FACTOR_SCHUR_FACTORED: 9675 PetscCall(MatSolveTranspose(F->schur, rhs, sol)); 9676 break; 9677 case MAT_FACTOR_SCHUR_INVERTED: 9678 PetscCall(MatMultTranspose(F->schur, rhs, sol)); 9679 break; 9680 default: 9681 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9682 } 9683 PetscFunctionReturn(PETSC_SUCCESS); 9684 } 9685 9686 /*@ 9687 MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step 9688 9689 Logically Collective 9690 9691 Input Parameters: 9692 + F - the factored matrix obtained by calling `MatGetFactor()` 9693 . rhs - location where the right hand side of the Schur complement system is stored 9694 - sol - location where the solution of the Schur complement system has to be returned 9695 9696 Level: advanced 9697 9698 Notes: 9699 The sizes of the vectors should match the size of the Schur complement 9700 9701 Must be called after `MatFactorSetSchurIS()` 9702 9703 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()` 9704 @*/ 9705 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol) 9706 { 9707 PetscFunctionBegin; 9708 PetscValidType(F, 1); 9709 PetscValidType(rhs, 2); 9710 PetscValidType(sol, 3); 9711 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9712 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9713 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9714 PetscCheckSameComm(F, 1, rhs, 2); 9715 PetscCheckSameComm(F, 1, sol, 3); 9716 PetscCall(MatFactorFactorizeSchurComplement(F)); 9717 switch (F->schur_status) { 9718 case MAT_FACTOR_SCHUR_FACTORED: 9719 PetscCall(MatSolve(F->schur, rhs, sol)); 9720 break; 9721 case MAT_FACTOR_SCHUR_INVERTED: 9722 PetscCall(MatMult(F->schur, rhs, sol)); 9723 break; 9724 default: 9725 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9726 } 9727 PetscFunctionReturn(PETSC_SUCCESS); 9728 } 9729 9730 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat); 9731 #if PetscDefined(HAVE_CUDA) 9732 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat); 9733 #endif 9734 9735 /* Schur status updated in the interface */ 9736 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F) 9737 { 9738 Mat S = F->schur; 9739 9740 PetscFunctionBegin; 9741 if (S) { 9742 PetscMPIInt size; 9743 PetscBool isdense, isdensecuda; 9744 9745 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size)); 9746 PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented"); 9747 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense)); 9748 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda)); 9749 PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name); 9750 PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0)); 9751 if (isdense) { 9752 PetscCall(MatSeqDenseInvertFactors_Private(S)); 9753 } else if (isdensecuda) { 9754 #if defined(PETSC_HAVE_CUDA) 9755 PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S)); 9756 #endif 9757 } 9758 // HIP?????????????? 9759 PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0)); 9760 } 9761 PetscFunctionReturn(PETSC_SUCCESS); 9762 } 9763 9764 /*@ 9765 MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step 9766 9767 Logically Collective 9768 9769 Input Parameter: 9770 . F - the factored matrix obtained by calling `MatGetFactor()` 9771 9772 Level: advanced 9773 9774 Notes: 9775 Must be called after `MatFactorSetSchurIS()`. 9776 9777 Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it. 9778 9779 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()` 9780 @*/ 9781 PetscErrorCode MatFactorInvertSchurComplement(Mat F) 9782 { 9783 PetscFunctionBegin; 9784 PetscValidType(F, 1); 9785 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9786 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS); 9787 PetscCall(MatFactorFactorizeSchurComplement(F)); 9788 PetscCall(MatFactorInvertSchurComplement_Private(F)); 9789 F->schur_status = MAT_FACTOR_SCHUR_INVERTED; 9790 PetscFunctionReturn(PETSC_SUCCESS); 9791 } 9792 9793 /*@ 9794 MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step 9795 9796 Logically Collective 9797 9798 Input Parameter: 9799 . F - the factored matrix obtained by calling `MatGetFactor()` 9800 9801 Level: advanced 9802 9803 Note: 9804 Must be called after `MatFactorSetSchurIS()` 9805 9806 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()` 9807 @*/ 9808 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F) 9809 { 9810 MatFactorInfo info; 9811 9812 PetscFunctionBegin; 9813 PetscValidType(F, 1); 9814 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9815 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS); 9816 PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0)); 9817 PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo))); 9818 if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */ 9819 PetscCall(MatCholeskyFactor(F->schur, NULL, &info)); 9820 } else { 9821 PetscCall(MatLUFactor(F->schur, NULL, NULL, &info)); 9822 } 9823 PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0)); 9824 F->schur_status = MAT_FACTOR_SCHUR_FACTORED; 9825 PetscFunctionReturn(PETSC_SUCCESS); 9826 } 9827 9828 /*@ 9829 MatPtAP - Creates the matrix product C = P^T * A * P 9830 9831 Neighbor-wise Collective 9832 9833 Input Parameters: 9834 + A - the matrix 9835 . P - the projection matrix 9836 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9837 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate 9838 if the result is a dense matrix this is irrelevant 9839 9840 Output Parameter: 9841 . C - the product matrix 9842 9843 Level: intermediate 9844 9845 Notes: 9846 C will be created and must be destroyed by the user with `MatDestroy()`. 9847 9848 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9849 9850 Developer Note: 9851 For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`. 9852 9853 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()` 9854 @*/ 9855 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C) 9856 { 9857 PetscFunctionBegin; 9858 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 9859 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9860 9861 if (scall == MAT_INITIAL_MATRIX) { 9862 PetscCall(MatProductCreate(A, P, NULL, C)); 9863 PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP)); 9864 PetscCall(MatProductSetAlgorithm(*C, "default")); 9865 PetscCall(MatProductSetFill(*C, fill)); 9866 9867 (*C)->product->api_user = PETSC_TRUE; 9868 PetscCall(MatProductSetFromOptions(*C)); 9869 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); 9870 PetscCall(MatProductSymbolic(*C)); 9871 } else { /* scall == MAT_REUSE_MATRIX */ 9872 PetscCall(MatProductReplaceMats(A, P, NULL, *C)); 9873 } 9874 9875 PetscCall(MatProductNumeric(*C)); 9876 (*C)->symmetric = A->symmetric; 9877 (*C)->spd = A->spd; 9878 PetscFunctionReturn(PETSC_SUCCESS); 9879 } 9880 9881 /*@ 9882 MatRARt - Creates the matrix product C = R * A * R^T 9883 9884 Neighbor-wise Collective 9885 9886 Input Parameters: 9887 + A - the matrix 9888 . R - the projection matrix 9889 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9890 - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate 9891 if the result is a dense matrix this is irrelevant 9892 9893 Output Parameter: 9894 . C - the product matrix 9895 9896 Level: intermediate 9897 9898 Notes: 9899 C will be created and must be destroyed by the user with `MatDestroy()`. 9900 9901 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9902 9903 This routine is currently only implemented for pairs of `MATAIJ` matrices and classes 9904 which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes, 9905 parallel MatRARt is implemented via explicit transpose of R, which could be very expensive. 9906 We recommend using MatPtAP(). 9907 9908 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()` 9909 @*/ 9910 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C) 9911 { 9912 PetscFunctionBegin; 9913 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 9914 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9915 9916 if (scall == MAT_INITIAL_MATRIX) { 9917 PetscCall(MatProductCreate(A, R, NULL, C)); 9918 PetscCall(MatProductSetType(*C, MATPRODUCT_RARt)); 9919 PetscCall(MatProductSetAlgorithm(*C, "default")); 9920 PetscCall(MatProductSetFill(*C, fill)); 9921 9922 (*C)->product->api_user = PETSC_TRUE; 9923 PetscCall(MatProductSetFromOptions(*C)); 9924 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); 9925 PetscCall(MatProductSymbolic(*C)); 9926 } else { /* scall == MAT_REUSE_MATRIX */ 9927 PetscCall(MatProductReplaceMats(A, R, NULL, *C)); 9928 } 9929 9930 PetscCall(MatProductNumeric(*C)); 9931 if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 9932 PetscFunctionReturn(PETSC_SUCCESS); 9933 } 9934 9935 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C) 9936 { 9937 PetscFunctionBegin; 9938 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9939 9940 if (scall == MAT_INITIAL_MATRIX) { 9941 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype])); 9942 PetscCall(MatProductCreate(A, B, NULL, C)); 9943 PetscCall(MatProductSetType(*C, ptype)); 9944 PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT)); 9945 PetscCall(MatProductSetFill(*C, fill)); 9946 9947 (*C)->product->api_user = PETSC_TRUE; 9948 PetscCall(MatProductSetFromOptions(*C)); 9949 PetscCall(MatProductSymbolic(*C)); 9950 } else { /* scall == MAT_REUSE_MATRIX */ 9951 Mat_Product *product = (*C)->product; 9952 PetscBool isdense; 9953 9954 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, "")); 9955 if (isdense && product && product->type != ptype) { 9956 PetscCall(MatProductClear(*C)); 9957 product = NULL; 9958 } 9959 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype])); 9960 if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */ 9961 PetscCheck(isdense, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first"); 9962 PetscCall(MatProductCreate_Private(A, B, NULL, *C)); 9963 product = (*C)->product; 9964 product->fill = fill; 9965 product->api_user = PETSC_TRUE; 9966 product->clear = PETSC_TRUE; 9967 9968 PetscCall(MatProductSetType(*C, ptype)); 9969 PetscCall(MatProductSetFromOptions(*C)); 9970 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); 9971 PetscCall(MatProductSymbolic(*C)); 9972 } else { /* user may change input matrices A or B when REUSE */ 9973 PetscCall(MatProductReplaceMats(A, B, NULL, *C)); 9974 } 9975 } 9976 PetscCall(MatProductNumeric(*C)); 9977 PetscFunctionReturn(PETSC_SUCCESS); 9978 } 9979 9980 /*@ 9981 MatMatMult - Performs matrix-matrix multiplication C=A*B. 9982 9983 Neighbor-wise Collective 9984 9985 Input Parameters: 9986 + A - the left matrix 9987 . B - the right matrix 9988 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9989 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate 9990 if the result is a dense matrix this is irrelevant 9991 9992 Output Parameter: 9993 . C - the product matrix 9994 9995 Notes: 9996 Unless scall is `MAT_REUSE_MATRIX` C will be created. 9997 9998 `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 9999 call to this function with `MAT_INITIAL_MATRIX`. 10000 10001 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed. 10002 10003 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`, 10004 rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse. 10005 10006 Example of Usage: 10007 .vb 10008 MatProductCreate(A,B,NULL,&C); 10009 MatProductSetType(C,MATPRODUCT_AB); 10010 MatProductSymbolic(C); 10011 MatProductNumeric(C); // compute C=A * B 10012 MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1 10013 MatProductNumeric(C); 10014 MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1 10015 MatProductNumeric(C); 10016 .ve 10017 10018 Level: intermediate 10019 10020 .seealso: [](chapter_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()` 10021 @*/ 10022 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10023 { 10024 PetscFunctionBegin; 10025 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C)); 10026 PetscFunctionReturn(PETSC_SUCCESS); 10027 } 10028 10029 /*@ 10030 MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T. 10031 10032 Neighbor-wise Collective 10033 10034 Input Parameters: 10035 + A - the left matrix 10036 . B - the right matrix 10037 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10038 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 10039 10040 Output Parameter: 10041 . C - the product matrix 10042 10043 Level: intermediate 10044 10045 Notes: 10046 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10047 10048 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call 10049 10050 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10051 actually needed. 10052 10053 This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class, 10054 and for pairs of `MATMPIDENSE` matrices. 10055 10056 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt` 10057 10058 Options Database Keys: 10059 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the 10060 first redundantly copies the transposed B matrix on each process and requiers O(log P) communication complexity; 10061 the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity. 10062 10063 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductCreate()`, `MatProductAlgorithm`, `MatProductType`, `MATPRODUCT_ABt` 10064 @*/ 10065 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10066 { 10067 PetscFunctionBegin; 10068 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C)); 10069 if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10070 PetscFunctionReturn(PETSC_SUCCESS); 10071 } 10072 10073 /*@ 10074 MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B. 10075 10076 Neighbor-wise Collective 10077 10078 Input Parameters: 10079 + A - the left matrix 10080 . B - the right matrix 10081 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10082 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 10083 10084 Output Parameter: 10085 . C - the product matrix 10086 10087 Level: intermediate 10088 10089 Notes: 10090 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10091 10092 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call. 10093 10094 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB` 10095 10096 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10097 actually needed. 10098 10099 This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes 10100 which inherit from `MATSEQAIJ`. C will be of the same type as the input matrices. 10101 10102 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()` 10103 @*/ 10104 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10105 { 10106 PetscFunctionBegin; 10107 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C)); 10108 PetscFunctionReturn(PETSC_SUCCESS); 10109 } 10110 10111 /*@ 10112 MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C. 10113 10114 Neighbor-wise Collective 10115 10116 Input Parameters: 10117 + A - the left matrix 10118 . B - the middle matrix 10119 . C - the right matrix 10120 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10121 - 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 10122 if the result is a dense matrix this is irrelevant 10123 10124 Output Parameter: 10125 . D - the product matrix 10126 10127 Level: intermediate 10128 10129 Notes: 10130 Unless scall is `MAT_REUSE_MATRIX` D will be created. 10131 10132 `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call 10133 10134 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC` 10135 10136 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10137 actually needed. 10138 10139 If you have many matrices with the same non-zero structure to multiply, you 10140 should use `MAT_REUSE_MATRIX` in all calls but the first 10141 10142 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()` 10143 @*/ 10144 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D) 10145 { 10146 PetscFunctionBegin; 10147 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6); 10148 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10149 10150 if (scall == MAT_INITIAL_MATRIX) { 10151 PetscCall(MatProductCreate(A, B, C, D)); 10152 PetscCall(MatProductSetType(*D, MATPRODUCT_ABC)); 10153 PetscCall(MatProductSetAlgorithm(*D, "default")); 10154 PetscCall(MatProductSetFill(*D, fill)); 10155 10156 (*D)->product->api_user = PETSC_TRUE; 10157 PetscCall(MatProductSetFromOptions(*D)); 10158 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, 10159 ((PetscObject)C)->type_name); 10160 PetscCall(MatProductSymbolic(*D)); 10161 } else { /* user may change input matrices when REUSE */ 10162 PetscCall(MatProductReplaceMats(A, B, C, *D)); 10163 } 10164 PetscCall(MatProductNumeric(*D)); 10165 PetscFunctionReturn(PETSC_SUCCESS); 10166 } 10167 10168 /*@ 10169 MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators. 10170 10171 Collective 10172 10173 Input Parameters: 10174 + mat - the matrix 10175 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices) 10176 . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used) 10177 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10178 10179 Output Parameter: 10180 . matredundant - redundant matrix 10181 10182 Level: advanced 10183 10184 Notes: 10185 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 10186 original matrix has not changed from that last call to MatCreateRedundantMatrix(). 10187 10188 This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before 10189 calling it. 10190 10191 `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be. 10192 10193 .seealso: [](chapter_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubComm` 10194 @*/ 10195 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant) 10196 { 10197 MPI_Comm comm; 10198 PetscMPIInt size; 10199 PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs; 10200 Mat_Redundant *redund = NULL; 10201 PetscSubcomm psubcomm = NULL; 10202 MPI_Comm subcomm_in = subcomm; 10203 Mat *matseq; 10204 IS isrow, iscol; 10205 PetscBool newsubcomm = PETSC_FALSE; 10206 10207 PetscFunctionBegin; 10208 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10209 if (nsubcomm && reuse == MAT_REUSE_MATRIX) { 10210 PetscValidPointer(*matredundant, 5); 10211 PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5); 10212 } 10213 10214 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10215 if (size == 1 || nsubcomm == 1) { 10216 if (reuse == MAT_INITIAL_MATRIX) { 10217 PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant)); 10218 } else { 10219 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"); 10220 PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN)); 10221 } 10222 PetscFunctionReturn(PETSC_SUCCESS); 10223 } 10224 10225 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10226 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10227 MatCheckPreallocated(mat, 1); 10228 10229 PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0)); 10230 if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */ 10231 /* create psubcomm, then get subcomm */ 10232 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10233 PetscCallMPI(MPI_Comm_size(comm, &size)); 10234 PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size); 10235 10236 PetscCall(PetscSubcommCreate(comm, &psubcomm)); 10237 PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm)); 10238 PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS)); 10239 PetscCall(PetscSubcommSetFromOptions(psubcomm)); 10240 PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL)); 10241 newsubcomm = PETSC_TRUE; 10242 PetscCall(PetscSubcommDestroy(&psubcomm)); 10243 } 10244 10245 /* get isrow, iscol and a local sequential matrix matseq[0] */ 10246 if (reuse == MAT_INITIAL_MATRIX) { 10247 mloc_sub = PETSC_DECIDE; 10248 nloc_sub = PETSC_DECIDE; 10249 if (bs < 1) { 10250 PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M)); 10251 PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N)); 10252 } else { 10253 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M)); 10254 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N)); 10255 } 10256 PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm)); 10257 rstart = rend - mloc_sub; 10258 PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow)); 10259 PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol)); 10260 } else { /* reuse == MAT_REUSE_MATRIX */ 10261 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"); 10262 /* retrieve subcomm */ 10263 PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm)); 10264 redund = (*matredundant)->redundant; 10265 isrow = redund->isrow; 10266 iscol = redund->iscol; 10267 matseq = redund->matseq; 10268 } 10269 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq)); 10270 10271 /* get matredundant over subcomm */ 10272 if (reuse == MAT_INITIAL_MATRIX) { 10273 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant)); 10274 10275 /* create a supporting struct and attach it to C for reuse */ 10276 PetscCall(PetscNew(&redund)); 10277 (*matredundant)->redundant = redund; 10278 redund->isrow = isrow; 10279 redund->iscol = iscol; 10280 redund->matseq = matseq; 10281 if (newsubcomm) { 10282 redund->subcomm = subcomm; 10283 } else { 10284 redund->subcomm = MPI_COMM_NULL; 10285 } 10286 } else { 10287 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant)); 10288 } 10289 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 10290 if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) { 10291 PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE)); 10292 PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE)); 10293 } 10294 #endif 10295 PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0)); 10296 PetscFunctionReturn(PETSC_SUCCESS); 10297 } 10298 10299 /*@C 10300 MatGetMultiProcBlock - Create multiple 'parallel submatrices' from 10301 a given `Mat`. Each submatrix can span multiple procs. 10302 10303 Collective 10304 10305 Input Parameters: 10306 + mat - the matrix 10307 . subcomm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))` 10308 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10309 10310 Output Parameter: 10311 . subMat - parallel sub-matrices each spanning a given `subcomm` 10312 10313 Level: advanced 10314 10315 Notes: 10316 The submatrix partition across processors is dictated by `subComm` a 10317 communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm` 10318 is not restricted to be grouped with consecutive original ranks. 10319 10320 Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices 10321 map directly to the layout of the original matrix [wrt the local 10322 row,col partitioning]. So the original 'DiagonalMat' naturally maps 10323 into the 'DiagonalMat' of the `subMat`, hence it is used directly from 10324 the `subMat`. However the offDiagMat looses some columns - and this is 10325 reconstructed with `MatSetValues()` 10326 10327 This is used by `PCBJACOBI` when a single block spans multiple MPI ranks 10328 10329 .seealso: [](chapter_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI` 10330 @*/ 10331 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) 10332 { 10333 PetscMPIInt commsize, subCommSize; 10334 10335 PetscFunctionBegin; 10336 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize)); 10337 PetscCallMPI(MPI_Comm_size(subComm, &subCommSize)); 10338 PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize); 10339 10340 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"); 10341 PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10342 PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat); 10343 PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10344 PetscFunctionReturn(PETSC_SUCCESS); 10345 } 10346 10347 /*@ 10348 MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering 10349 10350 Not Collective 10351 10352 Input Parameters: 10353 + mat - matrix to extract local submatrix from 10354 . isrow - local row indices for submatrix 10355 - iscol - local column indices for submatrix 10356 10357 Output Parameter: 10358 . submat - the submatrix 10359 10360 Level: intermediate 10361 10362 Notes: 10363 `submat` should be disposed of with `MatRestoreLocalSubMatrix()`. 10364 10365 Depending on the format of `mat`, the returned submat may not implement `MatMult()`. Its communicator may be 10366 the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of `mat`'s. 10367 10368 `submat` always implements `MatSetValuesLocal()`. If `isrow` and `iscol` have the same block size, then 10369 `MatSetValuesBlockedLocal()` will also be implemented. 10370 10371 `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`. 10372 Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided. 10373 10374 .seealso: [](chapter_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()` 10375 @*/ 10376 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10377 { 10378 PetscFunctionBegin; 10379 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10380 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10381 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10382 PetscCheckSameComm(isrow, 2, iscol, 3); 10383 PetscValidPointer(submat, 4); 10384 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call"); 10385 10386 if (mat->ops->getlocalsubmatrix) { 10387 PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat); 10388 } else { 10389 PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat)); 10390 } 10391 PetscFunctionReturn(PETSC_SUCCESS); 10392 } 10393 10394 /*@ 10395 MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()` 10396 10397 Not Collective 10398 10399 Input Parameters: 10400 + mat - matrix to extract local submatrix from 10401 . isrow - local row indices for submatrix 10402 . iscol - local column indices for submatrix 10403 - submat - the submatrix 10404 10405 Level: intermediate 10406 10407 .seealso: [](chapter_matrices), `Mat`, `MatGetLocalSubMatrix()` 10408 @*/ 10409 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10410 { 10411 PetscFunctionBegin; 10412 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10413 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10414 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10415 PetscCheckSameComm(isrow, 2, iscol, 3); 10416 PetscValidPointer(submat, 4); 10417 if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4); 10418 10419 if (mat->ops->restorelocalsubmatrix) { 10420 PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat); 10421 } else { 10422 PetscCall(MatDestroy(submat)); 10423 } 10424 *submat = NULL; 10425 PetscFunctionReturn(PETSC_SUCCESS); 10426 } 10427 10428 /*@ 10429 MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix 10430 10431 Collective 10432 10433 Input Parameter: 10434 . mat - the matrix 10435 10436 Output Parameter: 10437 . is - if any rows have zero diagonals this contains the list of them 10438 10439 Level: developer 10440 10441 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10442 @*/ 10443 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is) 10444 { 10445 PetscFunctionBegin; 10446 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10447 PetscValidType(mat, 1); 10448 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10449 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10450 10451 if (!mat->ops->findzerodiagonals) { 10452 Vec diag; 10453 const PetscScalar *a; 10454 PetscInt *rows; 10455 PetscInt rStart, rEnd, r, nrow = 0; 10456 10457 PetscCall(MatCreateVecs(mat, &diag, NULL)); 10458 PetscCall(MatGetDiagonal(mat, diag)); 10459 PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd)); 10460 PetscCall(VecGetArrayRead(diag, &a)); 10461 for (r = 0; r < rEnd - rStart; ++r) 10462 if (a[r] == 0.0) ++nrow; 10463 PetscCall(PetscMalloc1(nrow, &rows)); 10464 nrow = 0; 10465 for (r = 0; r < rEnd - rStart; ++r) 10466 if (a[r] == 0.0) rows[nrow++] = r + rStart; 10467 PetscCall(VecRestoreArrayRead(diag, &a)); 10468 PetscCall(VecDestroy(&diag)); 10469 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is)); 10470 } else { 10471 PetscUseTypeMethod(mat, findzerodiagonals, is); 10472 } 10473 PetscFunctionReturn(PETSC_SUCCESS); 10474 } 10475 10476 /*@ 10477 MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size) 10478 10479 Collective 10480 10481 Input Parameter: 10482 . mat - the matrix 10483 10484 Output Parameter: 10485 . is - contains the list of rows with off block diagonal entries 10486 10487 Level: developer 10488 10489 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10490 @*/ 10491 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is) 10492 { 10493 PetscFunctionBegin; 10494 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10495 PetscValidType(mat, 1); 10496 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10497 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10498 10499 PetscUseTypeMethod(mat, findoffblockdiagonalentries, is); 10500 PetscFunctionReturn(PETSC_SUCCESS); 10501 } 10502 10503 /*@C 10504 MatInvertBlockDiagonal - Inverts the block diagonal entries. 10505 10506 Collective; No Fortran Support 10507 10508 Input Parameter: 10509 . mat - the matrix 10510 10511 Output Parameter: 10512 . values - the block inverses in column major order (FORTRAN-like) 10513 10514 Level: advanced 10515 10516 Notes: 10517 The size of the blocks is determined by the block size of the matrix. 10518 10519 The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case 10520 10521 The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size 10522 10523 .seealso: [](chapter_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()` 10524 @*/ 10525 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values) 10526 { 10527 PetscFunctionBegin; 10528 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10529 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10530 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10531 PetscUseTypeMethod(mat, invertblockdiagonal, values); 10532 PetscFunctionReturn(PETSC_SUCCESS); 10533 } 10534 10535 /*@C 10536 MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries. 10537 10538 Collective; No Fortran Support 10539 10540 Input Parameters: 10541 + mat - the matrix 10542 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()` 10543 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()` 10544 10545 Output Parameter: 10546 . values - the block inverses in column major order (FORTRAN-like) 10547 10548 Level: advanced 10549 10550 Notes: 10551 Use `MatInvertBlockDiagonal()` if all blocks have the same size 10552 10553 The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case 10554 10555 .seealso: [](chapter_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()` 10556 @*/ 10557 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values) 10558 { 10559 PetscFunctionBegin; 10560 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10561 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10562 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10563 PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values); 10564 PetscFunctionReturn(PETSC_SUCCESS); 10565 } 10566 10567 /*@ 10568 MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A 10569 10570 Collective 10571 10572 Input Parameters: 10573 + A - the matrix 10574 - C - matrix with inverted block diagonal of `A`. This matrix should be created and may have its type set. 10575 10576 Level: advanced 10577 10578 Note: 10579 The blocksize of the matrix is used to determine the blocks on the diagonal of `C` 10580 10581 .seealso: [](chapter_matrices), `Mat`, `MatInvertBlockDiagonal()` 10582 @*/ 10583 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C) 10584 { 10585 const PetscScalar *vals; 10586 PetscInt *dnnz; 10587 PetscInt m, rstart, rend, bs, i, j; 10588 10589 PetscFunctionBegin; 10590 PetscCall(MatInvertBlockDiagonal(A, &vals)); 10591 PetscCall(MatGetBlockSize(A, &bs)); 10592 PetscCall(MatGetLocalSize(A, &m, NULL)); 10593 PetscCall(MatSetLayouts(C, A->rmap, A->cmap)); 10594 PetscCall(PetscMalloc1(m / bs, &dnnz)); 10595 for (j = 0; j < m / bs; j++) dnnz[j] = 1; 10596 PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL)); 10597 PetscCall(PetscFree(dnnz)); 10598 PetscCall(MatGetOwnershipRange(C, &rstart, &rend)); 10599 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE)); 10600 for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES)); 10601 PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 10602 PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 10603 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE)); 10604 PetscFunctionReturn(PETSC_SUCCESS); 10605 } 10606 10607 /*@C 10608 MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created 10609 via `MatTransposeColoringCreate()`. 10610 10611 Collective 10612 10613 Input Parameter: 10614 . c - coloring context 10615 10616 Level: intermediate 10617 10618 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringCreate()` 10619 @*/ 10620 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c) 10621 { 10622 MatTransposeColoring matcolor = *c; 10623 10624 PetscFunctionBegin; 10625 if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS); 10626 if (--((PetscObject)matcolor)->refct > 0) { 10627 matcolor = NULL; 10628 PetscFunctionReturn(PETSC_SUCCESS); 10629 } 10630 10631 PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow)); 10632 PetscCall(PetscFree(matcolor->rows)); 10633 PetscCall(PetscFree(matcolor->den2sp)); 10634 PetscCall(PetscFree(matcolor->colorforcol)); 10635 PetscCall(PetscFree(matcolor->columns)); 10636 if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart)); 10637 PetscCall(PetscHeaderDestroy(c)); 10638 PetscFunctionReturn(PETSC_SUCCESS); 10639 } 10640 10641 /*@C 10642 MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which 10643 a `MatTransposeColoring` context has been created, computes a dense B^T by applying 10644 `MatTransposeColoring` to sparse B. 10645 10646 Collective 10647 10648 Input Parameters: 10649 + coloring - coloring context created with `MatTransposeColoringCreate()` 10650 - B - sparse matrix 10651 10652 Output Parameter: 10653 . Btdense - dense matrix B^T 10654 10655 Level: developer 10656 10657 Note: 10658 These are used internally for some implementations of `MatRARt()` 10659 10660 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()` 10661 @*/ 10662 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense) 10663 { 10664 PetscFunctionBegin; 10665 PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10666 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 10667 PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3); 10668 10669 PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense)); 10670 PetscFunctionReturn(PETSC_SUCCESS); 10671 } 10672 10673 /*@C 10674 MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which 10675 a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense 10676 in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix 10677 `Csp` from `Cden`. 10678 10679 Collective 10680 10681 Input Parameters: 10682 + matcoloring - coloring context created with `MatTransposeColoringCreate()` 10683 - Cden - matrix product of a sparse matrix and a dense matrix Btdense 10684 10685 Output Parameter: 10686 . Csp - sparse matrix 10687 10688 Level: developer 10689 10690 Note: 10691 These are used internally for some implementations of `MatRARt()` 10692 10693 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()` 10694 @*/ 10695 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp) 10696 { 10697 PetscFunctionBegin; 10698 PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10699 PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2); 10700 PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3); 10701 10702 PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp)); 10703 PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY)); 10704 PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY)); 10705 PetscFunctionReturn(PETSC_SUCCESS); 10706 } 10707 10708 /*@C 10709 MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T. 10710 10711 Collective 10712 10713 Input Parameters: 10714 + mat - the matrix product C 10715 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()` 10716 10717 Output Parameter: 10718 . color - the new coloring context 10719 10720 Level: intermediate 10721 10722 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`, 10723 `MatTransColoringApplyDenToSp()` 10724 @*/ 10725 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color) 10726 { 10727 MatTransposeColoring c; 10728 MPI_Comm comm; 10729 10730 PetscFunctionBegin; 10731 PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10732 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10733 PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL)); 10734 10735 c->ctype = iscoloring->ctype; 10736 PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c); 10737 10738 *color = c; 10739 PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10740 PetscFunctionReturn(PETSC_SUCCESS); 10741 } 10742 10743 /*@ 10744 MatGetNonzeroState - Returns a 64 bit integer representing the current state of nonzeros in the matrix. If the 10745 matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the 10746 same, otherwise it will be larger 10747 10748 Not Collective 10749 10750 Input Parameter: 10751 . A - the matrix 10752 10753 Output Parameter: 10754 . state - the current state 10755 10756 Level: intermediate 10757 10758 Notes: 10759 You can only compare states from two different calls to the SAME matrix, you cannot compare calls between 10760 different matrices 10761 10762 Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix 10763 10764 Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers. 10765 10766 .seealso: [](chapter_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()` 10767 @*/ 10768 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state) 10769 { 10770 PetscFunctionBegin; 10771 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10772 *state = mat->nonzerostate; 10773 PetscFunctionReturn(PETSC_SUCCESS); 10774 } 10775 10776 /*@ 10777 MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential 10778 matrices from each processor 10779 10780 Collective 10781 10782 Input Parameters: 10783 + comm - the communicators the parallel matrix will live on 10784 . seqmat - the input sequential matrices 10785 . n - number of local columns (or `PETSC_DECIDE`) 10786 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10787 10788 Output Parameter: 10789 . mpimat - the parallel matrix generated 10790 10791 Level: developer 10792 10793 Note: 10794 The number of columns of the matrix in EACH processor MUST be the same. 10795 10796 .seealso: [](chapter_matrices), `Mat` 10797 @*/ 10798 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat) 10799 { 10800 PetscMPIInt size; 10801 10802 PetscFunctionBegin; 10803 PetscCallMPI(MPI_Comm_size(comm, &size)); 10804 if (size == 1) { 10805 if (reuse == MAT_INITIAL_MATRIX) { 10806 PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat)); 10807 } else { 10808 PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN)); 10809 } 10810 PetscFunctionReturn(PETSC_SUCCESS); 10811 } 10812 10813 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"); 10814 10815 PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0)); 10816 PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat)); 10817 PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0)); 10818 PetscFunctionReturn(PETSC_SUCCESS); 10819 } 10820 10821 /*@ 10822 MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent ranks' ownership ranges. 10823 10824 Collective 10825 10826 Input Parameters: 10827 + A - the matrix to create subdomains from 10828 - N - requested number of subdomains 10829 10830 Output Parameters: 10831 + n - number of subdomains resulting on this rank 10832 - iss - `IS` list with indices of subdomains on this rank 10833 10834 Level: advanced 10835 10836 Note: 10837 The number of subdomains must be smaller than the communicator size 10838 10839 .seealso: [](chapter_matrices), `Mat`, `IS` 10840 @*/ 10841 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[]) 10842 { 10843 MPI_Comm comm, subcomm; 10844 PetscMPIInt size, rank, color; 10845 PetscInt rstart, rend, k; 10846 10847 PetscFunctionBegin; 10848 PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 10849 PetscCallMPI(MPI_Comm_size(comm, &size)); 10850 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 10851 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); 10852 *n = 1; 10853 k = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */ 10854 color = rank / k; 10855 PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm)); 10856 PetscCall(PetscMalloc1(1, iss)); 10857 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 10858 PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0])); 10859 PetscCallMPI(MPI_Comm_free(&subcomm)); 10860 PetscFunctionReturn(PETSC_SUCCESS); 10861 } 10862 10863 /*@ 10864 MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection. 10865 10866 If the interpolation and restriction operators are the same, uses `MatPtAP()`. 10867 If they are not the same, uses `MatMatMatMult()`. 10868 10869 Once the coarse grid problem is constructed, correct for interpolation operators 10870 that are not of full rank, which can legitimately happen in the case of non-nested 10871 geometric multigrid. 10872 10873 Input Parameters: 10874 + restrct - restriction operator 10875 . dA - fine grid matrix 10876 . interpolate - interpolation operator 10877 . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10878 - fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate 10879 10880 Output Parameter: 10881 . A - the Galerkin coarse matrix 10882 10883 Options Database Key: 10884 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used 10885 10886 Level: developer 10887 10888 .seealso: [](chapter_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()` 10889 @*/ 10890 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A) 10891 { 10892 IS zerorows; 10893 Vec diag; 10894 10895 PetscFunctionBegin; 10896 PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10897 /* Construct the coarse grid matrix */ 10898 if (interpolate == restrct) { 10899 PetscCall(MatPtAP(dA, interpolate, reuse, fill, A)); 10900 } else { 10901 PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A)); 10902 } 10903 10904 /* If the interpolation matrix is not of full rank, A will have zero rows. 10905 This can legitimately happen in the case of non-nested geometric multigrid. 10906 In that event, we set the rows of the matrix to the rows of the identity, 10907 ignoring the equations (as the RHS will also be zero). */ 10908 10909 PetscCall(MatFindZeroRows(*A, &zerorows)); 10910 10911 if (zerorows != NULL) { /* if there are any zero rows */ 10912 PetscCall(MatCreateVecs(*A, &diag, NULL)); 10913 PetscCall(MatGetDiagonal(*A, diag)); 10914 PetscCall(VecISSet(diag, zerorows, 1.0)); 10915 PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES)); 10916 PetscCall(VecDestroy(&diag)); 10917 PetscCall(ISDestroy(&zerorows)); 10918 } 10919 PetscFunctionReturn(PETSC_SUCCESS); 10920 } 10921 10922 /*@C 10923 MatSetOperation - Allows user to set a matrix operation for any matrix type 10924 10925 Logically Collective 10926 10927 Input Parameters: 10928 + mat - the matrix 10929 . op - the name of the operation 10930 - f - the function that provides the operation 10931 10932 Level: developer 10933 10934 Usage: 10935 .vb 10936 extern PetscErrorCode usermult(Mat, Vec, Vec); 10937 10938 PetscCall(MatCreateXXX(comm, ..., &A)); 10939 PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFunction)usermult)); 10940 .ve 10941 10942 Notes: 10943 See the file `include/petscmat.h` for a complete list of matrix 10944 operations, which all have the form MATOP_<OPERATION>, where 10945 <OPERATION> is the name (in all capital letters) of the 10946 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 10947 10948 All user-provided functions (except for `MATOP_DESTROY`) should have the same calling 10949 sequence as the usual matrix interface routines, since they 10950 are intended to be accessed via the usual matrix interface 10951 routines, e.g., 10952 .vb 10953 MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec) 10954 .ve 10955 10956 In particular each function MUST return `PETSC_SUCCESS` on success and 10957 nonzero on failure. 10958 10959 This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type. 10960 10961 .seealso: [](chapter_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()` 10962 @*/ 10963 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void)) 10964 { 10965 PetscFunctionBegin; 10966 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10967 if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view; 10968 (((void (**)(void))mat->ops)[op]) = f; 10969 PetscFunctionReturn(PETSC_SUCCESS); 10970 } 10971 10972 /*@C 10973 MatGetOperation - Gets a matrix operation for any matrix type. 10974 10975 Not Collective 10976 10977 Input Parameters: 10978 + mat - the matrix 10979 - op - the name of the operation 10980 10981 Output Parameter: 10982 . f - the function that provides the operation 10983 10984 Level: developer 10985 10986 Usage: 10987 .vb 10988 PetscErrorCode (*usermult)(Mat, Vec, Vec); 10989 MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult); 10990 .ve 10991 10992 Notes: 10993 See the file include/petscmat.h for a complete list of matrix 10994 operations, which all have the form MATOP_<OPERATION>, where 10995 <OPERATION> is the name (in all capital letters) of the 10996 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 10997 10998 This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type. 10999 11000 .seealso: [](chapter_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()` 11001 @*/ 11002 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void)) 11003 { 11004 PetscFunctionBegin; 11005 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11006 *f = (((void (**)(void))mat->ops)[op]); 11007 PetscFunctionReturn(PETSC_SUCCESS); 11008 } 11009 11010 /*@ 11011 MatHasOperation - Determines whether the given matrix supports the particular operation. 11012 11013 Not Collective 11014 11015 Input Parameters: 11016 + mat - the matrix 11017 - op - the operation, for example, `MATOP_GET_DIAGONAL` 11018 11019 Output Parameter: 11020 . has - either `PETSC_TRUE` or `PETSC_FALSE` 11021 11022 Level: advanced 11023 11024 Note: 11025 See `MatSetOperation()` for additional discussion on naming convention and usage of `op`. 11026 11027 .seealso: [](chapter_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()` 11028 @*/ 11029 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has) 11030 { 11031 PetscFunctionBegin; 11032 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11033 PetscValidBoolPointer(has, 3); 11034 if (mat->ops->hasoperation) { 11035 PetscUseTypeMethod(mat, hasoperation, op, has); 11036 } else { 11037 if (((void **)mat->ops)[op]) *has = PETSC_TRUE; 11038 else { 11039 *has = PETSC_FALSE; 11040 if (op == MATOP_CREATE_SUBMATRIX) { 11041 PetscMPIInt size; 11042 11043 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 11044 if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has)); 11045 } 11046 } 11047 } 11048 PetscFunctionReturn(PETSC_SUCCESS); 11049 } 11050 11051 /*@ 11052 MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent 11053 11054 Collective 11055 11056 Input Parameter: 11057 . mat - the matrix 11058 11059 Output Parameter: 11060 . cong - either `PETSC_TRUE` or `PETSC_FALSE` 11061 11062 Level: beginner 11063 11064 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout` 11065 @*/ 11066 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong) 11067 { 11068 PetscFunctionBegin; 11069 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11070 PetscValidType(mat, 1); 11071 PetscValidBoolPointer(cong, 2); 11072 if (!mat->rmap || !mat->cmap) { 11073 *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE; 11074 PetscFunctionReturn(PETSC_SUCCESS); 11075 } 11076 if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */ 11077 PetscCall(PetscLayoutSetUp(mat->rmap)); 11078 PetscCall(PetscLayoutSetUp(mat->cmap)); 11079 PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong)); 11080 if (*cong) mat->congruentlayouts = 1; 11081 else mat->congruentlayouts = 0; 11082 } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE; 11083 PetscFunctionReturn(PETSC_SUCCESS); 11084 } 11085 11086 PetscErrorCode MatSetInf(Mat A) 11087 { 11088 PetscFunctionBegin; 11089 PetscUseTypeMethod(A, setinf); 11090 PetscFunctionReturn(PETSC_SUCCESS); 11091 } 11092 11093 /*@C 11094 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 11095 and possibly removes small values from the graph structure. 11096 11097 Collective 11098 11099 Input Parameters: 11100 + A - the matrix 11101 . sym - `PETSC_TRUE` indicates that the graph should be symmetrized 11102 . scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry 11103 - filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value 11104 11105 Output Parameter: 11106 . graph - the resulting graph 11107 11108 Level: advanced 11109 11110 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `PCGAMG` 11111 @*/ 11112 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph) 11113 { 11114 PetscFunctionBegin; 11115 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11116 PetscValidType(A, 1); 11117 PetscValidLogicalCollectiveBool(A, scale, 3); 11118 PetscValidPointer(graph, 5); 11119 PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph); 11120 PetscFunctionReturn(PETSC_SUCCESS); 11121 } 11122 11123 /*@ 11124 MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place, 11125 meaning the same memory is used for the matrix, and no new memory is allocated. 11126 11127 Collective 11128 11129 Input Parameter: 11130 . A - the matrix 11131 11132 Level: intermediate 11133 11134 Developer Note: 11135 The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end 11136 of the arrays in the data structure are unneeded. 11137 11138 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatChop()` 11139 @*/ 11140 PetscErrorCode MatEliminateZeros(Mat A) 11141 { 11142 PetscFunctionBegin; 11143 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11144 PetscUseTypeMethod(A, eliminatezeros); 11145 PetscFunctionReturn(PETSC_SUCCESS); 11146 } 11147