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