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_DenseCopyToGPU, MAT_DenseCopyFromGPU; 43 PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom; 44 PetscLogEvent MAT_FactorFactS, MAT_FactorInvS; 45 PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights; 46 PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR; 47 48 const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL}; 49 50 /*@ 51 MatSetRandom - Sets all components of a matrix to random numbers. 52 53 Logically Collective 54 55 Input Parameters: 56 + x - the matrix 57 - rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or `NULL` and 58 it will create one internally. 59 60 Example: 61 .vb 62 PetscRandomCreate(PETSC_COMM_WORLD,&rctx); 63 MatSetRandom(x,rctx); 64 PetscRandomDestroy(rctx); 65 .ve 66 67 Level: intermediate 68 69 Notes: 70 For sparse matrices that have been preallocated but not been assembled it randomly selects appropriate locations, 71 72 for sparse matrices that already have locations it fills the locations with random numbers. 73 74 It generates an error if used on sparse matrices that have not been preallocated. 75 76 .seealso: [](chapter_matrices), `Mat`, `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomCreate()`, `PetscRandomDestroy()` 77 @*/ 78 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx) 79 { 80 PetscRandom randObj = NULL; 81 82 PetscFunctionBegin; 83 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 84 if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2); 85 PetscValidType(x, 1); 86 MatCheckPreallocated(x, 1); 87 88 if (!rctx) { 89 MPI_Comm comm; 90 PetscCall(PetscObjectGetComm((PetscObject)x, &comm)); 91 PetscCall(PetscRandomCreate(comm, &randObj)); 92 PetscCall(PetscRandomSetType(randObj, x->defaultrandtype)); 93 PetscCall(PetscRandomSetFromOptions(randObj)); 94 rctx = randObj; 95 } 96 PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0)); 97 PetscUseTypeMethod(x, setrandom, rctx); 98 PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0)); 99 100 PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY)); 101 PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY)); 102 PetscCall(PetscRandomDestroy(&randObj)); 103 PetscFunctionReturn(PETSC_SUCCESS); 104 } 105 106 /*@ 107 MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in 108 109 Logically Collective 110 111 Input Parameter: 112 . mat - the factored matrix 113 114 Output Parameters: 115 + pivot - the pivot value computed 116 - row - the row that the zero pivot occurred. This row value must be interpreted carefully due to row reorderings and which processes 117 the share the matrix 118 119 Level: advanced 120 121 Notes: 122 This routine does not work for factorizations done with external packages. 123 124 This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT` 125 126 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 127 128 .seealso: [](chapter_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, 129 `MAT_FACTOR_NUMERIC_ZEROPIVOT` 130 @*/ 131 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row) 132 { 133 PetscFunctionBegin; 134 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 135 PetscValidRealPointer(pivot, 2); 136 PetscValidIntPointer(row, 3); 137 *pivot = mat->factorerror_zeropivot_value; 138 *row = mat->factorerror_zeropivot_row; 139 PetscFunctionReturn(PETSC_SUCCESS); 140 } 141 142 /*@ 143 MatFactorGetError - gets the error code from a factorization 144 145 Logically Collective 146 147 Input Parameter: 148 . mat - the factored matrix 149 150 Output Parameter: 151 . err - the error code 152 153 Level: advanced 154 155 Note: 156 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 157 158 .seealso: [](chapter_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, 159 `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, `MatFactorError` 160 @*/ 161 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err) 162 { 163 PetscFunctionBegin; 164 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 165 PetscValidPointer(err, 2); 166 *err = mat->factorerrortype; 167 PetscFunctionReturn(PETSC_SUCCESS); 168 } 169 170 /*@ 171 MatFactorClearError - clears the error code in a factorization 172 173 Logically Collective 174 175 Input Parameter: 176 . mat - the factored matrix 177 178 Level: developer 179 180 Note: 181 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 182 183 .seealso: [](chapter_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`, 184 `MatGetErrorCode()`, `MatFactorError` 185 @*/ 186 PetscErrorCode MatFactorClearError(Mat mat) 187 { 188 PetscFunctionBegin; 189 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 190 mat->factorerrortype = MAT_FACTOR_NOERROR; 191 mat->factorerror_zeropivot_value = 0.0; 192 mat->factorerror_zeropivot_row = 0; 193 PetscFunctionReturn(PETSC_SUCCESS); 194 } 195 196 PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero) 197 { 198 Vec r, l; 199 const PetscScalar *al; 200 PetscInt i, nz, gnz, N, n; 201 202 PetscFunctionBegin; 203 PetscCall(MatCreateVecs(mat, &r, &l)); 204 if (!cols) { /* nonzero rows */ 205 PetscCall(MatGetSize(mat, &N, NULL)); 206 PetscCall(MatGetLocalSize(mat, &n, NULL)); 207 PetscCall(VecSet(l, 0.0)); 208 PetscCall(VecSetRandom(r, NULL)); 209 PetscCall(MatMult(mat, r, l)); 210 PetscCall(VecGetArrayRead(l, &al)); 211 } else { /* nonzero columns */ 212 PetscCall(MatGetSize(mat, NULL, &N)); 213 PetscCall(MatGetLocalSize(mat, NULL, &n)); 214 PetscCall(VecSet(r, 0.0)); 215 PetscCall(VecSetRandom(l, NULL)); 216 PetscCall(MatMultTranspose(mat, l, r)); 217 PetscCall(VecGetArrayRead(r, &al)); 218 } 219 if (tol <= 0.0) { 220 for (i = 0, nz = 0; i < n; i++) 221 if (al[i] != 0.0) nz++; 222 } else { 223 for (i = 0, nz = 0; i < n; i++) 224 if (PetscAbsScalar(al[i]) > tol) nz++; 225 } 226 PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 227 if (gnz != N) { 228 PetscInt *nzr; 229 PetscCall(PetscMalloc1(nz, &nzr)); 230 if (nz) { 231 if (tol < 0) { 232 for (i = 0, nz = 0; i < n; i++) 233 if (al[i] != 0.0) nzr[nz++] = i; 234 } else { 235 for (i = 0, nz = 0; i < n; i++) 236 if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i; 237 } 238 } 239 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero)); 240 } else *nonzero = NULL; 241 if (!cols) { /* nonzero rows */ 242 PetscCall(VecRestoreArrayRead(l, &al)); 243 } else { 244 PetscCall(VecRestoreArrayRead(r, &al)); 245 } 246 PetscCall(VecDestroy(&l)); 247 PetscCall(VecDestroy(&r)); 248 PetscFunctionReturn(PETSC_SUCCESS); 249 } 250 251 /*@ 252 MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix 253 254 Input Parameter: 255 . A - the matrix 256 257 Output Parameter: 258 . keptrows - the rows that are not completely zero 259 260 Level: intermediate 261 262 Note: 263 `keptrows` is set to `NULL` if all rows are nonzero. 264 265 .seealso: [](chapter_matrices), `Mat`, `MatFindZeroRows()` 266 @*/ 267 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows) 268 { 269 PetscFunctionBegin; 270 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 271 PetscValidType(mat, 1); 272 PetscValidPointer(keptrows, 2); 273 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 274 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 275 if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows); 276 else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows)); 277 PetscFunctionReturn(PETSC_SUCCESS); 278 } 279 280 /*@ 281 MatFindZeroRows - Locate all rows that are completely zero in the matrix 282 283 Input Parameter: 284 . A - the matrix 285 286 Output Parameter: 287 . zerorows - the rows that are completely zero 288 289 Level: intermediate 290 291 Note: 292 `zerorows` is set to `NULL` if no rows are zero. 293 294 .seealso: [](chapter_matrices), `Mat`, `MatFindNonzeroRows()` 295 @*/ 296 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows) 297 { 298 IS keptrows; 299 PetscInt m, n; 300 301 PetscFunctionBegin; 302 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 303 PetscValidType(mat, 1); 304 PetscValidPointer(zerorows, 2); 305 PetscCall(MatFindNonzeroRows(mat, &keptrows)); 306 /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows. 307 In keeping with this convention, we set zerorows to NULL if there are no zero 308 rows. */ 309 if (keptrows == NULL) { 310 *zerorows = NULL; 311 } else { 312 PetscCall(MatGetOwnershipRange(mat, &m, &n)); 313 PetscCall(ISComplement(keptrows, m, n, zerorows)); 314 PetscCall(ISDestroy(&keptrows)); 315 } 316 PetscFunctionReturn(PETSC_SUCCESS); 317 } 318 319 /*@ 320 MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling 321 322 Not Collective 323 324 Input Parameter: 325 . A - the matrix 326 327 Output Parameter: 328 . a - the diagonal part (which is a SEQUENTIAL matrix) 329 330 Level: advanced 331 332 Notes: 333 See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix. 334 335 Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation. 336 337 .seealso: [](chapter_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ` 338 @*/ 339 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a) 340 { 341 PetscFunctionBegin; 342 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 343 PetscValidType(A, 1); 344 PetscValidPointer(a, 2); 345 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 346 if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a); 347 else { 348 PetscMPIInt size; 349 350 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 351 PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name); 352 *a = A; 353 } 354 PetscFunctionReturn(PETSC_SUCCESS); 355 } 356 357 /*@ 358 MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries. 359 360 Collective 361 362 Input Parameter: 363 . mat - the matrix 364 365 Output Parameter: 366 . trace - the sum of the diagonal entries 367 368 Level: advanced 369 370 .seealso: [](chapter_matrices), `Mat` 371 @*/ 372 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace) 373 { 374 Vec diag; 375 376 PetscFunctionBegin; 377 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 378 PetscValidScalarPointer(trace, 2); 379 PetscCall(MatCreateVecs(mat, &diag, NULL)); 380 PetscCall(MatGetDiagonal(mat, diag)); 381 PetscCall(VecSum(diag, trace)); 382 PetscCall(VecDestroy(&diag)); 383 PetscFunctionReturn(PETSC_SUCCESS); 384 } 385 386 /*@ 387 MatRealPart - Zeros out the imaginary part of the matrix 388 389 Logically Collective 390 391 Input Parameter: 392 . mat - the matrix 393 394 Level: advanced 395 396 .seealso: [](chapter_matrices), `Mat`, `MatImaginaryPart()` 397 @*/ 398 PetscErrorCode MatRealPart(Mat mat) 399 { 400 PetscFunctionBegin; 401 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 402 PetscValidType(mat, 1); 403 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 404 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 405 MatCheckPreallocated(mat, 1); 406 PetscUseTypeMethod(mat, realpart); 407 PetscFunctionReturn(PETSC_SUCCESS); 408 } 409 410 /*@C 411 MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix 412 413 Collective 414 415 Input Parameter: 416 . mat - the matrix 417 418 Output Parameters: 419 + nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each block) 420 - ghosts - the global indices of the ghost points 421 422 Level: advanced 423 424 Note: 425 `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()` 426 427 .seealso: [](chapter_matrices), `Mat`, `VecCreateGhost()` 428 @*/ 429 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[]) 430 { 431 PetscFunctionBegin; 432 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 433 PetscValidType(mat, 1); 434 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 435 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 436 if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts); 437 else { 438 if (nghosts) *nghosts = 0; 439 if (ghosts) *ghosts = NULL; 440 } 441 PetscFunctionReturn(PETSC_SUCCESS); 442 } 443 444 /*@ 445 MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part 446 447 Logically Collective 448 449 Input Parameter: 450 . mat - the matrix 451 452 Level: advanced 453 454 .seealso: [](chapter_matrices), `Mat`, `MatRealPart()` 455 @*/ 456 PetscErrorCode MatImaginaryPart(Mat mat) 457 { 458 PetscFunctionBegin; 459 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 460 PetscValidType(mat, 1); 461 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 462 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 463 MatCheckPreallocated(mat, 1); 464 PetscUseTypeMethod(mat, imaginarypart); 465 PetscFunctionReturn(PETSC_SUCCESS); 466 } 467 468 /*@ 469 MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices) 470 471 Not Collective 472 473 Input Parameter: 474 . mat - the matrix 475 476 Output Parameters: 477 + missing - is any diagonal missing 478 - dd - first diagonal entry that is missing (optional) on this process 479 480 Level: advanced 481 482 .seealso: [](chapter_matrices), `Mat` 483 @*/ 484 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd) 485 { 486 PetscFunctionBegin; 487 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 488 PetscValidType(mat, 1); 489 PetscValidBoolPointer(missing, 2); 490 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name); 491 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 492 PetscUseTypeMethod(mat, missingdiagonal, missing, dd); 493 PetscFunctionReturn(PETSC_SUCCESS); 494 } 495 496 /*@C 497 MatGetRow - Gets a row of a matrix. You MUST call `MatRestoreRow()` 498 for each row that you get to ensure that your application does 499 not bleed memory. 500 501 Not Collective 502 503 Input Parameters: 504 + mat - the matrix 505 - row - the row to get 506 507 Output Parameters: 508 + ncols - if not `NULL`, the number of nonzeros in the row 509 . cols - if not `NULL`, the column numbers 510 - vals - if not `NULL`, the values 511 512 Level: advanced 513 514 Notes: 515 This routine is provided for people who need to have direct access 516 to the structure of a matrix. We hope that we provide enough 517 high-level matrix routines that few users will need it. 518 519 `MatGetRow()` always returns 0-based column indices, regardless of 520 whether the internal representation is 0-based (default) or 1-based. 521 522 For better efficiency, set cols and/or vals to `NULL` if you do 523 not wish to extract these quantities. 524 525 The user can only examine the values extracted with `MatGetRow()`; 526 the values cannot be altered. To change the matrix entries, one 527 must use `MatSetValues()`. 528 529 You can only have one call to `MatGetRow()` outstanding for a particular 530 matrix at a time, per processor. `MatGetRow()` can only obtain rows 531 associated with the given processor, it cannot get rows from the 532 other processors; for that we suggest using `MatCreateSubMatrices()`, then 533 MatGetRow() on the submatrix. The row index passed to `MatGetRow()` 534 is in the global number of rows. 535 536 Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix. 537 538 Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly. 539 540 Fortran Note: 541 The calling sequence is 542 .vb 543 MatGetRow(matrix,row,ncols,cols,values,ierr) 544 Mat matrix (input) 545 integer row (input) 546 integer ncols (output) 547 integer cols(maxcols) (output) 548 double precision (or double complex) values(maxcols) output 549 .ve 550 where maxcols >= maximum nonzeros in any row of the matrix. 551 552 Caution: 553 Do not try to change the contents of the output arrays (`cols` and `vals`). 554 In some cases, this may corrupt the matrix. 555 556 .seealso: [](chapter_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()` 557 @*/ 558 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 559 { 560 PetscInt incols; 561 562 PetscFunctionBegin; 563 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 564 PetscValidType(mat, 1); 565 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 566 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 567 MatCheckPreallocated(mat, 1); 568 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); 569 PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0)); 570 PetscCall((*mat->ops->getrow)(mat, row, &incols, (PetscInt **)cols, (PetscScalar **)vals)); 571 if (ncols) *ncols = incols; 572 PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0)); 573 PetscFunctionReturn(PETSC_SUCCESS); 574 } 575 576 /*@ 577 MatConjugate - replaces the matrix values with their complex conjugates 578 579 Logically Collective 580 581 Input Parameter: 582 . mat - the matrix 583 584 Level: advanced 585 586 .seealso: [](chapter_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()` 587 @*/ 588 PetscErrorCode MatConjugate(Mat mat) 589 { 590 PetscFunctionBegin; 591 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 592 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 593 if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) { 594 PetscUseTypeMethod(mat, conjugate); 595 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 596 } 597 PetscFunctionReturn(PETSC_SUCCESS); 598 } 599 600 /*@C 601 MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`. 602 603 Not Collective 604 605 Input Parameters: 606 + mat - the matrix 607 . row - the row to get 608 . ncols - the number of nonzeros 609 . cols - the columns of the nonzeros 610 - vals - if nonzero the column values 611 612 Level: advanced 613 614 Notes: 615 This routine should be called after you have finished examining the entries. 616 617 This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental 618 us of the array after it has been restored. If you pass `NULL`, it will 619 not zero the pointers. Use of `cols` or `vals` after `MatRestoreRow()` is invalid. 620 621 Fortran Notes: 622 The calling sequence is 623 .vb 624 MatRestoreRow(matrix,row,ncols,cols,values,ierr) 625 Mat matrix (input) 626 integer row (input) 627 integer ncols (output) 628 integer cols(maxcols) (output) 629 double precision (or double complex) values(maxcols) output 630 .ve 631 Where maxcols >= maximum nonzeros in any row of the matrix. 632 633 In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()` 634 before another call to `MatGetRow()` can be made. 635 636 .seealso: [](chapter_matrices), `Mat`, `MatGetRow()` 637 @*/ 638 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 639 { 640 PetscFunctionBegin; 641 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 642 if (ncols) PetscValidIntPointer(ncols, 3); 643 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 644 if (!mat->ops->restorerow) PetscFunctionReturn(PETSC_SUCCESS); 645 PetscCall((*mat->ops->restorerow)(mat, row, ncols, (PetscInt **)cols, (PetscScalar **)vals)); 646 if (ncols) *ncols = 0; 647 if (cols) *cols = NULL; 648 if (vals) *vals = NULL; 649 PetscFunctionReturn(PETSC_SUCCESS); 650 } 651 652 /*@ 653 MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 654 You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag. 655 656 Not Collective 657 658 Input Parameter: 659 . mat - the matrix 660 661 Level: advanced 662 663 Note: 664 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. 665 666 .seealso: [](chapter_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()` 667 @*/ 668 PetscErrorCode MatGetRowUpperTriangular(Mat mat) 669 { 670 PetscFunctionBegin; 671 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 672 PetscValidType(mat, 1); 673 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 674 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 675 MatCheckPreallocated(mat, 1); 676 if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS); 677 PetscUseTypeMethod(mat, getrowuppertriangular); 678 PetscFunctionReturn(PETSC_SUCCESS); 679 } 680 681 /*@ 682 MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 683 684 Not Collective 685 686 Input Parameter: 687 . mat - the matrix 688 689 Level: advanced 690 691 Note: 692 This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`. 693 694 .seealso: [](chapter_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()` 695 @*/ 696 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat) 697 { 698 PetscFunctionBegin; 699 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 700 PetscValidType(mat, 1); 701 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 702 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 703 MatCheckPreallocated(mat, 1); 704 if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS); 705 PetscUseTypeMethod(mat, restorerowuppertriangular); 706 PetscFunctionReturn(PETSC_SUCCESS); 707 } 708 709 /*@C 710 MatSetOptionsPrefix - Sets the prefix used for searching for all 711 `Mat` options in the database. 712 713 Logically Collective 714 715 Input Parameters: 716 + A - the matrix 717 - prefix - the prefix to prepend to all option names 718 719 Level: advanced 720 721 Notes: 722 A hyphen (-) must NOT be given at the beginning of the prefix name. 723 The first character of all runtime options is AUTOMATICALLY the hyphen. 724 725 This is NOT used for options for the factorization of the matrix. Normally the 726 prefix is automatically passed in from the PC calling the factorization. To set 727 it directly use `MatSetOptionsPrefixFactor()` 728 729 .seealso: [](chapter_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()` 730 @*/ 731 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[]) 732 { 733 PetscFunctionBegin; 734 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 735 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix)); 736 PetscFunctionReturn(PETSC_SUCCESS); 737 } 738 739 /*@C 740 MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for 741 for matrices created with `MatGetFactor()` 742 743 Logically Collective 744 745 Input Parameters: 746 + A - the matrix 747 - prefix - the prefix to prepend to all option names for the factored matrix 748 749 Level: developer 750 751 Notes: 752 A hyphen (-) must NOT be given at the beginning of the prefix name. 753 The first character of all runtime options is AUTOMATICALLY the hyphen. 754 755 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 756 it directly when not using `KSP`/`PC` use `MatSetOptionsPrefixFactor()` 757 758 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()` 759 @*/ 760 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[]) 761 { 762 PetscFunctionBegin; 763 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 764 if (prefix) { 765 PetscValidCharPointer(prefix, 2); 766 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 767 if (prefix != A->factorprefix) { 768 PetscCall(PetscFree(A->factorprefix)); 769 PetscCall(PetscStrallocpy(prefix, &A->factorprefix)); 770 } 771 } else PetscCall(PetscFree(A->factorprefix)); 772 PetscFunctionReturn(PETSC_SUCCESS); 773 } 774 775 /*@C 776 MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for 777 for matrices created with `MatGetFactor()` 778 779 Logically Collective 780 781 Input Parameters: 782 + A - the matrix 783 - prefix - the prefix to prepend to all option names for the factored matrix 784 785 Level: developer 786 787 Notes: 788 A hyphen (-) must NOT be given at the beginning of the prefix name. 789 The first character of all runtime options is AUTOMATICALLY the hyphen. 790 791 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 792 it directly when not using `KSP`/`PC` use `MatAppendOptionsPrefixFactor()` 793 794 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`, 795 `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`, 796 `MatSetOptionsPrefix()` 797 @*/ 798 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[]) 799 { 800 size_t len1, len2, new_len; 801 802 PetscFunctionBegin; 803 PetscValidHeader(A, 1); 804 if (!prefix) PetscFunctionReturn(PETSC_SUCCESS); 805 if (!A->factorprefix) { 806 PetscCall(MatSetOptionsPrefixFactor(A, prefix)); 807 PetscFunctionReturn(PETSC_SUCCESS); 808 } 809 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 810 811 PetscCall(PetscStrlen(A->factorprefix, &len1)); 812 PetscCall(PetscStrlen(prefix, &len2)); 813 new_len = len1 + len2 + 1; 814 PetscCall(PetscRealloc(new_len * sizeof(*(A->factorprefix)), &A->factorprefix)); 815 PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1)); 816 PetscFunctionReturn(PETSC_SUCCESS); 817 } 818 819 /*@C 820 MatAppendOptionsPrefix - Appends to the prefix used for searching for all 821 matrix options in the database. 822 823 Logically Collective 824 825 Input Parameters: 826 + A - the matrix 827 - prefix - the prefix to prepend to all option names 828 829 Level: advanced 830 831 Note: 832 A hyphen (-) must NOT be given at the beginning of the prefix name. 833 The first character of all runtime options is AUTOMATICALLY the hyphen. 834 835 .seealso: [](chapter_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()` 836 @*/ 837 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[]) 838 { 839 PetscFunctionBegin; 840 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 841 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix)); 842 PetscFunctionReturn(PETSC_SUCCESS); 843 } 844 845 /*@C 846 MatGetOptionsPrefix - Gets the prefix used for searching for all 847 matrix options in the database. 848 849 Not Collective 850 851 Input Parameter: 852 . A - the matrix 853 854 Output Parameter: 855 . prefix - pointer to the prefix string used 856 857 Level: advanced 858 859 Fortran Note: 860 The user should pass in a string `prefix` of 861 sufficient length to hold the prefix. 862 863 .seealso: [](chapter_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()` 864 @*/ 865 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[]) 866 { 867 PetscFunctionBegin; 868 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 869 PetscValidPointer(prefix, 2); 870 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix)); 871 PetscFunctionReturn(PETSC_SUCCESS); 872 } 873 874 /*@ 875 MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by users. 876 877 Collective 878 879 Input Parameter: 880 . A - the matrix 881 882 Level: beginner 883 884 Notes: 885 The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`. 886 887 Users can reset the preallocation to access the original memory. 888 889 Currently only supported for `MATAIJ` matrices. 890 891 .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()` 892 @*/ 893 PetscErrorCode MatResetPreallocation(Mat A) 894 { 895 PetscFunctionBegin; 896 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 897 PetscValidType(A, 1); 898 PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A)); 899 PetscFunctionReturn(PETSC_SUCCESS); 900 } 901 902 /*@ 903 MatSetUp - Sets up the internal matrix data structures for later use. 904 905 Collective 906 907 Input Parameter: 908 . A - the matrix 909 910 Level: intermediate 911 912 Notes: 913 If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of 914 setting values in the matrix. 915 916 If a suitable preallocation routine is used, this function does not need to be called. 917 918 This routine is called internally by other matrix functions when needed so rarely needs to be called by users 919 920 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()` 921 @*/ 922 PetscErrorCode MatSetUp(Mat A) 923 { 924 PetscFunctionBegin; 925 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 926 if (!((PetscObject)A)->type_name) { 927 PetscMPIInt size; 928 929 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 930 PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ)); 931 } 932 if (!A->preallocated) PetscTryTypeMethod(A, setup); 933 PetscCall(PetscLayoutSetUp(A->rmap)); 934 PetscCall(PetscLayoutSetUp(A->cmap)); 935 A->preallocated = PETSC_TRUE; 936 PetscFunctionReturn(PETSC_SUCCESS); 937 } 938 939 #if defined(PETSC_HAVE_SAWS) 940 #include <petscviewersaws.h> 941 #endif 942 943 /*@C 944 MatViewFromOptions - View properties of the matrix based on options set in the options database 945 946 Collective 947 948 Input Parameters: 949 + A - the matrix 950 . obj - optional additional object that provides the options prefix to use 951 - name - command line option 952 953 Options Database Key: 954 . -mat_view [viewertype]:... - the viewer and its options 955 956 Level: intermediate 957 958 Notes: 959 .vb 960 If no value is provided ascii:stdout is used 961 ascii[:[filename][:[format][:append]]] defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab, 962 for example ascii::ascii_info prints just the information about the object not all details 963 unless :append is given filename opens in write mode, overwriting what was already there 964 binary[:[filename][:[format][:append]]] defaults to the file binaryoutput 965 draw[:drawtype[:filename]] for example, draw:tikz, draw:tikz:figure.tex or draw:x 966 socket[:port] defaults to the standard output port 967 saws[:communicatorname] publishes object to the Scientific Application Webserver (SAWs) 968 .ve 969 970 .seealso: [](chapter_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()` 971 @*/ 972 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[]) 973 { 974 PetscFunctionBegin; 975 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 976 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 977 PetscFunctionReturn(PETSC_SUCCESS); 978 } 979 980 /*@C 981 MatView - display information about a matrix in a variety ways 982 983 Collective 984 985 Input Parameters: 986 + mat - the matrix 987 - viewer - visualization context 988 989 Options Database Keys: 990 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 991 . -mat_view ::ascii_info_detail - Prints more detailed info 992 . -mat_view - Prints matrix in ASCII format 993 . -mat_view ::ascii_matlab - Prints matrix in Matlab format 994 . -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 995 . -display <name> - Sets display name (default is host) 996 . -draw_pause <sec> - Sets number of seconds to pause after display 997 . -mat_view socket - Sends matrix to socket, can be accessed from Matlab (see Users-Manual: ch_matlab for details) 998 . -viewer_socket_machine <machine> - 999 . -viewer_socket_port <port> - 1000 . -mat_view binary - save matrix to file in binary format 1001 - -viewer_binary_filename <name> - 1002 1003 Level: beginner 1004 1005 Notes: 1006 The available visualization contexts include 1007 + `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices 1008 . `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD` 1009 . `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm 1010 - `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure 1011 1012 The user can open alternative visualization contexts with 1013 + `PetscViewerASCIIOpen()` - Outputs matrix to a specified file 1014 . `PetscViewerBinaryOpen()` - Outputs matrix in binary to a 1015 specified file; corresponding input uses MatLoad() 1016 . `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to 1017 an X window display 1018 - `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer. 1019 Currently only the sequential dense and AIJ 1020 matrix types support the Socket viewer. 1021 1022 The user can call `PetscViewerPushFormat()` to specify the output 1023 format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`, 1024 `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`). Available formats include 1025 + `PETSC_VIEWER_DEFAULT` - default, prints matrix contents 1026 . `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in Matlab format 1027 . `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros 1028 . `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse 1029 format common among all matrix types 1030 . `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific 1031 format (which is in many cases the same as the default) 1032 . `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix 1033 size and structure (not the matrix entries) 1034 - `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about 1035 the matrix structure 1036 1037 The ASCII viewers are only recommended for small matrices on at most a moderate number of processes, 1038 the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format. 1039 1040 In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer). 1041 1042 See the manual page for `MatLoad()` for the exact format of the binary file when the binary 1043 viewer is used. 1044 1045 See share/petsc/matlab/PetscBinaryRead.m for a Matlab code that can read in the binary file when the binary 1046 viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python. 1047 1048 One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure, 1049 and then use the following mouse functions. 1050 .vb 1051 left mouse: zoom in 1052 middle mouse: zoom out 1053 right mouse: continue with the simulation 1054 .ve 1055 1056 .seealso: [](chapter_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`, 1057 `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()` 1058 @*/ 1059 PetscErrorCode MatView(Mat mat, PetscViewer viewer) 1060 { 1061 PetscInt rows, cols, rbs, cbs; 1062 PetscBool isascii, isstring, issaws; 1063 PetscViewerFormat format; 1064 PetscMPIInt size; 1065 1066 PetscFunctionBegin; 1067 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1068 PetscValidType(mat, 1); 1069 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer)); 1070 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1071 PetscCheckSameComm(mat, 1, viewer, 2); 1072 1073 PetscCall(PetscViewerGetFormat(viewer, &format)); 1074 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 1075 if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS); 1076 1077 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 1078 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 1079 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws)); 1080 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"); 1081 1082 PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0)); 1083 if (isascii) { 1084 if (!mat->preallocated) { 1085 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n")); 1086 PetscFunctionReturn(PETSC_SUCCESS); 1087 } 1088 if (!mat->assembled) { 1089 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n")); 1090 PetscFunctionReturn(PETSC_SUCCESS); 1091 } 1092 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer)); 1093 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1094 MatNullSpace nullsp, transnullsp; 1095 1096 PetscCall(PetscViewerASCIIPushTab(viewer)); 1097 PetscCall(MatGetSize(mat, &rows, &cols)); 1098 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1099 if (rbs != 1 || cbs != 1) { 1100 if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs)); 1101 else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs)); 1102 } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols)); 1103 if (mat->factortype) { 1104 MatSolverType solver; 1105 PetscCall(MatFactorGetSolverType(mat, &solver)); 1106 PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver)); 1107 } 1108 if (mat->ops->getinfo) { 1109 MatInfo info; 1110 PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info)); 1111 PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated)); 1112 if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs)); 1113 } 1114 PetscCall(MatGetNullSpace(mat, &nullsp)); 1115 PetscCall(MatGetTransposeNullSpace(mat, &transnullsp)); 1116 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached null space\n")); 1117 if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached transposed null space\n")); 1118 PetscCall(MatGetNearNullSpace(mat, &nullsp)); 1119 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached near null space\n")); 1120 PetscCall(PetscViewerASCIIPushTab(viewer)); 1121 PetscCall(MatProductView(mat, viewer)); 1122 PetscCall(PetscViewerASCIIPopTab(viewer)); 1123 } 1124 } else if (issaws) { 1125 #if defined(PETSC_HAVE_SAWS) 1126 PetscMPIInt rank; 1127 1128 PetscCall(PetscObjectName((PetscObject)mat)); 1129 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 1130 if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer)); 1131 #endif 1132 } else if (isstring) { 1133 const char *type; 1134 PetscCall(MatGetType(mat, &type)); 1135 PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type)); 1136 PetscTryTypeMethod(mat, view, viewer); 1137 } 1138 if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) { 1139 PetscCall(PetscViewerASCIIPushTab(viewer)); 1140 PetscUseTypeMethod(mat, viewnative, viewer); 1141 PetscCall(PetscViewerASCIIPopTab(viewer)); 1142 } else if (mat->ops->view) { 1143 PetscCall(PetscViewerASCIIPushTab(viewer)); 1144 PetscUseTypeMethod(mat, view, viewer); 1145 PetscCall(PetscViewerASCIIPopTab(viewer)); 1146 } 1147 if (isascii) { 1148 PetscCall(PetscViewerGetFormat(viewer, &format)); 1149 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer)); 1150 } 1151 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1152 PetscFunctionReturn(PETSC_SUCCESS); 1153 } 1154 1155 #if defined(PETSC_USE_DEBUG) 1156 #include <../src/sys/totalview/tv_data_display.h> 1157 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat) 1158 { 1159 TV_add_row("Local rows", "int", &mat->rmap->n); 1160 TV_add_row("Local columns", "int", &mat->cmap->n); 1161 TV_add_row("Global rows", "int", &mat->rmap->N); 1162 TV_add_row("Global columns", "int", &mat->cmap->N); 1163 TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name); 1164 return TV_format_OK; 1165 } 1166 #endif 1167 1168 /*@C 1169 MatLoad - Loads a matrix that has been stored in binary/HDF5 format 1170 with `MatView()`. The matrix format is determined from the options database. 1171 Generates a parallel MPI matrix if the communicator has more than one 1172 processor. The default matrix type is `MATAIJ`. 1173 1174 Collective 1175 1176 Input Parameters: 1177 + mat - the newly loaded matrix, this needs to have been created with `MatCreate()` 1178 or some related function before a call to `MatLoad()` 1179 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer 1180 1181 Options Database Keys: 1182 Used with block matrix formats (`MATSEQBAIJ`, ...) to specify 1183 block size 1184 . -matload_block_size <bs> - set block size 1185 1186 Level: beginner 1187 1188 Notes: 1189 If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the 1190 `Mat` before calling this routine if you wish to set it from the options database. 1191 1192 `MatLoad()` automatically loads into the options database any options 1193 given in the file filename.info where filename is the name of the file 1194 that was passed to the `PetscViewerBinaryOpen()`. The options in the info 1195 file will be ignored if you use the -viewer_binary_skip_info option. 1196 1197 If the type or size of mat is not set before a call to `MatLoad()`, PETSc 1198 sets the default matrix type AIJ and sets the local and global sizes. 1199 If type and/or size is already set, then the same are used. 1200 1201 In parallel, each processor can load a subset of rows (or the 1202 entire matrix). This routine is especially useful when a large 1203 matrix is stored on disk and only part of it is desired on each 1204 processor. For example, a parallel solver may access only some of 1205 the rows from each processor. The algorithm used here reads 1206 relatively small blocks of data rather than reading the entire 1207 matrix and then subsetting it. 1208 1209 Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`. 1210 Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`, 1211 or the sequence like 1212 .vb 1213 `PetscViewer` v; 1214 `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v); 1215 `PetscViewerSetType`(v,`PETSCVIEWERBINARY`); 1216 `PetscViewerSetFromOptions`(v); 1217 `PetscViewerFileSetMode`(v,`FILE_MODE_READ`); 1218 `PetscViewerFileSetName`(v,"datafile"); 1219 .ve 1220 The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option 1221 $ -viewer_type {binary,hdf5} 1222 1223 See the example src/ksp/ksp/tutorials/ex27.c with the first approach, 1224 and src/mat/tutorials/ex10.c with the second approach. 1225 1226 In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks 1227 is read onto rank 0 and then shipped to its destination rank, one after another. 1228 Multiple objects, both matrices and vectors, can be stored within the same file. 1229 Their PetscObject name is ignored; they are loaded in the order of their storage. 1230 1231 Most users should not need to know the details of the binary storage 1232 format, since `MatLoad()` and `MatView()` completely hide these details. 1233 But for anyone who's interested, the standard binary matrix storage 1234 format is 1235 1236 .vb 1237 PetscInt MAT_FILE_CLASSID 1238 PetscInt number of rows 1239 PetscInt number of columns 1240 PetscInt total number of nonzeros 1241 PetscInt *number nonzeros in each row 1242 PetscInt *column indices of all nonzeros (starting index is zero) 1243 PetscScalar *values of all nonzeros 1244 .ve 1245 1246 PETSc automatically does the byte swapping for 1247 machines that store the bytes reversed. Thus if you write your own binary 1248 read/write routines you have to swap the bytes; see `PetscBinaryRead()` 1249 and `PetscBinaryWrite()` to see how this may be done. 1250 1251 In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used. 1252 Each processor's chunk is loaded independently by its owning rank. 1253 Multiple objects, both matrices and vectors, can be stored within the same file. 1254 They are looked up by their PetscObject name. 1255 1256 As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use 1257 by default the same structure and naming of the AIJ arrays and column count 1258 within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g. 1259 $ save example.mat A b -v7.3 1260 can be directly read by this routine (see Reference 1 for details). 1261 1262 Depending on your MATLAB version, this format might be a default, 1263 otherwise you can set it as default in Preferences. 1264 1265 Unless -nocompression flag is used to save the file in MATLAB, 1266 PETSc must be configured with ZLIB package. 1267 1268 See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c 1269 1270 This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5` 1271 1272 Corresponding `MatView()` is not yet implemented. 1273 1274 The loaded matrix is actually a transpose of the original one in MATLAB, 1275 unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above). 1276 With this format, matrix is automatically transposed by PETSc, 1277 unless the matrix is marked as SPD or symmetric 1278 (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`). 1279 1280 References: 1281 . * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version 1282 1283 .seealso: [](chapter_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()` 1284 @*/ 1285 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer) 1286 { 1287 PetscBool flg; 1288 1289 PetscFunctionBegin; 1290 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1291 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1292 1293 if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ)); 1294 1295 flg = PETSC_FALSE; 1296 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL)); 1297 if (flg) { 1298 PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE)); 1299 PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE)); 1300 } 1301 flg = PETSC_FALSE; 1302 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL)); 1303 if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE)); 1304 1305 PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0)); 1306 PetscUseTypeMethod(mat, load, viewer); 1307 PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0)); 1308 PetscFunctionReturn(PETSC_SUCCESS); 1309 } 1310 1311 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant) 1312 { 1313 Mat_Redundant *redund = *redundant; 1314 1315 PetscFunctionBegin; 1316 if (redund) { 1317 if (redund->matseq) { /* via MatCreateSubMatrices() */ 1318 PetscCall(ISDestroy(&redund->isrow)); 1319 PetscCall(ISDestroy(&redund->iscol)); 1320 PetscCall(MatDestroySubMatrices(1, &redund->matseq)); 1321 } else { 1322 PetscCall(PetscFree2(redund->send_rank, redund->recv_rank)); 1323 PetscCall(PetscFree(redund->sbuf_j)); 1324 PetscCall(PetscFree(redund->sbuf_a)); 1325 for (PetscInt i = 0; i < redund->nrecvs; i++) { 1326 PetscCall(PetscFree(redund->rbuf_j[i])); 1327 PetscCall(PetscFree(redund->rbuf_a[i])); 1328 } 1329 PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a)); 1330 } 1331 1332 if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm)); 1333 PetscCall(PetscFree(redund)); 1334 } 1335 PetscFunctionReturn(PETSC_SUCCESS); 1336 } 1337 1338 /*@C 1339 MatDestroy - Frees space taken by a matrix. 1340 1341 Collective 1342 1343 Input Parameter: 1344 . A - the matrix 1345 1346 Level: beginner 1347 1348 Developer Note: 1349 Some special arrays of matrices are not destroyed in this routine but instead by the routines called by 1350 `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines. 1351 `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes 1352 if changes are needed here. 1353 1354 .seealso: [](chapter_matrices), `Mat`, `MatCreate()` 1355 @*/ 1356 PetscErrorCode MatDestroy(Mat *A) 1357 { 1358 PetscFunctionBegin; 1359 if (!*A) PetscFunctionReturn(PETSC_SUCCESS); 1360 PetscValidHeaderSpecific(*A, MAT_CLASSID, 1); 1361 if (--((PetscObject)(*A))->refct > 0) { 1362 *A = NULL; 1363 PetscFunctionReturn(PETSC_SUCCESS); 1364 } 1365 1366 /* if memory was published with SAWs then destroy it */ 1367 PetscCall(PetscObjectSAWsViewOff((PetscObject)*A)); 1368 PetscTryTypeMethod((*A), destroy); 1369 1370 PetscCall(PetscFree((*A)->factorprefix)); 1371 PetscCall(PetscFree((*A)->defaultvectype)); 1372 PetscCall(PetscFree((*A)->defaultrandtype)); 1373 PetscCall(PetscFree((*A)->bsizes)); 1374 PetscCall(PetscFree((*A)->solvertype)); 1375 for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i])); 1376 if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL; 1377 PetscCall(MatDestroy_Redundant(&(*A)->redundant)); 1378 PetscCall(MatProductClear(*A)); 1379 PetscCall(MatNullSpaceDestroy(&(*A)->nullsp)); 1380 PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp)); 1381 PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp)); 1382 PetscCall(MatDestroy(&(*A)->schur)); 1383 PetscCall(PetscLayoutDestroy(&(*A)->rmap)); 1384 PetscCall(PetscLayoutDestroy(&(*A)->cmap)); 1385 PetscCall(PetscHeaderDestroy(A)); 1386 PetscFunctionReturn(PETSC_SUCCESS); 1387 } 1388 1389 /*@C 1390 MatSetValues - Inserts or adds a block of values into a matrix. 1391 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1392 MUST be called after all calls to `MatSetValues()` have been completed. 1393 1394 Not Collective 1395 1396 Input Parameters: 1397 + mat - the matrix 1398 . v - a logically two-dimensional array of values 1399 . m - the number of rows 1400 . idxm - the global indices of the rows 1401 . n - the number of columns 1402 . idxn - the global indices of the columns 1403 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1404 1405 Level: beginner 1406 1407 Notes: 1408 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1409 1410 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1411 options cannot be mixed without intervening calls to the assembly 1412 routines. 1413 1414 `MatSetValues()` uses 0-based row and column numbers in Fortran 1415 as well as in C. 1416 1417 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1418 simply ignored. This allows easily inserting element stiffness matrices 1419 with homogeneous Dirchlet boundary conditions that you don't want represented 1420 in the matrix. 1421 1422 Efficiency Alert: 1423 The routine `MatSetValuesBlocked()` may offer much better efficiency 1424 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1425 1426 Developer Note: 1427 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1428 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1429 1430 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1431 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1432 @*/ 1433 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1434 { 1435 PetscFunctionBeginHot; 1436 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1437 PetscValidType(mat, 1); 1438 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1439 PetscValidIntPointer(idxm, 3); 1440 PetscValidIntPointer(idxn, 5); 1441 MatCheckPreallocated(mat, 1); 1442 1443 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1444 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1445 1446 if (PetscDefined(USE_DEBUG)) { 1447 PetscInt i, j; 1448 1449 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1450 for (i = 0; i < m; i++) { 1451 for (j = 0; j < n; j++) { 1452 if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j])) 1453 #if defined(PETSC_USE_COMPLEX) 1454 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]); 1455 #else 1456 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]); 1457 #endif 1458 } 1459 } 1460 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); 1461 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); 1462 } 1463 1464 if (mat->assembled) { 1465 mat->was_assembled = PETSC_TRUE; 1466 mat->assembled = PETSC_FALSE; 1467 } 1468 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1469 PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv); 1470 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1471 PetscFunctionReturn(PETSC_SUCCESS); 1472 } 1473 1474 /*@C 1475 MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns 1476 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1477 MUST be called after all calls to `MatSetValues()` have been completed. 1478 1479 Not Collective 1480 1481 Input Parameters: 1482 + mat - the matrix 1483 . v - a logically two-dimensional array of values 1484 . ism - the rows to provide 1485 . isn - the columns to provide 1486 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1487 1488 Level: beginner 1489 1490 Notes: 1491 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1492 1493 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1494 options cannot be mixed without intervening calls to the assembly 1495 routines. 1496 1497 `MatSetValues()` uses 0-based row and column numbers in Fortran 1498 as well as in C. 1499 1500 Negative indices may be passed in `ism` and `isn`, these rows and columns are 1501 simply ignored. This allows easily inserting element stiffness matrices 1502 with homogeneous Dirchlet boundary conditions that you don't want represented 1503 in the matrix. 1504 1505 Efficiency Alert: 1506 The routine `MatSetValuesBlocked()` may offer much better efficiency 1507 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1508 1509 This is currently not optimized for any particular `ISType` 1510 1511 Developer Notes: 1512 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1513 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1514 1515 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1516 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()` 1517 @*/ 1518 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv) 1519 { 1520 PetscInt m, n; 1521 const PetscInt *rows, *cols; 1522 1523 PetscFunctionBeginHot; 1524 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1525 PetscCall(ISGetIndices(ism, &rows)); 1526 PetscCall(ISGetIndices(isn, &cols)); 1527 PetscCall(ISGetLocalSize(ism, &m)); 1528 PetscCall(ISGetLocalSize(isn, &n)); 1529 PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv)); 1530 PetscCall(ISRestoreIndices(ism, &rows)); 1531 PetscCall(ISRestoreIndices(isn, &cols)); 1532 PetscFunctionReturn(PETSC_SUCCESS); 1533 } 1534 1535 /*@ 1536 MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1537 values into a matrix 1538 1539 Not Collective 1540 1541 Input Parameters: 1542 + mat - the matrix 1543 . row - the (block) row to set 1544 - v - a logically two-dimensional array of values 1545 1546 Level: intermediate 1547 1548 Notes: 1549 The values, `v`, are column-oriented (for the block version) and sorted 1550 1551 All the nonzeros in the row must be provided 1552 1553 The matrix must have previously had its column indices set, likely by having been assembled. 1554 1555 The row must belong to this process 1556 1557 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1558 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()` 1559 @*/ 1560 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[]) 1561 { 1562 PetscInt globalrow; 1563 1564 PetscFunctionBegin; 1565 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1566 PetscValidType(mat, 1); 1567 PetscValidScalarPointer(v, 3); 1568 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow)); 1569 PetscCall(MatSetValuesRow(mat, globalrow, v)); 1570 PetscFunctionReturn(PETSC_SUCCESS); 1571 } 1572 1573 /*@ 1574 MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1575 values into a matrix 1576 1577 Not Collective 1578 1579 Input Parameters: 1580 + mat - the matrix 1581 . row - the (block) row to set 1582 - 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 1583 1584 Level: advanced 1585 1586 Notes: 1587 The values, `v`, are column-oriented for the block version. 1588 1589 All the nonzeros in the row must be provided 1590 1591 THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used. 1592 1593 The row must belong to this process 1594 1595 .seealso: [](chapter_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1596 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()` 1597 @*/ 1598 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[]) 1599 { 1600 PetscFunctionBeginHot; 1601 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1602 PetscValidType(mat, 1); 1603 MatCheckPreallocated(mat, 1); 1604 PetscValidScalarPointer(v, 3); 1605 PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values"); 1606 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1607 mat->insertmode = INSERT_VALUES; 1608 1609 if (mat->assembled) { 1610 mat->was_assembled = PETSC_TRUE; 1611 mat->assembled = PETSC_FALSE; 1612 } 1613 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1614 PetscUseTypeMethod(mat, setvaluesrow, row, v); 1615 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1616 PetscFunctionReturn(PETSC_SUCCESS); 1617 } 1618 1619 /*@ 1620 MatSetValuesStencil - Inserts or adds a block of values into a matrix. 1621 Using structured grid indexing 1622 1623 Not Collective 1624 1625 Input Parameters: 1626 + mat - the matrix 1627 . m - number of rows being entered 1628 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered 1629 . n - number of columns being entered 1630 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered 1631 . v - a logically two-dimensional array of values 1632 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values 1633 1634 Level: beginner 1635 1636 Notes: 1637 By default the values, `v`, are row-oriented. See `MatSetOption()` for other options. 1638 1639 Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1640 options cannot be mixed without intervening calls to the assembly 1641 routines. 1642 1643 The grid coordinates are across the entire grid, not just the local portion 1644 1645 `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran 1646 as well as in C. 1647 1648 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1649 1650 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1651 or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1652 1653 The columns and rows in the stencil passed in MUST be contained within the 1654 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1655 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1656 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1657 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1658 1659 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 1660 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 1661 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 1662 `DM_BOUNDARY_PERIODIC` boundary type. 1663 1664 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 1665 a single value per point) you can skip filling those indices. 1666 1667 Inspired by the structured grid interface to the HYPRE package 1668 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1669 1670 Efficiency Alert: 1671 The routine `MatSetValuesBlockedStencil()` may offer much better efficiency 1672 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1673 1674 Fortran Note: 1675 `idxm` and `idxn` should be declared as 1676 $ MatStencil idxm(4,m),idxn(4,n) 1677 and the values inserted using 1678 .vb 1679 idxm(MatStencil_i,1) = i 1680 idxm(MatStencil_j,1) = j 1681 idxm(MatStencil_k,1) = k 1682 idxm(MatStencil_c,1) = c 1683 etc 1684 .ve 1685 1686 .seealso: [](chapter_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1687 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil` 1688 @*/ 1689 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1690 { 1691 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1692 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1693 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1694 1695 PetscFunctionBegin; 1696 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1697 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1698 PetscValidType(mat, 1); 1699 PetscValidPointer(idxm, 3); 1700 PetscValidPointer(idxn, 5); 1701 1702 if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 1703 jdxm = buf; 1704 jdxn = buf + m; 1705 } else { 1706 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1707 jdxm = bufm; 1708 jdxn = bufn; 1709 } 1710 for (i = 0; i < m; i++) { 1711 for (j = 0; j < 3 - sdim; j++) dxm++; 1712 tmp = *dxm++ - starts[0]; 1713 for (j = 0; j < dim - 1; j++) { 1714 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1715 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1716 } 1717 if (mat->stencil.noc) dxm++; 1718 jdxm[i] = tmp; 1719 } 1720 for (i = 0; i < n; i++) { 1721 for (j = 0; j < 3 - sdim; j++) dxn++; 1722 tmp = *dxn++ - starts[0]; 1723 for (j = 0; j < dim - 1; j++) { 1724 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1725 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1726 } 1727 if (mat->stencil.noc) dxn++; 1728 jdxn[i] = tmp; 1729 } 1730 PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv)); 1731 PetscCall(PetscFree2(bufm, bufn)); 1732 PetscFunctionReturn(PETSC_SUCCESS); 1733 } 1734 1735 /*@ 1736 MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix. 1737 Using structured grid indexing 1738 1739 Not Collective 1740 1741 Input Parameters: 1742 + mat - the matrix 1743 . m - number of rows being entered 1744 . idxm - grid coordinates for matrix rows being entered 1745 . n - number of columns being entered 1746 . idxn - grid coordinates for matrix columns being entered 1747 . v - a logically two-dimensional array of values 1748 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values 1749 1750 Level: beginner 1751 1752 Notes: 1753 By default the values, `v`, are row-oriented and unsorted. 1754 See `MatSetOption()` for other options. 1755 1756 Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1757 options cannot be mixed without intervening calls to the assembly 1758 routines. 1759 1760 The grid coordinates are across the entire grid, not just the local portion 1761 1762 `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran 1763 as well as in C. 1764 1765 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1766 1767 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1768 or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1769 1770 The columns and rows in the stencil passed in MUST be contained within the 1771 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1772 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1773 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1774 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1775 1776 Negative indices may be passed in idxm and idxn, these rows and columns are 1777 simply ignored. This allows easily inserting element stiffness matrices 1778 with homogeneous Dirchlet boundary conditions that you don't want represented 1779 in the matrix. 1780 1781 Inspired by the structured grid interface to the HYPRE package 1782 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1783 1784 Fortran Note: 1785 `idxm` and `idxn` should be declared as 1786 $ MatStencil idxm(4,m),idxn(4,n) 1787 and the values inserted using 1788 .vb 1789 idxm(MatStencil_i,1) = i 1790 idxm(MatStencil_j,1) = j 1791 idxm(MatStencil_k,1) = k 1792 etc 1793 .ve 1794 1795 .seealso: [](chapter_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1796 `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`, 1797 `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` 1798 @*/ 1799 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1800 { 1801 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1802 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1803 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1804 1805 PetscFunctionBegin; 1806 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1807 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1808 PetscValidType(mat, 1); 1809 PetscValidPointer(idxm, 3); 1810 PetscValidPointer(idxn, 5); 1811 PetscValidScalarPointer(v, 6); 1812 1813 if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 1814 jdxm = buf; 1815 jdxn = buf + m; 1816 } else { 1817 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1818 jdxm = bufm; 1819 jdxn = bufn; 1820 } 1821 for (i = 0; i < m; i++) { 1822 for (j = 0; j < 3 - sdim; j++) dxm++; 1823 tmp = *dxm++ - starts[0]; 1824 for (j = 0; j < sdim - 1; j++) { 1825 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1826 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1827 } 1828 dxm++; 1829 jdxm[i] = tmp; 1830 } 1831 for (i = 0; i < n; i++) { 1832 for (j = 0; j < 3 - sdim; j++) dxn++; 1833 tmp = *dxn++ - starts[0]; 1834 for (j = 0; j < sdim - 1; j++) { 1835 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1836 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1837 } 1838 dxn++; 1839 jdxn[i] = tmp; 1840 } 1841 PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv)); 1842 PetscCall(PetscFree2(bufm, bufn)); 1843 PetscFunctionReturn(PETSC_SUCCESS); 1844 } 1845 1846 /*@ 1847 MatSetStencil - Sets the grid information for setting values into a matrix via 1848 `MatSetValuesStencil()` 1849 1850 Not Collective 1851 1852 Input Parameters: 1853 + mat - the matrix 1854 . dim - dimension of the grid 1, 2, or 3 1855 . dims - number of grid points in x, y, and z direction, including ghost points on your processor 1856 . starts - starting point of ghost nodes on your processor in x, y, and z direction 1857 - dof - number of degrees of freedom per node 1858 1859 Level: beginner 1860 1861 Notes: 1862 Inspired by the structured grid interface to the HYPRE package 1863 (www.llnl.gov/CASC/hyper) 1864 1865 For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the 1866 user. 1867 1868 .seealso: [](chapter_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1869 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()` 1870 @*/ 1871 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof) 1872 { 1873 PetscFunctionBegin; 1874 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1875 PetscValidIntPointer(dims, 3); 1876 PetscValidIntPointer(starts, 4); 1877 1878 mat->stencil.dim = dim + (dof > 1); 1879 for (PetscInt i = 0; i < dim; i++) { 1880 mat->stencil.dims[i] = dims[dim - i - 1]; /* copy the values in backwards */ 1881 mat->stencil.starts[i] = starts[dim - i - 1]; 1882 } 1883 mat->stencil.dims[dim] = dof; 1884 mat->stencil.starts[dim] = 0; 1885 mat->stencil.noc = (PetscBool)(dof == 1); 1886 PetscFunctionReturn(PETSC_SUCCESS); 1887 } 1888 1889 /*@C 1890 MatSetValuesBlocked - Inserts or adds a block of values into a matrix. 1891 1892 Not Collective 1893 1894 Input Parameters: 1895 + mat - the matrix 1896 . v - a logically two-dimensional array of values 1897 . m - the number of block rows 1898 . idxm - the global block indices 1899 . n - the number of block columns 1900 . idxn - the global block indices 1901 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values 1902 1903 Level: intermediate 1904 1905 Notes: 1906 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call 1907 MatXXXXSetPreallocation() or `MatSetUp()` before using this routine. 1908 1909 The `m` and `n` count the NUMBER of blocks in the row direction and column direction, 1910 NOT the total number of rows/columns; for example, if the block size is 2 and 1911 you are passing in values for rows 2,3,4,5 then m would be 2 (not 4). 1912 The values in idxm would be 1 2; that is the first index for each block divided by 1913 the block size. 1914 1915 You must call `MatSetBlockSize()` when constructing this matrix (before 1916 preallocating it). 1917 1918 By default the values, `v`, are row-oriented, so the layout of 1919 `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options. 1920 1921 Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES` 1922 options cannot be mixed without intervening calls to the assembly 1923 routines. 1924 1925 `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran 1926 as well as in C. 1927 1928 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1929 simply ignored. This allows easily inserting element stiffness matrices 1930 with homogeneous Dirchlet boundary conditions that you don't want represented 1931 in the matrix. 1932 1933 Each time an entry is set within a sparse matrix via `MatSetValues()`, 1934 internal searching must be done to determine where to place the 1935 data in the matrix storage space. By instead inserting blocks of 1936 entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is 1937 reduced. 1938 1939 Example: 1940 .vb 1941 Suppose m=n=2 and block size(bs) = 2 The array is 1942 1943 1 2 | 3 4 1944 5 6 | 7 8 1945 - - - | - - - 1946 9 10 | 11 12 1947 13 14 | 15 16 1948 1949 v[] should be passed in like 1950 v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] 1951 1952 If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then 1953 v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16] 1954 .ve 1955 1956 .seealso: [](chapter_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()` 1957 @*/ 1958 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1959 { 1960 PetscFunctionBeginHot; 1961 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1962 PetscValidType(mat, 1); 1963 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1964 PetscValidIntPointer(idxm, 3); 1965 PetscValidIntPointer(idxn, 5); 1966 MatCheckPreallocated(mat, 1); 1967 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1968 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1969 if (PetscDefined(USE_DEBUG)) { 1970 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1971 PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 1972 } 1973 if (PetscDefined(USE_DEBUG)) { 1974 PetscInt rbs, cbs, M, N, i; 1975 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1976 PetscCall(MatGetSize(mat, &M, &N)); 1977 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); 1978 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); 1979 } 1980 if (mat->assembled) { 1981 mat->was_assembled = PETSC_TRUE; 1982 mat->assembled = PETSC_FALSE; 1983 } 1984 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1985 if (mat->ops->setvaluesblocked) { 1986 PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv); 1987 } else { 1988 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn; 1989 PetscInt i, j, bs, cbs; 1990 1991 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 1992 if (m * bs + n * cbs <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 1993 iidxm = buf; 1994 iidxn = buf + m * bs; 1995 } else { 1996 PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc)); 1997 iidxm = bufr; 1998 iidxn = bufc; 1999 } 2000 for (i = 0; i < m; i++) { 2001 for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j; 2002 } 2003 if (m != n || bs != cbs || idxm != idxn) { 2004 for (i = 0; i < n; i++) { 2005 for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j; 2006 } 2007 } else iidxn = iidxm; 2008 PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv)); 2009 PetscCall(PetscFree2(bufr, bufc)); 2010 } 2011 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2012 PetscFunctionReturn(PETSC_SUCCESS); 2013 } 2014 2015 /*@C 2016 MatGetValues - Gets a block of local values from a matrix. 2017 2018 Not Collective; can only return values that are owned by the give process 2019 2020 Input Parameters: 2021 + mat - the matrix 2022 . v - a logically two-dimensional array for storing the values 2023 . m - the number of rows 2024 . idxm - the global indices of the rows 2025 . n - the number of columns 2026 - idxn - the global indices of the columns 2027 2028 Level: advanced 2029 2030 Notes: 2031 The user must allocate space (m*n `PetscScalar`s) for the values, `v`. 2032 The values, `v`, are then returned in a row-oriented format, 2033 analogous to that used by default in `MatSetValues()`. 2034 2035 `MatGetValues()` uses 0-based row and column numbers in 2036 Fortran as well as in C. 2037 2038 `MatGetValues()` requires that the matrix has been assembled 2039 with `MatAssemblyBegin()`/`MatAssemblyEnd()`. Thus, calls to 2040 `MatSetValues()` and `MatGetValues()` CANNOT be made in succession 2041 without intermediate matrix assembly. 2042 2043 Negative row or column indices will be ignored and those locations in `v` will be 2044 left unchanged. 2045 2046 For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI rank. 2047 That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable 2048 from `MatGetOwnershipRange`(mat,&rstart,&rend). 2049 2050 .seealso: [](chapter_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()` 2051 @*/ 2052 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) 2053 { 2054 PetscFunctionBegin; 2055 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2056 PetscValidType(mat, 1); 2057 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); 2058 PetscValidIntPointer(idxm, 3); 2059 PetscValidIntPointer(idxn, 5); 2060 PetscValidScalarPointer(v, 6); 2061 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2062 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2063 MatCheckPreallocated(mat, 1); 2064 2065 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2066 PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v); 2067 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2068 PetscFunctionReturn(PETSC_SUCCESS); 2069 } 2070 2071 /*@C 2072 MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices 2073 defined previously by `MatSetLocalToGlobalMapping()` 2074 2075 Not Collective 2076 2077 Input Parameters: 2078 + mat - the matrix 2079 . nrow - number of rows 2080 . irow - the row local indices 2081 . ncol - number of columns 2082 - icol - the column local indices 2083 2084 Output Parameter: 2085 . y - a logically two-dimensional array of values 2086 2087 Level: advanced 2088 2089 Notes: 2090 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine. 2091 2092 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, 2093 are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can 2094 determine if the resulting global row associated with the local row r is owned by the requesting MPI rank by applying the `ISLocalToGlobalMapping` set 2095 with `MatSetLocalToGlobalMapping()`. 2096 2097 Developer Note: 2098 This is labelled with C so does not automatically generate Fortran stubs and interfaces 2099 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2100 2101 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2102 `MatSetValuesLocal()`, `MatGetValues()` 2103 @*/ 2104 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[]) 2105 { 2106 PetscFunctionBeginHot; 2107 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2108 PetscValidType(mat, 1); 2109 MatCheckPreallocated(mat, 1); 2110 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */ 2111 PetscValidIntPointer(irow, 3); 2112 PetscValidIntPointer(icol, 5); 2113 if (PetscDefined(USE_DEBUG)) { 2114 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2115 PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2116 } 2117 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2118 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2119 if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y); 2120 else { 2121 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm; 2122 if ((nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2123 irowm = buf; 2124 icolm = buf + nrow; 2125 } else { 2126 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2127 irowm = bufr; 2128 icolm = bufc; 2129 } 2130 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping())."); 2131 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping())."); 2132 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm)); 2133 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm)); 2134 PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y)); 2135 PetscCall(PetscFree2(bufr, bufc)); 2136 } 2137 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2138 PetscFunctionReturn(PETSC_SUCCESS); 2139 } 2140 2141 /*@ 2142 MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and 2143 the same size. Currently, this can only be called once and creates the given matrix. 2144 2145 Not Collective 2146 2147 Input Parameters: 2148 + mat - the matrix 2149 . nb - the number of blocks 2150 . bs - the number of rows (and columns) in each block 2151 . rows - a concatenation of the rows for each block 2152 - v - a concatenation of logically two-dimensional arrays of values 2153 2154 Level: advanced 2155 2156 Note: 2157 `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values 2158 2159 In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix. 2160 2161 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 2162 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()` 2163 @*/ 2164 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[]) 2165 { 2166 PetscFunctionBegin; 2167 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2168 PetscValidType(mat, 1); 2169 PetscValidIntPointer(rows, 4); 2170 PetscValidScalarPointer(v, 5); 2171 PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2172 2173 PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0)); 2174 if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v); 2175 else { 2176 for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES)); 2177 } 2178 PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0)); 2179 PetscFunctionReturn(PETSC_SUCCESS); 2180 } 2181 2182 /*@ 2183 MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by 2184 the routine `MatSetValuesLocal()` to allow users to insert matrix entries 2185 using a local (per-processor) numbering. 2186 2187 Not Collective 2188 2189 Input Parameters: 2190 + x - the matrix 2191 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()` 2192 - cmapping - column mapping 2193 2194 Level: intermediate 2195 2196 Note: 2197 If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix 2198 2199 .seealso: [](chapter_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()` 2200 @*/ 2201 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping) 2202 { 2203 PetscFunctionBegin; 2204 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 2205 PetscValidType(x, 1); 2206 if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2); 2207 if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3); 2208 if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping); 2209 else { 2210 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping)); 2211 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping)); 2212 } 2213 PetscFunctionReturn(PETSC_SUCCESS); 2214 } 2215 2216 /*@ 2217 MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()` 2218 2219 Not Collective 2220 2221 Input Parameter: 2222 . A - the matrix 2223 2224 Output Parameters: 2225 + rmapping - row mapping 2226 - cmapping - column mapping 2227 2228 Level: advanced 2229 2230 .seealso: [](chapter_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()` 2231 @*/ 2232 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping) 2233 { 2234 PetscFunctionBegin; 2235 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2236 PetscValidType(A, 1); 2237 if (rmapping) { 2238 PetscValidPointer(rmapping, 2); 2239 *rmapping = A->rmap->mapping; 2240 } 2241 if (cmapping) { 2242 PetscValidPointer(cmapping, 3); 2243 *cmapping = A->cmap->mapping; 2244 } 2245 PetscFunctionReturn(PETSC_SUCCESS); 2246 } 2247 2248 /*@ 2249 MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix 2250 2251 Logically Collective 2252 2253 Input Parameters: 2254 + A - the matrix 2255 . rmap - row layout 2256 - cmap - column layout 2257 2258 Level: advanced 2259 2260 Note: 2261 The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called. 2262 2263 .seealso: [](chapter_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()` 2264 @*/ 2265 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap) 2266 { 2267 PetscFunctionBegin; 2268 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2269 PetscCall(PetscLayoutReference(rmap, &A->rmap)); 2270 PetscCall(PetscLayoutReference(cmap, &A->cmap)); 2271 PetscFunctionReturn(PETSC_SUCCESS); 2272 } 2273 2274 /*@ 2275 MatGetLayouts - Gets the `PetscLayout` objects for rows and columns 2276 2277 Not Collective 2278 2279 Input Parameter: 2280 . A - the matrix 2281 2282 Output Parameters: 2283 + rmap - row layout 2284 - cmap - column layout 2285 2286 Level: advanced 2287 2288 .seealso: [](chapter_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()` 2289 @*/ 2290 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap) 2291 { 2292 PetscFunctionBegin; 2293 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2294 PetscValidType(A, 1); 2295 if (rmap) { 2296 PetscValidPointer(rmap, 2); 2297 *rmap = A->rmap; 2298 } 2299 if (cmap) { 2300 PetscValidPointer(cmap, 3); 2301 *cmap = A->cmap; 2302 } 2303 PetscFunctionReturn(PETSC_SUCCESS); 2304 } 2305 2306 /*@C 2307 MatSetValuesLocal - Inserts or adds values into certain locations of a matrix, 2308 using a local numbering of the nodes. 2309 2310 Not Collective 2311 2312 Input Parameters: 2313 + mat - the matrix 2314 . nrow - number of rows 2315 . irow - the row local indices 2316 . ncol - number of columns 2317 . icol - the column local indices 2318 . y - a logically two-dimensional array of values 2319 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2320 2321 Level: intermediate 2322 2323 Notes: 2324 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 2325 `MatSetUp()` before using this routine 2326 2327 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine 2328 2329 Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2330 options cannot be mixed without intervening calls to the assembly 2331 routines. 2332 2333 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2334 MUST be called after all calls to `MatSetValuesLocal()` have been completed. 2335 2336 Developer Note: 2337 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2338 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2339 2340 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2341 `MatGetValuesLocal()` 2342 @*/ 2343 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2344 { 2345 PetscFunctionBeginHot; 2346 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2347 PetscValidType(mat, 1); 2348 MatCheckPreallocated(mat, 1); 2349 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2350 PetscValidIntPointer(irow, 3); 2351 PetscValidIntPointer(icol, 5); 2352 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2353 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2354 if (PetscDefined(USE_DEBUG)) { 2355 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2356 PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2357 } 2358 2359 if (mat->assembled) { 2360 mat->was_assembled = PETSC_TRUE; 2361 mat->assembled = PETSC_FALSE; 2362 } 2363 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2364 if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv); 2365 else { 2366 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2367 const PetscInt *irowm, *icolm; 2368 2369 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2370 bufr = buf; 2371 bufc = buf + nrow; 2372 irowm = bufr; 2373 icolm = bufc; 2374 } else { 2375 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2376 irowm = bufr; 2377 icolm = bufc; 2378 } 2379 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr)); 2380 else irowm = irow; 2381 if (mat->cmap->mapping) { 2382 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2383 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc)); 2384 } else icolm = irowm; 2385 } else icolm = icol; 2386 PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv)); 2387 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2388 } 2389 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2390 PetscFunctionReturn(PETSC_SUCCESS); 2391 } 2392 2393 /*@C 2394 MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix, 2395 using a local ordering of the nodes a block at a time. 2396 2397 Not Collective 2398 2399 Input Parameters: 2400 + x - the matrix 2401 . nrow - number of rows 2402 . irow - the row local indices 2403 . ncol - number of columns 2404 . icol - the column local indices 2405 . y - a logically two-dimensional array of values 2406 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2407 2408 Level: intermediate 2409 2410 Notes: 2411 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 2412 `MatSetUp()` before using this routine 2413 2414 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()` 2415 before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the 2416 2417 Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2418 options cannot be mixed without intervening calls to the assembly 2419 routines. 2420 2421 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2422 MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed. 2423 2424 Developer Note: 2425 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2426 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2427 2428 .seealso: [](chapter_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, 2429 `MatSetValuesLocal()`, `MatSetValuesBlocked()` 2430 @*/ 2431 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2432 { 2433 PetscFunctionBeginHot; 2434 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2435 PetscValidType(mat, 1); 2436 MatCheckPreallocated(mat, 1); 2437 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2438 PetscValidIntPointer(irow, 3); 2439 PetscValidIntPointer(icol, 5); 2440 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2441 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2442 if (PetscDefined(USE_DEBUG)) { 2443 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2444 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); 2445 } 2446 2447 if (mat->assembled) { 2448 mat->was_assembled = PETSC_TRUE; 2449 mat->assembled = PETSC_FALSE; 2450 } 2451 if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */ 2452 PetscInt irbs, rbs; 2453 PetscCall(MatGetBlockSizes(mat, &rbs, NULL)); 2454 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs)); 2455 PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs); 2456 } 2457 if (PetscUnlikelyDebug(mat->cmap->mapping)) { 2458 PetscInt icbs, cbs; 2459 PetscCall(MatGetBlockSizes(mat, NULL, &cbs)); 2460 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs)); 2461 PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs); 2462 } 2463 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2464 if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv); 2465 else { 2466 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2467 const PetscInt *irowm, *icolm; 2468 2469 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2470 bufr = buf; 2471 bufc = buf + nrow; 2472 irowm = bufr; 2473 icolm = bufc; 2474 } else { 2475 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2476 irowm = bufr; 2477 icolm = bufc; 2478 } 2479 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr)); 2480 else irowm = irow; 2481 if (mat->cmap->mapping) { 2482 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2483 PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc)); 2484 } else icolm = irowm; 2485 } else icolm = icol; 2486 PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv)); 2487 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2488 } 2489 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2490 PetscFunctionReturn(PETSC_SUCCESS); 2491 } 2492 2493 /*@ 2494 MatMultDiagonalBlock - Computes the matrix-vector product, y = Dx. Where D is defined by the inode or block structure of the diagonal 2495 2496 Collective 2497 2498 Input Parameters: 2499 + mat - the matrix 2500 - x - the vector to be multiplied 2501 2502 Output Parameter: 2503 . y - the result 2504 2505 Level: developer 2506 2507 Note: 2508 The vectors `x` and `y` cannot be the same. I.e., one cannot 2509 call `MatMultDiagonalBlock`(A,y,y). 2510 2511 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2512 @*/ 2513 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y) 2514 { 2515 PetscFunctionBegin; 2516 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2517 PetscValidType(mat, 1); 2518 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2519 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2520 2521 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2522 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2523 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2524 MatCheckPreallocated(mat, 1); 2525 2526 PetscUseTypeMethod(mat, multdiagonalblock, x, y); 2527 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2528 PetscFunctionReturn(PETSC_SUCCESS); 2529 } 2530 2531 /*@ 2532 MatMult - Computes the matrix-vector product, y = Ax. 2533 2534 Neighbor-wise Collective 2535 2536 Input Parameters: 2537 + mat - the matrix 2538 - x - the vector to be multiplied 2539 2540 Output Parameter: 2541 . y - the result 2542 2543 Level: beginner 2544 2545 Note: 2546 The vectors `x` and `y` cannot be the same. I.e., one cannot 2547 call `MatMult`(A,y,y). 2548 2549 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2550 @*/ 2551 PetscErrorCode MatMult(Mat mat, Vec x, Vec y) 2552 { 2553 PetscFunctionBegin; 2554 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2555 PetscValidType(mat, 1); 2556 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2557 VecCheckAssembled(x); 2558 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2559 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2560 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2561 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2562 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); 2563 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); 2564 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); 2565 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); 2566 PetscCall(VecSetErrorIfLocked(y, 3)); 2567 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2568 MatCheckPreallocated(mat, 1); 2569 2570 PetscCall(VecLockReadPush(x)); 2571 PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0)); 2572 PetscUseTypeMethod(mat, mult, x, y); 2573 PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0)); 2574 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2575 PetscCall(VecLockReadPop(x)); 2576 PetscFunctionReturn(PETSC_SUCCESS); 2577 } 2578 2579 /*@ 2580 MatMultTranspose - Computes matrix transpose times a vector y = A^T * x. 2581 2582 Neighbor-wise Collective 2583 2584 Input Parameters: 2585 + mat - the matrix 2586 - x - the vector to be multiplied 2587 2588 Output Parameter: 2589 . y - the result 2590 2591 Level: beginner 2592 2593 Notes: 2594 The vectors `x` and `y` cannot be the same. I.e., one cannot 2595 call `MatMultTranspose`(A,y,y). 2596 2597 For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple, 2598 use `MatMultHermitianTranspose()` 2599 2600 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()` 2601 @*/ 2602 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y) 2603 { 2604 PetscErrorCode (*op)(Mat, Vec, Vec) = NULL; 2605 2606 PetscFunctionBegin; 2607 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2608 PetscValidType(mat, 1); 2609 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2610 VecCheckAssembled(x); 2611 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2612 2613 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2614 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2615 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2616 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); 2617 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); 2618 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); 2619 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); 2620 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2621 MatCheckPreallocated(mat, 1); 2622 2623 if (!mat->ops->multtranspose) { 2624 if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult; 2625 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); 2626 } else op = mat->ops->multtranspose; 2627 PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0)); 2628 PetscCall(VecLockReadPush(x)); 2629 PetscCall((*op)(mat, x, y)); 2630 PetscCall(VecLockReadPop(x)); 2631 PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0)); 2632 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2633 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2634 PetscFunctionReturn(PETSC_SUCCESS); 2635 } 2636 2637 /*@ 2638 MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector. 2639 2640 Neighbor-wise Collective 2641 2642 Input Parameters: 2643 + mat - the matrix 2644 - x - the vector to be multilplied 2645 2646 Output Parameter: 2647 . y - the result 2648 2649 Level: beginner 2650 2651 Notes: 2652 The vectors `x` and `y` cannot be the same. I.e., one cannot 2653 call `MatMultHermitianTranspose`(A,y,y). 2654 2655 Also called the conjugate transpose, complex conjugate transpose, or adjoint. 2656 2657 For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical. 2658 2659 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()` 2660 @*/ 2661 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y) 2662 { 2663 PetscFunctionBegin; 2664 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2665 PetscValidType(mat, 1); 2666 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2667 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2668 2669 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2670 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2671 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2672 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); 2673 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); 2674 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); 2675 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); 2676 MatCheckPreallocated(mat, 1); 2677 2678 PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0)); 2679 #if defined(PETSC_USE_COMPLEX) 2680 if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) { 2681 PetscCall(VecLockReadPush(x)); 2682 if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y); 2683 else PetscUseTypeMethod(mat, mult, x, y); 2684 PetscCall(VecLockReadPop(x)); 2685 } else { 2686 Vec w; 2687 PetscCall(VecDuplicate(x, &w)); 2688 PetscCall(VecCopy(x, w)); 2689 PetscCall(VecConjugate(w)); 2690 PetscCall(MatMultTranspose(mat, w, y)); 2691 PetscCall(VecDestroy(&w)); 2692 PetscCall(VecConjugate(y)); 2693 } 2694 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2695 #else 2696 PetscCall(MatMultTranspose(mat, x, y)); 2697 #endif 2698 PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0)); 2699 PetscFunctionReturn(PETSC_SUCCESS); 2700 } 2701 2702 /*@ 2703 MatMultAdd - Computes v3 = v2 + A * v1. 2704 2705 Neighbor-wise Collective 2706 2707 Input Parameters: 2708 + mat - the matrix 2709 . v1 - the vector to be multiplied by `mat` 2710 - v2 - the vector to be added to the result 2711 2712 Output Parameter: 2713 . v3 - the result 2714 2715 Level: beginner 2716 2717 Note: 2718 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2719 call `MatMultAdd`(A,v1,v2,v1). 2720 2721 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()` 2722 @*/ 2723 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2724 { 2725 PetscFunctionBegin; 2726 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2727 PetscValidType(mat, 1); 2728 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2729 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2730 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2731 2732 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2733 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2734 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); 2735 /* 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); 2736 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); */ 2737 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); 2738 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); 2739 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2740 MatCheckPreallocated(mat, 1); 2741 2742 PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3)); 2743 PetscCall(VecLockReadPush(v1)); 2744 PetscUseTypeMethod(mat, multadd, v1, v2, v3); 2745 PetscCall(VecLockReadPop(v1)); 2746 PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3)); 2747 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2748 PetscFunctionReturn(PETSC_SUCCESS); 2749 } 2750 2751 /*@ 2752 MatMultTransposeAdd - Computes v3 = v2 + A' * v1. 2753 2754 Neighbor-wise Collective 2755 2756 Input Parameters: 2757 + mat - the matrix 2758 . v1 - the vector to be multiplied by the transpose of the matrix 2759 - v2 - the vector to be added to the result 2760 2761 Output Parameter: 2762 . v3 - the result 2763 2764 Level: beginner 2765 2766 Note: 2767 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2768 call `MatMultTransposeAdd`(A,v1,v2,v1). 2769 2770 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2771 @*/ 2772 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2773 { 2774 PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd; 2775 2776 PetscFunctionBegin; 2777 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2778 PetscValidType(mat, 1); 2779 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2780 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2781 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2782 2783 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2784 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2785 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); 2786 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); 2787 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); 2788 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2789 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2790 MatCheckPreallocated(mat, 1); 2791 2792 PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2793 PetscCall(VecLockReadPush(v1)); 2794 PetscCall((*op)(mat, v1, v2, v3)); 2795 PetscCall(VecLockReadPop(v1)); 2796 PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2797 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2798 PetscFunctionReturn(PETSC_SUCCESS); 2799 } 2800 2801 /*@ 2802 MatMultHermitianTransposeAdd - Computes v3 = v2 + A^H * v1. 2803 2804 Neighbor-wise Collective 2805 2806 Input Parameters: 2807 + mat - the matrix 2808 . v1 - the vector to be multiplied by the Hermitian transpose 2809 - v2 - the vector to be added to the result 2810 2811 Output Parameter: 2812 . v3 - the result 2813 2814 Level: beginner 2815 2816 Note: 2817 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2818 call `MatMultHermitianTransposeAdd`(A,v1,v2,v1). 2819 2820 .seealso: [](chapter_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2821 @*/ 2822 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2823 { 2824 PetscFunctionBegin; 2825 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2826 PetscValidType(mat, 1); 2827 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2828 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2829 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2830 2831 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2832 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2833 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2834 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); 2835 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); 2836 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); 2837 MatCheckPreallocated(mat, 1); 2838 2839 PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2840 PetscCall(VecLockReadPush(v1)); 2841 if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3); 2842 else { 2843 Vec w, z; 2844 PetscCall(VecDuplicate(v1, &w)); 2845 PetscCall(VecCopy(v1, w)); 2846 PetscCall(VecConjugate(w)); 2847 PetscCall(VecDuplicate(v3, &z)); 2848 PetscCall(MatMultTranspose(mat, w, z)); 2849 PetscCall(VecDestroy(&w)); 2850 PetscCall(VecConjugate(z)); 2851 if (v2 != v3) { 2852 PetscCall(VecWAXPY(v3, 1.0, v2, z)); 2853 } else { 2854 PetscCall(VecAXPY(v3, 1.0, z)); 2855 } 2856 PetscCall(VecDestroy(&z)); 2857 } 2858 PetscCall(VecLockReadPop(v1)); 2859 PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2860 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2861 PetscFunctionReturn(PETSC_SUCCESS); 2862 } 2863 2864 /*@C 2865 MatGetFactorType - gets the type of factorization it is 2866 2867 Not Collective 2868 2869 Input Parameter: 2870 . mat - the matrix 2871 2872 Output Parameter: 2873 . 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` 2874 2875 Level: intermediate 2876 2877 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2878 `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2879 @*/ 2880 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t) 2881 { 2882 PetscFunctionBegin; 2883 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2884 PetscValidType(mat, 1); 2885 PetscValidPointer(t, 2); 2886 *t = mat->factortype; 2887 PetscFunctionReturn(PETSC_SUCCESS); 2888 } 2889 2890 /*@C 2891 MatSetFactorType - sets the type of factorization it is 2892 2893 Logically Collective 2894 2895 Input Parameters: 2896 + mat - the matrix 2897 - 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` 2898 2899 Level: intermediate 2900 2901 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2902 `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2903 @*/ 2904 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t) 2905 { 2906 PetscFunctionBegin; 2907 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2908 PetscValidType(mat, 1); 2909 mat->factortype = t; 2910 PetscFunctionReturn(PETSC_SUCCESS); 2911 } 2912 2913 /*@C 2914 MatGetInfo - Returns information about matrix storage (number of 2915 nonzeros, memory, etc.). 2916 2917 Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag 2918 2919 Input Parameters: 2920 + mat - the matrix 2921 - 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) 2922 2923 Output Parameter: 2924 . info - matrix information context 2925 2926 Notes: 2927 The `MatInfo` context contains a variety of matrix data, including 2928 number of nonzeros allocated and used, number of mallocs during 2929 matrix assembly, etc. Additional information for factored matrices 2930 is provided (such as the fill ratio, number of mallocs during 2931 factorization, etc.). Much of this info is printed to `PETSC_STDOUT` 2932 when using the runtime options 2933 $ -info -mat_view ::ascii_info 2934 2935 Example: 2936 See the file ${PETSC_DIR}/include/petscmat.h for a complete list of 2937 data within the MatInfo context. For example, 2938 .vb 2939 MatInfo info; 2940 Mat A; 2941 double mal, nz_a, nz_u; 2942 2943 MatGetInfo(A,MAT_LOCAL,&info); 2944 mal = info.mallocs; 2945 nz_a = info.nz_allocated; 2946 .ve 2947 2948 Fortran users should declare info as a double precision 2949 array of dimension `MAT_INFO_SIZE`, and then extract the parameters 2950 of interest. See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h 2951 a complete list of parameter names. 2952 .vb 2953 double precision info(MAT_INFO_SIZE) 2954 double precision mal, nz_a 2955 Mat A 2956 integer ierr 2957 2958 call MatGetInfo(A,MAT_LOCAL,info,ierr) 2959 mal = info(MAT_INFO_MALLOCS) 2960 nz_a = info(MAT_INFO_NZ_ALLOCATED) 2961 .ve 2962 2963 Level: intermediate 2964 2965 Developer Note: 2966 The Fortran interface is not autogenerated as the 2967 interface definition cannot be generated correctly [due to `MatInfo` argument] 2968 2969 .seealso: [](chapter_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()` 2970 @*/ 2971 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info) 2972 { 2973 PetscFunctionBegin; 2974 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2975 PetscValidType(mat, 1); 2976 PetscValidPointer(info, 3); 2977 MatCheckPreallocated(mat, 1); 2978 PetscUseTypeMethod(mat, getinfo, flag, info); 2979 PetscFunctionReturn(PETSC_SUCCESS); 2980 } 2981 2982 /* 2983 This is used by external packages where it is not easy to get the info from the actual 2984 matrix factorization. 2985 */ 2986 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info) 2987 { 2988 PetscFunctionBegin; 2989 PetscCall(PetscMemzero(info, sizeof(MatInfo))); 2990 PetscFunctionReturn(PETSC_SUCCESS); 2991 } 2992 2993 /*@C 2994 MatLUFactor - Performs in-place LU factorization of matrix. 2995 2996 Collective 2997 2998 Input Parameters: 2999 + mat - the matrix 3000 . row - row permutation 3001 . col - column permutation 3002 - info - options for factorization, includes 3003 .vb 3004 fill - expected fill as ratio of original fill. 3005 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3006 Run with the option -info to determine an optimal value to use 3007 .ve 3008 Level: developer 3009 3010 Notes: 3011 Most users should employ the `KSP` interface for linear solvers 3012 instead of working directly with matrix algebra routines such as this. 3013 See, e.g., `KSPCreate()`. 3014 3015 This changes the state of the matrix to a factored matrix; it cannot be used 3016 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3017 3018 This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()` 3019 when not using `KSP`. 3020 3021 Developer Note: 3022 The Fortran interface is not autogenerated as the 3023 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3024 3025 .seealso: [](chapter_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, 3026 `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3027 @*/ 3028 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3029 { 3030 MatFactorInfo tinfo; 3031 3032 PetscFunctionBegin; 3033 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3034 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3035 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3036 if (info) PetscValidPointer(info, 4); 3037 PetscValidType(mat, 1); 3038 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3039 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3040 MatCheckPreallocated(mat, 1); 3041 if (!info) { 3042 PetscCall(MatFactorInfoInitialize(&tinfo)); 3043 info = &tinfo; 3044 } 3045 3046 PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0)); 3047 PetscUseTypeMethod(mat, lufactor, row, col, info); 3048 PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0)); 3049 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3050 PetscFunctionReturn(PETSC_SUCCESS); 3051 } 3052 3053 /*@C 3054 MatILUFactor - Performs in-place ILU factorization of matrix. 3055 3056 Collective 3057 3058 Input Parameters: 3059 + mat - the matrix 3060 . row - row permutation 3061 . col - column permutation 3062 - info - structure containing 3063 .vb 3064 levels - number of levels of fill. 3065 expected fill - as ratio of original fill. 3066 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 3067 missing diagonal entries) 3068 .ve 3069 3070 Level: developer 3071 3072 Notes: 3073 Most users should employ the `KSP` interface for linear solvers 3074 instead of working directly with matrix algebra routines such as this. 3075 See, e.g., `KSPCreate()`. 3076 3077 Probably really in-place only when level of fill is zero, otherwise allocates 3078 new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()` 3079 when not using `KSP`. 3080 3081 Developer Note: 3082 The Fortran interface is not autogenerated as the 3083 interface definition cannot be generated correctly [due to MatFactorInfo] 3084 3085 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 3086 @*/ 3087 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3088 { 3089 PetscFunctionBegin; 3090 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3091 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3092 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3093 PetscValidPointer(info, 4); 3094 PetscValidType(mat, 1); 3095 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 3096 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3097 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3098 MatCheckPreallocated(mat, 1); 3099 3100 PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0)); 3101 PetscUseTypeMethod(mat, ilufactor, row, col, info); 3102 PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0)); 3103 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3104 PetscFunctionReturn(PETSC_SUCCESS); 3105 } 3106 3107 /*@C 3108 MatLUFactorSymbolic - Performs symbolic LU factorization of matrix. 3109 Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`. 3110 3111 Collective 3112 3113 Input Parameters: 3114 + fact - the factor matrix obtained with `MatGetFactor()` 3115 . mat - the matrix 3116 . row - the row permutation 3117 . col - the column permutation 3118 - info - options for factorization, includes 3119 .vb 3120 fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use 3121 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3122 .ve 3123 3124 Level: developer 3125 3126 Notes: 3127 See [Matrix Factorization](sec_matfactor) for additional information about factorizations 3128 3129 Most users should employ the simplified `KSP` interface for linear solvers 3130 instead of working directly with matrix algebra routines such as this. 3131 See, e.g., `KSPCreate()`. 3132 3133 Developer Note: 3134 The Fortran interface is not autogenerated as the 3135 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3136 3137 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3138 @*/ 3139 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 3140 { 3141 MatFactorInfo tinfo; 3142 3143 PetscFunctionBegin; 3144 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 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(fact, 1); 3150 PetscValidType(mat, 2); 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(fact, MAT_CLASSID, 1); 3204 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3205 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3206 PetscValidType(fact, 1); 3207 PetscValidType(mat, 2); 3208 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3209 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, 3210 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3211 3212 PetscCheck((fact)->ops->lufactornumeric, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s numeric LU", ((PetscObject)mat)->type_name); 3213 MatCheckPreallocated(mat, 2); 3214 if (!info) { 3215 PetscCall(MatFactorInfoInitialize(&tinfo)); 3216 info = &tinfo; 3217 } 3218 3219 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3220 else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0)); 3221 PetscCall((*fact->ops->lufactornumeric)(fact, mat, info)); 3222 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3223 else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0)); 3224 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3225 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3226 PetscFunctionReturn(PETSC_SUCCESS); 3227 } 3228 3229 /*@C 3230 MatCholeskyFactor - Performs in-place Cholesky factorization of a 3231 symmetric matrix. 3232 3233 Collective 3234 3235 Input Parameters: 3236 + mat - the matrix 3237 . perm - row and column permutations 3238 - f - expected fill as ratio of original fill 3239 3240 Level: developer 3241 3242 Notes: 3243 See `MatLUFactor()` for the nonsymmetric case. See also `MatGetFactor()`, 3244 `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`. 3245 3246 Most users should employ the `KSP` interface for linear solvers 3247 instead of working directly with matrix algebra routines such as this. 3248 See, e.g., `KSPCreate()`. 3249 3250 Developer Note: 3251 The Fortran interface is not autogenerated as the 3252 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3253 3254 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()` 3255 `MatGetOrdering()` 3256 @*/ 3257 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info) 3258 { 3259 MatFactorInfo tinfo; 3260 3261 PetscFunctionBegin; 3262 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3263 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2); 3264 if (info) PetscValidPointer(info, 3); 3265 PetscValidType(mat, 1); 3266 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3267 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3268 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3269 MatCheckPreallocated(mat, 1); 3270 if (!info) { 3271 PetscCall(MatFactorInfoInitialize(&tinfo)); 3272 info = &tinfo; 3273 } 3274 3275 PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0)); 3276 PetscUseTypeMethod(mat, choleskyfactor, perm, info); 3277 PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0)); 3278 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3279 PetscFunctionReturn(PETSC_SUCCESS); 3280 } 3281 3282 /*@C 3283 MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization 3284 of a symmetric matrix. 3285 3286 Collective 3287 3288 Input Parameters: 3289 + fact - the factor matrix obtained with `MatGetFactor()` 3290 . mat - the matrix 3291 . perm - row and column permutations 3292 - info - options for factorization, includes 3293 .vb 3294 fill - expected fill as ratio of original fill. 3295 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3296 Run with the option -info to determine an optimal value to use 3297 .ve 3298 3299 Level: developer 3300 3301 Notes: 3302 See `MatLUFactorSymbolic()` for the nonsymmetric case. See also 3303 `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`. 3304 3305 Most users should employ the `KSP` interface for linear solvers 3306 instead of working directly with matrix algebra routines such as this. 3307 See, e.g., `KSPCreate()`. 3308 3309 Developer Note: 3310 The Fortran interface is not autogenerated as the 3311 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3312 3313 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()` 3314 `MatGetOrdering()` 3315 @*/ 3316 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 3317 { 3318 MatFactorInfo tinfo; 3319 3320 PetscFunctionBegin; 3321 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3322 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3323 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 3324 if (info) PetscValidPointer(info, 4); 3325 PetscValidType(fact, 1); 3326 PetscValidType(mat, 2); 3327 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3328 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3329 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3330 if (!fact->ops->choleskyfactorsymbolic) { 3331 MatSolverType stype; 3332 PetscCall(MatFactorGetSolverType(fact, &stype)); 3333 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s symbolic factor Cholesky using solver package %s", ((PetscObject)mat)->type_name, stype); 3334 } 3335 MatCheckPreallocated(mat, 2); 3336 if (!info) { 3337 PetscCall(MatFactorInfoInitialize(&tinfo)); 3338 info = &tinfo; 3339 } 3340 3341 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3342 PetscCall((*fact->ops->choleskyfactorsymbolic)(fact, mat, perm, info)); 3343 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3344 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3345 PetscFunctionReturn(PETSC_SUCCESS); 3346 } 3347 3348 /*@C 3349 MatCholeskyFactorNumeric - Performs numeric Cholesky factorization 3350 of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and 3351 `MatCholeskyFactorSymbolic()`. 3352 3353 Collective 3354 3355 Input Parameters: 3356 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored 3357 . mat - the initial matrix that is to be factored 3358 - info - options for factorization 3359 3360 Level: developer 3361 3362 Note: 3363 Most users should employ the `KSP` interface for linear solvers 3364 instead of working directly with matrix algebra routines such as this. 3365 See, e.g., `KSPCreate()`. 3366 3367 Developer Note: 3368 The Fortran interface is not autogenerated as the 3369 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3370 3371 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()` 3372 @*/ 3373 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3374 { 3375 MatFactorInfo tinfo; 3376 3377 PetscFunctionBegin; 3378 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3379 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3380 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3381 PetscValidType(fact, 1); 3382 PetscValidType(mat, 2); 3383 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3384 PetscCheck((fact)->ops->choleskyfactornumeric, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s numeric factor Cholesky", ((PetscObject)mat)->type_name); 3385 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, 3386 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3387 MatCheckPreallocated(mat, 2); 3388 if (!info) { 3389 PetscCall(MatFactorInfoInitialize(&tinfo)); 3390 info = &tinfo; 3391 } 3392 3393 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3394 else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0)); 3395 PetscCall((*fact->ops->choleskyfactornumeric)(fact, mat, info)); 3396 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3397 else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0)); 3398 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3399 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3400 PetscFunctionReturn(PETSC_SUCCESS); 3401 } 3402 3403 /*@ 3404 MatQRFactor - Performs in-place QR factorization of matrix. 3405 3406 Collective 3407 3408 Input Parameters: 3409 + mat - the matrix 3410 . col - column permutation 3411 - info - options for factorization, includes 3412 .vb 3413 fill - expected fill as ratio of original fill. 3414 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3415 Run with the option -info to determine an optimal value to use 3416 .ve 3417 3418 Level: developer 3419 3420 Notes: 3421 Most users should employ the `KSP` interface for linear solvers 3422 instead of working directly with matrix algebra routines such as this. 3423 See, e.g., `KSPCreate()`. 3424 3425 This changes the state of the matrix to a factored matrix; it cannot be used 3426 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3427 3428 Developer Note: 3429 The Fortran interface is not autogenerated as the 3430 interface definition cannot be generated correctly [due to MatFactorInfo] 3431 3432 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`, 3433 `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3434 @*/ 3435 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info) 3436 { 3437 PetscFunctionBegin; 3438 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3439 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2); 3440 if (info) PetscValidPointer(info, 3); 3441 PetscValidType(mat, 1); 3442 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3443 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3444 MatCheckPreallocated(mat, 1); 3445 PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0)); 3446 PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info)); 3447 PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0)); 3448 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3449 PetscFunctionReturn(PETSC_SUCCESS); 3450 } 3451 3452 /*@ 3453 MatQRFactorSymbolic - Performs symbolic QR factorization of matrix. 3454 Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`. 3455 3456 Collective 3457 3458 Input Parameters: 3459 + fact - the factor matrix obtained with `MatGetFactor()` 3460 . mat - the matrix 3461 . col - column permutation 3462 - info - options for factorization, includes 3463 .vb 3464 fill - expected fill as ratio of original fill. 3465 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3466 Run with the option -info to determine an optimal value to use 3467 .ve 3468 3469 Level: developer 3470 3471 Note: 3472 Most users should employ the `KSP` interface for linear solvers 3473 instead of working directly with matrix algebra routines such as this. 3474 See, e.g., `KSPCreate()`. 3475 3476 Developer Note: 3477 The Fortran interface is not autogenerated as the 3478 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3479 3480 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3481 @*/ 3482 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info) 3483 { 3484 MatFactorInfo tinfo; 3485 3486 PetscFunctionBegin; 3487 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3488 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3489 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3490 if (info) PetscValidPointer(info, 4); 3491 PetscValidType(fact, 1); 3492 PetscValidType(mat, 2); 3493 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3494 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3495 MatCheckPreallocated(mat, 2); 3496 if (!info) { 3497 PetscCall(MatFactorInfoInitialize(&tinfo)); 3498 info = &tinfo; 3499 } 3500 3501 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3502 PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info)); 3503 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3504 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3505 PetscFunctionReturn(PETSC_SUCCESS); 3506 } 3507 3508 /*@ 3509 MatQRFactorNumeric - Performs numeric QR factorization of a matrix. 3510 Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`. 3511 3512 Collective 3513 3514 Input Parameters: 3515 + fact - the factor matrix obtained with `MatGetFactor()` 3516 . mat - the matrix 3517 - info - options for factorization 3518 3519 Level: developer 3520 3521 Notes: 3522 See `MatQRFactor()` for in-place factorization. 3523 3524 Most users should employ the `KSP` interface for linear solvers 3525 instead of working directly with matrix algebra routines such as this. 3526 See, e.g., `KSPCreate()`. 3527 3528 Developer Note: 3529 The Fortran interface is not autogenerated as the 3530 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3531 3532 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()` 3533 @*/ 3534 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3535 { 3536 MatFactorInfo tinfo; 3537 3538 PetscFunctionBegin; 3539 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3540 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3541 PetscValidType(fact, 1); 3542 PetscValidType(mat, 2); 3543 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3544 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, 3545 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3546 3547 MatCheckPreallocated(mat, 2); 3548 if (!info) { 3549 PetscCall(MatFactorInfoInitialize(&tinfo)); 3550 info = &tinfo; 3551 } 3552 3553 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3554 else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0)); 3555 PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info)); 3556 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3557 else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0)); 3558 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3559 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3560 PetscFunctionReturn(PETSC_SUCCESS); 3561 } 3562 3563 /*@ 3564 MatSolve - Solves A x = b, given a factored matrix. 3565 3566 Neighbor-wise Collective 3567 3568 Input Parameters: 3569 + mat - the factored matrix 3570 - b - the right-hand-side vector 3571 3572 Output Parameter: 3573 . x - the result vector 3574 3575 Level: developer 3576 3577 Notes: 3578 The vectors `b` and `x` cannot be the same. I.e., one cannot 3579 call `MatSolve`(A,x,x). 3580 3581 Most users should employ the `KSP` interface for linear solvers 3582 instead of working directly with matrix algebra routines such as this. 3583 See, e.g., `KSPCreate()`. 3584 3585 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3586 @*/ 3587 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x) 3588 { 3589 PetscFunctionBegin; 3590 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3591 PetscValidType(mat, 1); 3592 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3593 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3594 PetscCheckSameComm(mat, 1, b, 2); 3595 PetscCheckSameComm(mat, 1, x, 3); 3596 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3597 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); 3598 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); 3599 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); 3600 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3601 MatCheckPreallocated(mat, 1); 3602 3603 PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0)); 3604 if (mat->factorerrortype) { 3605 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3606 PetscCall(VecSetInf(x)); 3607 } else PetscUseTypeMethod(mat, solve, b, x); 3608 PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0)); 3609 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3610 PetscFunctionReturn(PETSC_SUCCESS); 3611 } 3612 3613 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans) 3614 { 3615 Vec b, x; 3616 PetscInt N, i; 3617 PetscErrorCode (*f)(Mat, Vec, Vec); 3618 PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE; 3619 3620 PetscFunctionBegin; 3621 if (A->factorerrortype) { 3622 PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype)); 3623 PetscCall(MatSetInf(X)); 3624 PetscFunctionReturn(PETSC_SUCCESS); 3625 } 3626 f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose; 3627 PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 3628 PetscCall(MatBoundToCPU(A, &Abound)); 3629 if (!Abound) { 3630 PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3631 PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3632 } 3633 #if defined(PETSC_HAVE_CUDA) 3634 if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B)); 3635 if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X)); 3636 #elif (PETSC_HAVE_HIP) 3637 if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B)); 3638 if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X)); 3639 #endif 3640 PetscCall(MatGetSize(B, NULL, &N)); 3641 for (i = 0; i < N; i++) { 3642 PetscCall(MatDenseGetColumnVecRead(B, i, &b)); 3643 PetscCall(MatDenseGetColumnVecWrite(X, i, &x)); 3644 PetscCall((*f)(A, b, x)); 3645 PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x)); 3646 PetscCall(MatDenseRestoreColumnVecRead(B, i, &b)); 3647 } 3648 if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B)); 3649 if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X)); 3650 PetscFunctionReturn(PETSC_SUCCESS); 3651 } 3652 3653 /*@ 3654 MatMatSolve - Solves A X = B, given a factored matrix. 3655 3656 Neighbor-wise Collective 3657 3658 Input Parameters: 3659 + A - the factored matrix 3660 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS) 3661 3662 Output Parameter: 3663 . X - the result matrix (dense matrix) 3664 3665 Level: developer 3666 3667 Note: 3668 If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`; 3669 otherwise, `B` and `X` cannot be the same. 3670 3671 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3672 @*/ 3673 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X) 3674 { 3675 PetscFunctionBegin; 3676 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3677 PetscValidType(A, 1); 3678 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3679 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3680 PetscCheckSameComm(A, 1, B, 2); 3681 PetscCheckSameComm(A, 1, X, 3); 3682 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); 3683 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); 3684 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"); 3685 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3686 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3687 MatCheckPreallocated(A, 1); 3688 3689 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3690 if (!A->ops->matsolve) { 3691 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name)); 3692 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE)); 3693 } else PetscUseTypeMethod(A, matsolve, B, X); 3694 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3695 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3696 PetscFunctionReturn(PETSC_SUCCESS); 3697 } 3698 3699 /*@ 3700 MatMatSolveTranspose - Solves A^T X = B, given a factored matrix. 3701 3702 Neighbor-wise Collective 3703 3704 Input Parameters: 3705 + A - the factored matrix 3706 - B - the right-hand-side matrix (`MATDENSE` matrix) 3707 3708 Output Parameter: 3709 . X - the result matrix (dense matrix) 3710 3711 Level: developer 3712 3713 Note: 3714 The matrices `B` and `X` cannot be the same. I.e., one cannot 3715 call `MatMatSolveTranspose`(A,X,X). 3716 3717 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()` 3718 @*/ 3719 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X) 3720 { 3721 PetscFunctionBegin; 3722 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3723 PetscValidType(A, 1); 3724 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3725 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3726 PetscCheckSameComm(A, 1, B, 2); 3727 PetscCheckSameComm(A, 1, X, 3); 3728 PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3729 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); 3730 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); 3731 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); 3732 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"); 3733 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3734 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3735 MatCheckPreallocated(A, 1); 3736 3737 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3738 if (!A->ops->matsolvetranspose) { 3739 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name)); 3740 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE)); 3741 } else PetscUseTypeMethod(A, matsolvetranspose, B, X); 3742 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3743 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3744 PetscFunctionReturn(PETSC_SUCCESS); 3745 } 3746 3747 /*@ 3748 MatMatTransposeSolve - Solves A X = B^T, given a factored matrix. 3749 3750 Neighbor-wise Collective 3751 3752 Input Parameters: 3753 + A - the factored matrix 3754 - Bt - the transpose of right-hand-side matrix as a `MATDENSE` 3755 3756 Output Parameter: 3757 . X - the result matrix (dense matrix) 3758 3759 Level: developer 3760 3761 Note: 3762 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 3763 format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`. 3764 3765 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3766 @*/ 3767 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X) 3768 { 3769 PetscFunctionBegin; 3770 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3771 PetscValidType(A, 1); 3772 PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2); 3773 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3774 PetscCheckSameComm(A, 1, Bt, 2); 3775 PetscCheckSameComm(A, 1, X, 3); 3776 3777 PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3778 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); 3779 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); 3780 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"); 3781 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3782 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3783 MatCheckPreallocated(A, 1); 3784 3785 PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0)); 3786 PetscUseTypeMethod(A, mattransposesolve, Bt, X); 3787 PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0)); 3788 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3789 PetscFunctionReturn(PETSC_SUCCESS); 3790 } 3791 3792 /*@ 3793 MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or 3794 U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U, 3795 3796 Neighbor-wise Collective 3797 3798 Input Parameters: 3799 + mat - the factored matrix 3800 - b - the right-hand-side vector 3801 3802 Output Parameter: 3803 . x - the result vector 3804 3805 Level: developer 3806 3807 Notes: 3808 `MatSolve()` should be used for most applications, as it performs 3809 a forward solve followed by a backward solve. 3810 3811 The vectors `b` and `x` cannot be the same, i.e., one cannot 3812 call `MatForwardSolve`(A,x,x). 3813 3814 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3815 the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet. 3816 `MatForwardSolve()` solves U^T*D y = b, and 3817 `MatBackwardSolve()` solves U x = y. 3818 Thus they do not provide a symmetric preconditioner. 3819 3820 .seealso: [](chapter_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatBackwardSolve()` 3821 @*/ 3822 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x) 3823 { 3824 PetscFunctionBegin; 3825 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3826 PetscValidType(mat, 1); 3827 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3828 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3829 PetscCheckSameComm(mat, 1, b, 2); 3830 PetscCheckSameComm(mat, 1, x, 3); 3831 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3832 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); 3833 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); 3834 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); 3835 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3836 MatCheckPreallocated(mat, 1); 3837 3838 PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0)); 3839 PetscUseTypeMethod(mat, forwardsolve, b, x); 3840 PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0)); 3841 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3842 PetscFunctionReturn(PETSC_SUCCESS); 3843 } 3844 3845 /*@ 3846 MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU. 3847 D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U, 3848 3849 Neighbor-wise Collective 3850 3851 Input Parameters: 3852 + mat - the factored matrix 3853 - b - the right-hand-side vector 3854 3855 Output Parameter: 3856 . x - the result vector 3857 3858 Level: developer 3859 3860 Notes: 3861 `MatSolve()` should be used for most applications, as it performs 3862 a forward solve followed by a backward solve. 3863 3864 The vectors `b` and `x` cannot be the same. I.e., one cannot 3865 call `MatBackwardSolve`(A,x,x). 3866 3867 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3868 the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet. 3869 `MatForwardSolve()` solves U^T*D y = b, and 3870 `MatBackwardSolve()` solves U x = y. 3871 Thus they do not provide a symmetric preconditioner. 3872 3873 .seealso: [](chapter_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatForwardSolve()` 3874 @*/ 3875 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x) 3876 { 3877 PetscFunctionBegin; 3878 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3879 PetscValidType(mat, 1); 3880 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3881 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3882 PetscCheckSameComm(mat, 1, b, 2); 3883 PetscCheckSameComm(mat, 1, x, 3); 3884 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3885 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); 3886 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); 3887 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); 3888 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3889 MatCheckPreallocated(mat, 1); 3890 3891 PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0)); 3892 PetscUseTypeMethod(mat, backwardsolve, b, x); 3893 PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0)); 3894 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3895 PetscFunctionReturn(PETSC_SUCCESS); 3896 } 3897 3898 /*@ 3899 MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix. 3900 3901 Neighbor-wise Collective 3902 3903 Input Parameters: 3904 + mat - the factored matrix 3905 . b - the right-hand-side vector 3906 - y - the vector to be added to 3907 3908 Output Parameter: 3909 . x - the result vector 3910 3911 Level: developer 3912 3913 Note: 3914 The vectors `b` and `x` cannot be the same. I.e., one cannot 3915 call `MatSolveAdd`(A,x,y,x). 3916 3917 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3918 @*/ 3919 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x) 3920 { 3921 PetscScalar one = 1.0; 3922 Vec tmp; 3923 3924 PetscFunctionBegin; 3925 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3926 PetscValidType(mat, 1); 3927 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 3928 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3929 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 3930 PetscCheckSameComm(mat, 1, b, 2); 3931 PetscCheckSameComm(mat, 1, y, 3); 3932 PetscCheckSameComm(mat, 1, x, 4); 3933 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3934 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); 3935 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); 3936 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); 3937 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); 3938 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); 3939 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3940 MatCheckPreallocated(mat, 1); 3941 3942 PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y)); 3943 if (mat->factorerrortype) { 3944 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3945 PetscCall(VecSetInf(x)); 3946 } else if (mat->ops->solveadd) { 3947 PetscUseTypeMethod(mat, solveadd, b, y, x); 3948 } else { 3949 /* do the solve then the add manually */ 3950 if (x != y) { 3951 PetscCall(MatSolve(mat, b, x)); 3952 PetscCall(VecAXPY(x, one, y)); 3953 } else { 3954 PetscCall(VecDuplicate(x, &tmp)); 3955 PetscCall(VecCopy(x, tmp)); 3956 PetscCall(MatSolve(mat, b, x)); 3957 PetscCall(VecAXPY(x, one, tmp)); 3958 PetscCall(VecDestroy(&tmp)); 3959 } 3960 } 3961 PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y)); 3962 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3963 PetscFunctionReturn(PETSC_SUCCESS); 3964 } 3965 3966 /*@ 3967 MatSolveTranspose - Solves A' x = b, given a factored matrix. 3968 3969 Neighbor-wise Collective 3970 3971 Input Parameters: 3972 + mat - the factored matrix 3973 - b - the right-hand-side vector 3974 3975 Output Parameter: 3976 . x - the result vector 3977 3978 Level: developer 3979 3980 Notes: 3981 The vectors `b` and `x` cannot be the same. I.e., one cannot 3982 call `MatSolveTranspose`(A,x,x). 3983 3984 Most users should employ the `KSP` interface for linear solvers 3985 instead of working directly with matrix algebra routines such as this. 3986 See, e.g., `KSPCreate()`. 3987 3988 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()` 3989 @*/ 3990 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x) 3991 { 3992 PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose; 3993 3994 PetscFunctionBegin; 3995 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3996 PetscValidType(mat, 1); 3997 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3998 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3999 PetscCheckSameComm(mat, 1, b, 2); 4000 PetscCheckSameComm(mat, 1, x, 3); 4001 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4002 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); 4003 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); 4004 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4005 MatCheckPreallocated(mat, 1); 4006 PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0)); 4007 if (mat->factorerrortype) { 4008 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4009 PetscCall(VecSetInf(x)); 4010 } else { 4011 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name); 4012 PetscCall((*f)(mat, b, x)); 4013 } 4014 PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0)); 4015 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4016 PetscFunctionReturn(PETSC_SUCCESS); 4017 } 4018 4019 /*@ 4020 MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a 4021 factored matrix. 4022 4023 Neighbor-wise Collective 4024 4025 Input Parameters: 4026 + mat - the factored matrix 4027 . b - the right-hand-side vector 4028 - y - the vector to be added to 4029 4030 Output Parameter: 4031 . x - the result vector 4032 4033 Level: developer 4034 4035 Note: 4036 The vectors `b` and `x` cannot be the same. I.e., one cannot 4037 call `MatSolveTransposeAdd`(A,x,y,x). 4038 4039 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()` 4040 @*/ 4041 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x) 4042 { 4043 PetscScalar one = 1.0; 4044 Vec tmp; 4045 PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd; 4046 4047 PetscFunctionBegin; 4048 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4049 PetscValidType(mat, 1); 4050 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4051 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4052 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4053 PetscCheckSameComm(mat, 1, b, 2); 4054 PetscCheckSameComm(mat, 1, y, 3); 4055 PetscCheckSameComm(mat, 1, x, 4); 4056 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4057 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); 4058 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); 4059 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); 4060 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); 4061 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4062 MatCheckPreallocated(mat, 1); 4063 4064 PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y)); 4065 if (mat->factorerrortype) { 4066 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4067 PetscCall(VecSetInf(x)); 4068 } else if (f) { 4069 PetscCall((*f)(mat, b, y, x)); 4070 } else { 4071 /* do the solve then the add manually */ 4072 if (x != y) { 4073 PetscCall(MatSolveTranspose(mat, b, x)); 4074 PetscCall(VecAXPY(x, one, y)); 4075 } else { 4076 PetscCall(VecDuplicate(x, &tmp)); 4077 PetscCall(VecCopy(x, tmp)); 4078 PetscCall(MatSolveTranspose(mat, b, x)); 4079 PetscCall(VecAXPY(x, one, tmp)); 4080 PetscCall(VecDestroy(&tmp)); 4081 } 4082 } 4083 PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y)); 4084 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4085 PetscFunctionReturn(PETSC_SUCCESS); 4086 } 4087 4088 /*@ 4089 MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps. 4090 4091 Neighbor-wise Collective 4092 4093 Input Parameters: 4094 + mat - the matrix 4095 . b - the right hand side 4096 . omega - the relaxation factor 4097 . flag - flag indicating the type of SOR (see below) 4098 . shift - diagonal shift 4099 . its - the number of iterations 4100 - lits - the number of local iterations 4101 4102 Output Parameter: 4103 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess) 4104 4105 SOR Flags: 4106 + `SOR_FORWARD_SWEEP` - forward SOR 4107 . `SOR_BACKWARD_SWEEP` - backward SOR 4108 . `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR) 4109 . `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR 4110 . `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR 4111 . `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR 4112 . `SOR_EISENSTAT` - SOR with Eisenstat trick 4113 . `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies 4114 upper/lower triangular part of matrix to 4115 vector (with omega) 4116 - `SOR_ZERO_INITIAL_GUESS` - zero initial guess 4117 4118 Level: developer 4119 4120 Notes: 4121 `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and 4122 `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings 4123 on each processor. 4124 4125 Application programmers will not generally use `MatSOR()` directly, 4126 but instead will employ the `KSP`/`PC` interface. 4127 4128 For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing 4129 4130 Most users should employ the `KSP` interface for linear solvers 4131 instead of working directly with matrix algebra routines such as this. 4132 See, e.g., `KSPCreate()`. 4133 4134 Vectors `x` and `b` CANNOT be the same 4135 4136 The flags are implemented as bitwise inclusive or operations. 4137 For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`) 4138 to specify a zero initial guess for SSOR. 4139 4140 Developer Note: 4141 We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes 4142 4143 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()` 4144 @*/ 4145 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x) 4146 { 4147 PetscFunctionBegin; 4148 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4149 PetscValidType(mat, 1); 4150 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4151 PetscValidHeaderSpecific(x, VEC_CLASSID, 8); 4152 PetscCheckSameComm(mat, 1, b, 2); 4153 PetscCheckSameComm(mat, 1, x, 8); 4154 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4155 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4156 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); 4157 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); 4158 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); 4159 PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its); 4160 PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits); 4161 PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same"); 4162 4163 MatCheckPreallocated(mat, 1); 4164 PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0)); 4165 PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x); 4166 PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0)); 4167 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4168 PetscFunctionReturn(PETSC_SUCCESS); 4169 } 4170 4171 /* 4172 Default matrix copy routine. 4173 */ 4174 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str) 4175 { 4176 PetscInt i, rstart = 0, rend = 0, nz; 4177 const PetscInt *cwork; 4178 const PetscScalar *vwork; 4179 4180 PetscFunctionBegin; 4181 if (B->assembled) PetscCall(MatZeroEntries(B)); 4182 if (str == SAME_NONZERO_PATTERN) { 4183 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 4184 for (i = rstart; i < rend; i++) { 4185 PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork)); 4186 PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES)); 4187 PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork)); 4188 } 4189 } else { 4190 PetscCall(MatAYPX(B, 0.0, A, str)); 4191 } 4192 PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 4193 PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 4194 PetscFunctionReturn(PETSC_SUCCESS); 4195 } 4196 4197 /*@ 4198 MatCopy - Copies a matrix to another matrix. 4199 4200 Collective 4201 4202 Input Parameters: 4203 + A - the matrix 4204 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN` 4205 4206 Output Parameter: 4207 . B - where the copy is put 4208 4209 Level: intermediate 4210 4211 Notes: 4212 If you use `SAME_NONZERO_PATTERN` then the two matrices must have the same nonzero pattern or the routine will crash. 4213 4214 `MatCopy()` copies the matrix entries of a matrix to another existing 4215 matrix (after first zeroing the second matrix). A related routine is 4216 `MatConvert()`, which first creates a new matrix and then copies the data. 4217 4218 .seealso: [](chapter_matrices), `Mat`, `MatConvert()`, `MatDuplicate()` 4219 @*/ 4220 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str) 4221 { 4222 PetscInt i; 4223 4224 PetscFunctionBegin; 4225 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 4226 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 4227 PetscValidType(A, 1); 4228 PetscValidType(B, 2); 4229 PetscCheckSameComm(A, 1, B, 2); 4230 MatCheckPreallocated(B, 2); 4231 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4232 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4233 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, 4234 A->cmap->N, B->cmap->N); 4235 MatCheckPreallocated(A, 1); 4236 if (A == B) PetscFunctionReturn(PETSC_SUCCESS); 4237 4238 PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0)); 4239 if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str); 4240 else PetscCall(MatCopy_Basic(A, B, str)); 4241 4242 B->stencil.dim = A->stencil.dim; 4243 B->stencil.noc = A->stencil.noc; 4244 for (i = 0; i <= A->stencil.dim; i++) { 4245 B->stencil.dims[i] = A->stencil.dims[i]; 4246 B->stencil.starts[i] = A->stencil.starts[i]; 4247 } 4248 4249 PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0)); 4250 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4251 PetscFunctionReturn(PETSC_SUCCESS); 4252 } 4253 4254 /*@C 4255 MatConvert - Converts a matrix to another matrix, either of the same 4256 or different type. 4257 4258 Collective 4259 4260 Input Parameters: 4261 + mat - the matrix 4262 . newtype - new matrix type. Use `MATSAME` to create a new matrix of the 4263 same type as the original matrix. 4264 - reuse - denotes if the destination matrix is to be created or reused. 4265 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 4266 `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). 4267 4268 Output Parameter: 4269 . M - pointer to place new matrix 4270 4271 Level: intermediate 4272 4273 Notes: 4274 `MatConvert()` first creates a new matrix and then copies the data from 4275 the first matrix. A related routine is `MatCopy()`, which copies the matrix 4276 entries of one matrix to another already existing matrix context. 4277 4278 Cannot be used to convert a sequential matrix to parallel or parallel to sequential, 4279 the MPI communicator of the generated matrix is always the same as the communicator 4280 of the input matrix. 4281 4282 .seealso: [](chapter_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 4283 @*/ 4284 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M) 4285 { 4286 PetscBool sametype, issame, flg; 4287 PetscBool3 issymmetric, ishermitian; 4288 char convname[256], mtype[256]; 4289 Mat B; 4290 4291 PetscFunctionBegin; 4292 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4293 PetscValidType(mat, 1); 4294 PetscValidPointer(M, 4); 4295 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4296 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4297 MatCheckPreallocated(mat, 1); 4298 4299 PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg)); 4300 if (flg) newtype = mtype; 4301 4302 PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype)); 4303 PetscCall(PetscStrcmp(newtype, "same", &issame)); 4304 PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix"); 4305 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"); 4306 4307 if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) { 4308 PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4309 PetscFunctionReturn(PETSC_SUCCESS); 4310 } 4311 4312 /* Cache Mat options because some converters use MatHeaderReplace */ 4313 issymmetric = mat->symmetric; 4314 ishermitian = mat->hermitian; 4315 4316 if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) { 4317 PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4318 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4319 } else { 4320 PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL; 4321 const char *prefix[3] = {"seq", "mpi", ""}; 4322 PetscInt i; 4323 /* 4324 Order of precedence: 4325 0) See if newtype is a superclass of the current matrix. 4326 1) See if a specialized converter is known to the current matrix. 4327 2) See if a specialized converter is known to the desired matrix class. 4328 3) See if a good general converter is registered for the desired class 4329 (as of 6/27/03 only MATMPIADJ falls into this category). 4330 4) See if a good general converter is known for the current matrix. 4331 5) Use a really basic converter. 4332 */ 4333 4334 /* 0) See if newtype is a superclass of the current matrix. 4335 i.e mat is mpiaij and newtype is aij */ 4336 for (i = 0; i < 2; i++) { 4337 PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname))); 4338 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4339 PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg)); 4340 PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg)); 4341 if (flg) { 4342 if (reuse == MAT_INPLACE_MATRIX) { 4343 PetscCall(PetscInfo(mat, "Early return\n")); 4344 PetscFunctionReturn(PETSC_SUCCESS); 4345 } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) { 4346 PetscCall(PetscInfo(mat, "Calling MatDuplicate\n")); 4347 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4348 PetscFunctionReturn(PETSC_SUCCESS); 4349 } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) { 4350 PetscCall(PetscInfo(mat, "Calling MatCopy\n")); 4351 PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN)); 4352 PetscFunctionReturn(PETSC_SUCCESS); 4353 } 4354 } 4355 } 4356 /* 1) See if a specialized converter is known to the current matrix and the desired class */ 4357 for (i = 0; i < 3; i++) { 4358 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4359 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4360 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4361 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4362 PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname))); 4363 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4364 PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv)); 4365 PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv)); 4366 if (conv) goto foundconv; 4367 } 4368 4369 /* 2) See if a specialized converter is known to the desired matrix class. */ 4370 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B)); 4371 PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 4372 PetscCall(MatSetType(B, newtype)); 4373 for (i = 0; i < 3; i++) { 4374 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4375 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4376 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4377 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4378 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4379 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4380 PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv)); 4381 PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv)); 4382 if (conv) { 4383 PetscCall(MatDestroy(&B)); 4384 goto foundconv; 4385 } 4386 } 4387 4388 /* 3) See if a good general converter is registered for the desired class */ 4389 conv = B->ops->convertfrom; 4390 PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv)); 4391 PetscCall(MatDestroy(&B)); 4392 if (conv) goto foundconv; 4393 4394 /* 4) See if a good general converter is known for the current matrix */ 4395 if (mat->ops->convert) conv = mat->ops->convert; 4396 PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv)); 4397 if (conv) goto foundconv; 4398 4399 /* 5) Use a really basic converter. */ 4400 PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n")); 4401 conv = MatConvert_Basic; 4402 4403 foundconv: 4404 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4405 PetscCall((*conv)(mat, newtype, reuse, M)); 4406 if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) { 4407 /* the block sizes must be same if the mappings are copied over */ 4408 (*M)->rmap->bs = mat->rmap->bs; 4409 (*M)->cmap->bs = mat->cmap->bs; 4410 PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping)); 4411 PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping)); 4412 (*M)->rmap->mapping = mat->rmap->mapping; 4413 (*M)->cmap->mapping = mat->cmap->mapping; 4414 } 4415 (*M)->stencil.dim = mat->stencil.dim; 4416 (*M)->stencil.noc = mat->stencil.noc; 4417 for (i = 0; i <= mat->stencil.dim; i++) { 4418 (*M)->stencil.dims[i] = mat->stencil.dims[i]; 4419 (*M)->stencil.starts[i] = mat->stencil.starts[i]; 4420 } 4421 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4422 } 4423 PetscCall(PetscObjectStateIncrease((PetscObject)*M)); 4424 4425 /* Copy Mat options */ 4426 if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE)); 4427 else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE)); 4428 if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE)); 4429 else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE)); 4430 PetscFunctionReturn(PETSC_SUCCESS); 4431 } 4432 4433 /*@C 4434 MatFactorGetSolverType - Returns name of the package providing the factorization routines 4435 4436 Not Collective 4437 4438 Input Parameter: 4439 . mat - the matrix, must be a factored matrix 4440 4441 Output Parameter: 4442 . type - the string name of the package (do not free this string) 4443 4444 Level: intermediate 4445 4446 Fortran Note: 4447 Pass in an empty string and the package name will be copied into it. Make sure the string is long enough. 4448 4449 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()` 4450 @*/ 4451 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type) 4452 { 4453 PetscErrorCode (*conv)(Mat, MatSolverType *); 4454 4455 PetscFunctionBegin; 4456 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4457 PetscValidType(mat, 1); 4458 PetscValidPointer(type, 2); 4459 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 4460 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv)); 4461 if (conv) PetscCall((*conv)(mat, type)); 4462 else *type = MATSOLVERPETSC; 4463 PetscFunctionReturn(PETSC_SUCCESS); 4464 } 4465 4466 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType; 4467 struct _MatSolverTypeForSpecifcType { 4468 MatType mtype; 4469 /* no entry for MAT_FACTOR_NONE */ 4470 PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *); 4471 MatSolverTypeForSpecifcType next; 4472 }; 4473 4474 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder; 4475 struct _MatSolverTypeHolder { 4476 char *name; 4477 MatSolverTypeForSpecifcType handlers; 4478 MatSolverTypeHolder next; 4479 }; 4480 4481 static MatSolverTypeHolder MatSolverTypeHolders = NULL; 4482 4483 /*@C 4484 MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type 4485 4486 Input Parameters: 4487 + package - name of the package, for example petsc or superlu 4488 . mtype - the matrix type that works with this package 4489 . ftype - the type of factorization supported by the package 4490 - createfactor - routine that will create the factored matrix ready to be used 4491 4492 Level: developer 4493 4494 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()` 4495 @*/ 4496 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *)) 4497 { 4498 MatSolverTypeHolder next = MatSolverTypeHolders, prev = NULL; 4499 PetscBool flg; 4500 MatSolverTypeForSpecifcType inext, iprev = NULL; 4501 4502 PetscFunctionBegin; 4503 PetscCall(MatInitializePackage()); 4504 if (!next) { 4505 PetscCall(PetscNew(&MatSolverTypeHolders)); 4506 PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name)); 4507 PetscCall(PetscNew(&MatSolverTypeHolders->handlers)); 4508 PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype)); 4509 MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor; 4510 PetscFunctionReturn(PETSC_SUCCESS); 4511 } 4512 while (next) { 4513 PetscCall(PetscStrcasecmp(package, next->name, &flg)); 4514 if (flg) { 4515 PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers"); 4516 inext = next->handlers; 4517 while (inext) { 4518 PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg)); 4519 if (flg) { 4520 inext->createfactor[(int)ftype - 1] = createfactor; 4521 PetscFunctionReturn(PETSC_SUCCESS); 4522 } 4523 iprev = inext; 4524 inext = inext->next; 4525 } 4526 PetscCall(PetscNew(&iprev->next)); 4527 PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype)); 4528 iprev->next->createfactor[(int)ftype - 1] = createfactor; 4529 PetscFunctionReturn(PETSC_SUCCESS); 4530 } 4531 prev = next; 4532 next = next->next; 4533 } 4534 PetscCall(PetscNew(&prev->next)); 4535 PetscCall(PetscStrallocpy(package, &prev->next->name)); 4536 PetscCall(PetscNew(&prev->next->handlers)); 4537 PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype)); 4538 prev->next->handlers->createfactor[(int)ftype - 1] = createfactor; 4539 PetscFunctionReturn(PETSC_SUCCESS); 4540 } 4541 4542 /*@C 4543 MatSolverTypeGet - Gets the function that creates the factor matrix if it exist 4544 4545 Input Parameters: 4546 + type - name of the package, for example petsc or superlu 4547 . ftype - the type of factorization supported by the type 4548 - mtype - the matrix type that works with this type 4549 4550 Output Parameters: 4551 + foundtype - `PETSC_TRUE` if the type was registered 4552 . foundmtype - `PETSC_TRUE` if the type supports the requested mtype 4553 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found 4554 4555 Level: developer 4556 4557 .seealso: [](chapter_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()` 4558 @*/ 4559 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *)) 4560 { 4561 MatSolverTypeHolder next = MatSolverTypeHolders; 4562 PetscBool flg; 4563 MatSolverTypeForSpecifcType inext; 4564 4565 PetscFunctionBegin; 4566 if (foundtype) *foundtype = PETSC_FALSE; 4567 if (foundmtype) *foundmtype = PETSC_FALSE; 4568 if (createfactor) *createfactor = NULL; 4569 4570 if (type) { 4571 while (next) { 4572 PetscCall(PetscStrcasecmp(type, next->name, &flg)); 4573 if (flg) { 4574 if (foundtype) *foundtype = PETSC_TRUE; 4575 inext = next->handlers; 4576 while (inext) { 4577 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4578 if (flg) { 4579 if (foundmtype) *foundmtype = PETSC_TRUE; 4580 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4581 PetscFunctionReturn(PETSC_SUCCESS); 4582 } 4583 inext = inext->next; 4584 } 4585 } 4586 next = next->next; 4587 } 4588 } else { 4589 while (next) { 4590 inext = next->handlers; 4591 while (inext) { 4592 PetscCall(PetscStrcmp(mtype, inext->mtype, &flg)); 4593 if (flg && inext->createfactor[(int)ftype - 1]) { 4594 if (foundtype) *foundtype = PETSC_TRUE; 4595 if (foundmtype) *foundmtype = PETSC_TRUE; 4596 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4597 PetscFunctionReturn(PETSC_SUCCESS); 4598 } 4599 inext = inext->next; 4600 } 4601 next = next->next; 4602 } 4603 /* try with base classes inext->mtype */ 4604 next = MatSolverTypeHolders; 4605 while (next) { 4606 inext = next->handlers; 4607 while (inext) { 4608 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4609 if (flg && inext->createfactor[(int)ftype - 1]) { 4610 if (foundtype) *foundtype = PETSC_TRUE; 4611 if (foundmtype) *foundmtype = PETSC_TRUE; 4612 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4613 PetscFunctionReturn(PETSC_SUCCESS); 4614 } 4615 inext = inext->next; 4616 } 4617 next = next->next; 4618 } 4619 } 4620 PetscFunctionReturn(PETSC_SUCCESS); 4621 } 4622 4623 PetscErrorCode MatSolverTypeDestroy(void) 4624 { 4625 MatSolverTypeHolder next = MatSolverTypeHolders, prev; 4626 MatSolverTypeForSpecifcType inext, iprev; 4627 4628 PetscFunctionBegin; 4629 while (next) { 4630 PetscCall(PetscFree(next->name)); 4631 inext = next->handlers; 4632 while (inext) { 4633 PetscCall(PetscFree(inext->mtype)); 4634 iprev = inext; 4635 inext = inext->next; 4636 PetscCall(PetscFree(iprev)); 4637 } 4638 prev = next; 4639 next = next->next; 4640 PetscCall(PetscFree(prev)); 4641 } 4642 MatSolverTypeHolders = NULL; 4643 PetscFunctionReturn(PETSC_SUCCESS); 4644 } 4645 4646 /*@C 4647 MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4648 4649 Logically Collective 4650 4651 Input Parameter: 4652 . mat - the matrix 4653 4654 Output Parameter: 4655 . flg - `PETSC_TRUE` if uses the ordering 4656 4657 Level: developer 4658 4659 Note: 4660 Most internal PETSc factorizations use the ordering passed to the factorization routine but external 4661 packages do not, thus we want to skip generating the ordering when it is not needed or used. 4662 4663 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4664 @*/ 4665 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg) 4666 { 4667 PetscFunctionBegin; 4668 *flg = mat->canuseordering; 4669 PetscFunctionReturn(PETSC_SUCCESS); 4670 } 4671 4672 /*@C 4673 MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object 4674 4675 Logically Collective 4676 4677 Input Parameters: 4678 + mat - the matrix obtained with `MatGetFactor()` 4679 - ftype - the factorization type to be used 4680 4681 Output Parameter: 4682 . otype - the preferred ordering type 4683 4684 Level: developer 4685 4686 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4687 @*/ 4688 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype) 4689 { 4690 PetscFunctionBegin; 4691 *otype = mat->preferredordering[ftype]; 4692 PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering"); 4693 PetscFunctionReturn(PETSC_SUCCESS); 4694 } 4695 4696 /*@C 4697 MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic() 4698 4699 Collective 4700 4701 Input Parameters: 4702 + mat - the matrix 4703 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4704 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4705 4706 Output Parameter: 4707 . f - the factor matrix used with MatXXFactorSymbolic() calls 4708 4709 Options Database Key: 4710 . -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory. 4711 One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices. 4712 4713 Level: intermediate 4714 4715 Notes: 4716 Users usually access the factorization solvers via `KSP` 4717 4718 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4719 such as pastix, superlu, mumps etc. 4720 4721 PETSc must have been ./configure to use the external solver, using the option --download-package 4722 4723 Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption 4724 where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set 4725 call `MatSetOptionsPrefixFactor()` on the originating matrix or `MatSetOptionsPrefix()` on the resulting factor matrix. 4726 4727 Developer Note: 4728 This should actually be called `MatCreateFactor()` since it creates a new factor object 4729 4730 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, 4731 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4732 @*/ 4733 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f) 4734 { 4735 PetscBool foundtype, foundmtype; 4736 PetscErrorCode (*conv)(Mat, MatFactorType, Mat *); 4737 4738 PetscFunctionBegin; 4739 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4740 PetscValidType(mat, 1); 4741 4742 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4743 MatCheckPreallocated(mat, 1); 4744 4745 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv)); 4746 if (!foundtype) { 4747 if (type) { 4748 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], 4749 ((PetscObject)mat)->type_name, type); 4750 } else { 4751 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); 4752 } 4753 } 4754 PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name); 4755 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); 4756 4757 PetscCall((*conv)(mat, ftype, f)); 4758 if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix)); 4759 PetscFunctionReturn(PETSC_SUCCESS); 4760 } 4761 4762 /*@C 4763 MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type 4764 4765 Not Collective 4766 4767 Input Parameters: 4768 + mat - the matrix 4769 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4770 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4771 4772 Output Parameter: 4773 . flg - PETSC_TRUE if the factorization is available 4774 4775 Level: intermediate 4776 4777 Notes: 4778 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4779 such as pastix, superlu, mumps etc. 4780 4781 PETSc must have been ./configure to use the external solver, using the option --download-package 4782 4783 Developer Note: 4784 This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object 4785 4786 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactor()`, `MatSolverTypeRegister()`, 4787 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4788 @*/ 4789 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg) 4790 { 4791 PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *); 4792 4793 PetscFunctionBegin; 4794 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4795 PetscValidType(mat, 1); 4796 PetscValidBoolPointer(flg, 4); 4797 4798 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4799 MatCheckPreallocated(mat, 1); 4800 4801 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv)); 4802 *flg = gconv ? PETSC_TRUE : PETSC_FALSE; 4803 PetscFunctionReturn(PETSC_SUCCESS); 4804 } 4805 4806 /*@ 4807 MatDuplicate - Duplicates a matrix including the non-zero structure. 4808 4809 Collective 4810 4811 Input Parameters: 4812 + mat - the matrix 4813 - op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`. 4814 See the manual page for `MatDuplicateOption()` for an explanation of these options. 4815 4816 Output Parameter: 4817 . M - pointer to place new matrix 4818 4819 Level: intermediate 4820 4821 Notes: 4822 You cannot change the nonzero pattern for the parent or child matrix if you use `MAT_SHARE_NONZERO_PATTERN`. 4823 4824 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. 4825 4826 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 4827 is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated. 4828 User should not use `MatDuplicate()` to create new matrix M if M is intended to be reused as the product of matrix operation. 4829 4830 .seealso: [](chapter_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption` 4831 @*/ 4832 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M) 4833 { 4834 Mat B; 4835 VecType vtype; 4836 PetscInt i; 4837 PetscObject dm; 4838 void (*viewf)(void); 4839 4840 PetscFunctionBegin; 4841 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4842 PetscValidType(mat, 1); 4843 PetscValidPointer(M, 3); 4844 PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix"); 4845 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4846 MatCheckPreallocated(mat, 1); 4847 4848 *M = NULL; 4849 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4850 PetscUseTypeMethod(mat, duplicate, op, M); 4851 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4852 B = *M; 4853 4854 PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf)); 4855 if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf)); 4856 PetscCall(MatGetVecType(mat, &vtype)); 4857 PetscCall(MatSetVecType(B, vtype)); 4858 4859 B->stencil.dim = mat->stencil.dim; 4860 B->stencil.noc = mat->stencil.noc; 4861 for (i = 0; i <= mat->stencil.dim; i++) { 4862 B->stencil.dims[i] = mat->stencil.dims[i]; 4863 B->stencil.starts[i] = mat->stencil.starts[i]; 4864 } 4865 4866 B->nooffproczerorows = mat->nooffproczerorows; 4867 B->nooffprocentries = mat->nooffprocentries; 4868 4869 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm)); 4870 if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm)); 4871 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4872 PetscFunctionReturn(PETSC_SUCCESS); 4873 } 4874 4875 /*@ 4876 MatGetDiagonal - Gets the diagonal of a matrix as a `Vec` 4877 4878 Logically Collective 4879 4880 Input Parameter: 4881 . mat - the matrix 4882 4883 Output Parameter: 4884 . v - the diagonal of the matrix 4885 4886 Level: intermediate 4887 4888 Note: 4889 Currently only correct in parallel for square matrices. 4890 4891 .seealso: [](chapter_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()` 4892 @*/ 4893 PetscErrorCode MatGetDiagonal(Mat mat, Vec v) 4894 { 4895 PetscFunctionBegin; 4896 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4897 PetscValidType(mat, 1); 4898 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4899 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4900 MatCheckPreallocated(mat, 1); 4901 4902 PetscUseTypeMethod(mat, getdiagonal, v); 4903 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4904 PetscFunctionReturn(PETSC_SUCCESS); 4905 } 4906 4907 /*@C 4908 MatGetRowMin - Gets the minimum value (of the real part) of each 4909 row of the matrix 4910 4911 Logically Collective 4912 4913 Input Parameter: 4914 . mat - the matrix 4915 4916 Output Parameters: 4917 + v - the vector for storing the maximums 4918 - idx - the indices of the column found for each row (optional) 4919 4920 Level: intermediate 4921 4922 Note: 4923 The result of this call are the same as if one converted the matrix to dense format 4924 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 4925 4926 This code is only implemented for a couple of matrix formats. 4927 4928 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, 4929 `MatGetRowMax()` 4930 @*/ 4931 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[]) 4932 { 4933 PetscFunctionBegin; 4934 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4935 PetscValidType(mat, 1); 4936 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4937 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4938 4939 if (!mat->cmap->N) { 4940 PetscCall(VecSet(v, PETSC_MAX_REAL)); 4941 if (idx) { 4942 PetscInt i, m = mat->rmap->n; 4943 for (i = 0; i < m; i++) idx[i] = -1; 4944 } 4945 } else { 4946 MatCheckPreallocated(mat, 1); 4947 } 4948 PetscUseTypeMethod(mat, getrowmin, v, idx); 4949 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4950 PetscFunctionReturn(PETSC_SUCCESS); 4951 } 4952 4953 /*@C 4954 MatGetRowMinAbs - Gets the minimum value (in absolute value) of each 4955 row of the matrix 4956 4957 Logically Collective 4958 4959 Input Parameter: 4960 . mat - the matrix 4961 4962 Output Parameters: 4963 + v - the vector for storing the minimums 4964 - idx - the indices of the column found for each row (or `NULL` if not needed) 4965 4966 Level: intermediate 4967 4968 Notes: 4969 if a row is completely empty or has only 0.0 values then the idx[] value for that 4970 row is 0 (the first column). 4971 4972 This code is only implemented for a couple of matrix formats. 4973 4974 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()` 4975 @*/ 4976 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[]) 4977 { 4978 PetscFunctionBegin; 4979 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4980 PetscValidType(mat, 1); 4981 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4982 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4983 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4984 4985 if (!mat->cmap->N) { 4986 PetscCall(VecSet(v, 0.0)); 4987 if (idx) { 4988 PetscInt i, m = mat->rmap->n; 4989 for (i = 0; i < m; i++) idx[i] = -1; 4990 } 4991 } else { 4992 MatCheckPreallocated(mat, 1); 4993 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 4994 PetscUseTypeMethod(mat, getrowminabs, v, idx); 4995 } 4996 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4997 PetscFunctionReturn(PETSC_SUCCESS); 4998 } 4999 5000 /*@C 5001 MatGetRowMax - Gets the maximum value (of the real part) of each 5002 row of the matrix 5003 5004 Logically Collective 5005 5006 Input Parameter: 5007 . mat - the matrix 5008 5009 Output Parameters: 5010 + v - the vector for storing the maximums 5011 - idx - the indices of the column found for each row (optional) 5012 5013 Level: intermediate 5014 5015 Notes: 5016 The result of this call are the same as if one converted the matrix to dense format 5017 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5018 5019 This code is only implemented for a couple of matrix formats. 5020 5021 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5022 @*/ 5023 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[]) 5024 { 5025 PetscFunctionBegin; 5026 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5027 PetscValidType(mat, 1); 5028 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5029 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5030 5031 if (!mat->cmap->N) { 5032 PetscCall(VecSet(v, PETSC_MIN_REAL)); 5033 if (idx) { 5034 PetscInt i, m = mat->rmap->n; 5035 for (i = 0; i < m; i++) idx[i] = -1; 5036 } 5037 } else { 5038 MatCheckPreallocated(mat, 1); 5039 PetscUseTypeMethod(mat, getrowmax, v, idx); 5040 } 5041 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5042 PetscFunctionReturn(PETSC_SUCCESS); 5043 } 5044 5045 /*@C 5046 MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each 5047 row of the matrix 5048 5049 Logically Collective 5050 5051 Input Parameter: 5052 . mat - the matrix 5053 5054 Output Parameters: 5055 + v - the vector for storing the maximums 5056 - idx - the indices of the column found for each row (or `NULL` if not needed) 5057 5058 Level: intermediate 5059 5060 Notes: 5061 if a row is completely empty or has only 0.0 values then the idx[] value for that 5062 row is 0 (the first column). 5063 5064 This code is only implemented for a couple of matrix formats. 5065 5066 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5067 @*/ 5068 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[]) 5069 { 5070 PetscFunctionBegin; 5071 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5072 PetscValidType(mat, 1); 5073 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5074 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5075 5076 if (!mat->cmap->N) { 5077 PetscCall(VecSet(v, 0.0)); 5078 if (idx) { 5079 PetscInt i, m = mat->rmap->n; 5080 for (i = 0; i < m; i++) idx[i] = -1; 5081 } 5082 } else { 5083 MatCheckPreallocated(mat, 1); 5084 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5085 PetscUseTypeMethod(mat, getrowmaxabs, v, idx); 5086 } 5087 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5088 PetscFunctionReturn(PETSC_SUCCESS); 5089 } 5090 5091 /*@ 5092 MatGetRowSum - Gets the sum of each row of the matrix 5093 5094 Logically or Neighborhood Collective 5095 5096 Input Parameter: 5097 . mat - the matrix 5098 5099 Output Parameter: 5100 . v - the vector for storing the sum of rows 5101 5102 Level: intermediate 5103 5104 Notes: 5105 This code is slow since it is not currently specialized for different formats 5106 5107 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()` 5108 @*/ 5109 PetscErrorCode MatGetRowSum(Mat mat, Vec v) 5110 { 5111 Vec ones; 5112 5113 PetscFunctionBegin; 5114 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5115 PetscValidType(mat, 1); 5116 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5117 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5118 MatCheckPreallocated(mat, 1); 5119 PetscCall(MatCreateVecs(mat, &ones, NULL)); 5120 PetscCall(VecSet(ones, 1.)); 5121 PetscCall(MatMult(mat, ones, v)); 5122 PetscCall(VecDestroy(&ones)); 5123 PetscFunctionReturn(PETSC_SUCCESS); 5124 } 5125 5126 /*@ 5127 MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) 5128 when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B) 5129 5130 Collective 5131 5132 Input Parameter: 5133 . mat - the matrix to provide the transpose 5134 5135 Output Parameter: 5136 . 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 5137 5138 Level: advanced 5139 5140 Note: 5141 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 5142 routine allows bypassing that call. 5143 5144 .seealso: [](chapter_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5145 @*/ 5146 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B) 5147 { 5148 PetscContainer rB = NULL; 5149 MatParentState *rb = NULL; 5150 5151 PetscFunctionBegin; 5152 PetscCall(PetscNew(&rb)); 5153 rb->id = ((PetscObject)mat)->id; 5154 rb->state = 0; 5155 PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate)); 5156 PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB)); 5157 PetscCall(PetscContainerSetPointer(rB, rb)); 5158 PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault)); 5159 PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB)); 5160 PetscCall(PetscObjectDereference((PetscObject)rB)); 5161 PetscFunctionReturn(PETSC_SUCCESS); 5162 } 5163 5164 /*@ 5165 MatTranspose - Computes an in-place or out-of-place transpose of a matrix. 5166 5167 Collective 5168 5169 Input Parameters: 5170 + mat - the matrix to transpose 5171 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5172 5173 Output Parameter: 5174 . B - the transpose 5175 5176 Level: intermediate 5177 5178 Notes: 5179 If you use `MAT_INPLACE_MATRIX` then you must pass in &mat for B 5180 5181 `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 5182 transpose, call `MatTransposeSetPrecursor`(mat,B) before calling this routine. 5183 5184 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. 5185 5186 Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed. 5187 5188 If mat is unchanged from the last call this function returns immediately without recomputing the result 5189 5190 If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()` 5191 5192 .seealso: [](chapter_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`, 5193 `MatTransposeSymbolic()`, `MatCreateTranspose()` 5194 @*/ 5195 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B) 5196 { 5197 PetscContainer rB = NULL; 5198 MatParentState *rb = NULL; 5199 5200 PetscFunctionBegin; 5201 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5202 PetscValidType(mat, 1); 5203 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5204 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5205 PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first"); 5206 PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX"); 5207 MatCheckPreallocated(mat, 1); 5208 if (reuse == MAT_REUSE_MATRIX) { 5209 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5210 PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor()."); 5211 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5212 PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5213 if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS); 5214 } 5215 5216 PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0)); 5217 if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) { 5218 PetscUseTypeMethod(mat, transpose, reuse, B); 5219 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5220 } 5221 PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0)); 5222 5223 if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B)); 5224 if (reuse != MAT_INPLACE_MATRIX) { 5225 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5226 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5227 rb->state = ((PetscObject)mat)->state; 5228 rb->nonzerostate = mat->nonzerostate; 5229 } 5230 PetscFunctionReturn(PETSC_SUCCESS); 5231 } 5232 5233 /*@ 5234 MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix. 5235 5236 Collective 5237 5238 Input Parameter: 5239 . A - the matrix to transpose 5240 5241 Output Parameter: 5242 . 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 5243 numerical portion. 5244 5245 Level: intermediate 5246 5247 Note: 5248 This is not supported for many matrix types, use `MatTranspose()` in those cases 5249 5250 .seealso: [](chapter_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5251 @*/ 5252 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B) 5253 { 5254 PetscFunctionBegin; 5255 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5256 PetscValidType(A, 1); 5257 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5258 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5259 PetscCheck(A->ops->transposesymbolic, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 5260 PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0)); 5261 PetscCall((*A->ops->transposesymbolic)(A, B)); 5262 PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0)); 5263 5264 PetscCall(MatTransposeSetPrecursor(A, *B)); 5265 PetscFunctionReturn(PETSC_SUCCESS); 5266 } 5267 5268 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B) 5269 { 5270 PetscContainer rB; 5271 MatParentState *rb; 5272 5273 PetscFunctionBegin; 5274 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5275 PetscValidType(A, 1); 5276 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5277 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5278 PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB)); 5279 PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()"); 5280 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5281 PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5282 PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure"); 5283 PetscFunctionReturn(PETSC_SUCCESS); 5284 } 5285 5286 /*@ 5287 MatIsTranspose - Test whether a matrix is another one's transpose, 5288 or its own, in which case it tests symmetry. 5289 5290 Collective 5291 5292 Input Parameters: 5293 + A - the matrix to test 5294 . B - the matrix to test against, this can equal the first parameter 5295 - tol - tolerance, differences between entries smaller than this are counted as zero 5296 5297 Output Parameter: 5298 . flg - the result 5299 5300 Level: intermediate 5301 5302 Notes: 5303 Only available for `MATAIJ` matrices. 5304 5305 The sequential algorithm has a running time of the order of the number of nonzeros; the parallel 5306 test involves parallel copies of the block-offdiagonal parts of the matrix. 5307 5308 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()` 5309 @*/ 5310 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5311 { 5312 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5313 5314 PetscFunctionBegin; 5315 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5316 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5317 PetscValidBoolPointer(flg, 4); 5318 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f)); 5319 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g)); 5320 *flg = PETSC_FALSE; 5321 if (f && g) { 5322 PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test"); 5323 PetscCall((*f)(A, B, tol, flg)); 5324 } else { 5325 MatType mattype; 5326 5327 PetscCall(MatGetType(f ? B : A, &mattype)); 5328 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype); 5329 } 5330 PetscFunctionReturn(PETSC_SUCCESS); 5331 } 5332 5333 /*@ 5334 MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate. 5335 5336 Collective 5337 5338 Input Parameters: 5339 + mat - the matrix to transpose and complex conjugate 5340 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5341 5342 Output Parameter: 5343 . B - the Hermitian transpose 5344 5345 Level: intermediate 5346 5347 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse` 5348 @*/ 5349 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B) 5350 { 5351 PetscFunctionBegin; 5352 PetscCall(MatTranspose(mat, reuse, B)); 5353 #if defined(PETSC_USE_COMPLEX) 5354 PetscCall(MatConjugate(*B)); 5355 #endif 5356 PetscFunctionReturn(PETSC_SUCCESS); 5357 } 5358 5359 /*@ 5360 MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose, 5361 5362 Collective 5363 5364 Input Parameters: 5365 + A - the matrix to test 5366 . B - the matrix to test against, this can equal the first parameter 5367 - tol - tolerance, differences between entries smaller than this are counted as zero 5368 5369 Output Parameter: 5370 . flg - the result 5371 5372 Level: intermediate 5373 5374 Notes: 5375 Only available for `MATAIJ` matrices. 5376 5377 The sequential algorithm 5378 has a running time of the order of the number of nonzeros; the parallel 5379 test involves parallel copies of the block-offdiagonal parts of the matrix. 5380 5381 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()` 5382 @*/ 5383 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5384 { 5385 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5386 5387 PetscFunctionBegin; 5388 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5389 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5390 PetscValidBoolPointer(flg, 4); 5391 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f)); 5392 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g)); 5393 if (f && g) { 5394 PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test"); 5395 PetscCall((*f)(A, B, tol, flg)); 5396 } 5397 PetscFunctionReturn(PETSC_SUCCESS); 5398 } 5399 5400 /*@ 5401 MatPermute - Creates a new matrix with rows and columns permuted from the 5402 original. 5403 5404 Collective 5405 5406 Input Parameters: 5407 + mat - the matrix to permute 5408 . row - row permutation, each processor supplies only the permutation for its rows 5409 - col - column permutation, each processor supplies only the permutation for its columns 5410 5411 Output Parameter: 5412 . B - the permuted matrix 5413 5414 Level: advanced 5415 5416 Note: 5417 The index sets map from row/col of permuted matrix to row/col of original matrix. 5418 The index sets should be on the same communicator as mat and have the same local sizes. 5419 5420 Developer Note: 5421 If you want to implement `MatPermute()` for a matrix type, and your approach doesn't 5422 exploit the fact that row and col are permutations, consider implementing the 5423 more general `MatCreateSubMatrix()` instead. 5424 5425 .seealso: [](chapter_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()` 5426 @*/ 5427 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B) 5428 { 5429 PetscFunctionBegin; 5430 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5431 PetscValidType(mat, 1); 5432 PetscValidHeaderSpecific(row, IS_CLASSID, 2); 5433 PetscValidHeaderSpecific(col, IS_CLASSID, 3); 5434 PetscValidPointer(B, 4); 5435 PetscCheckSameComm(mat, 1, row, 2); 5436 if (row != col) PetscCheckSameComm(row, 2, col, 3); 5437 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5438 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5439 PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name); 5440 MatCheckPreallocated(mat, 1); 5441 5442 if (mat->ops->permute) { 5443 PetscUseTypeMethod(mat, permute, row, col, B); 5444 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5445 } else { 5446 PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B)); 5447 } 5448 PetscFunctionReturn(PETSC_SUCCESS); 5449 } 5450 5451 /*@ 5452 MatEqual - Compares two matrices. 5453 5454 Collective 5455 5456 Input Parameters: 5457 + A - the first matrix 5458 - B - the second matrix 5459 5460 Output Parameter: 5461 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise. 5462 5463 Level: intermediate 5464 5465 .seealso: [](chapter_matrices), `Mat` 5466 @*/ 5467 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg) 5468 { 5469 PetscFunctionBegin; 5470 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5471 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5472 PetscValidType(A, 1); 5473 PetscValidType(B, 2); 5474 PetscValidBoolPointer(flg, 3); 5475 PetscCheckSameComm(A, 1, B, 2); 5476 MatCheckPreallocated(A, 1); 5477 MatCheckPreallocated(B, 2); 5478 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5479 PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5480 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, 5481 B->cmap->N); 5482 if (A->ops->equal && A->ops->equal == B->ops->equal) { 5483 PetscUseTypeMethod(A, equal, B, flg); 5484 } else { 5485 PetscCall(MatMultEqual(A, B, 10, flg)); 5486 } 5487 PetscFunctionReturn(PETSC_SUCCESS); 5488 } 5489 5490 /*@ 5491 MatDiagonalScale - Scales a matrix on the left and right by diagonal 5492 matrices that are stored as vectors. Either of the two scaling 5493 matrices can be `NULL`. 5494 5495 Collective 5496 5497 Input Parameters: 5498 + mat - the matrix to be scaled 5499 . l - the left scaling vector (or `NULL`) 5500 - r - the right scaling vector (or `NULL`) 5501 5502 Level: intermediate 5503 5504 Note: 5505 `MatDiagonalScale()` computes A = LAR, where 5506 L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector) 5507 The L scales the rows of the matrix, the R scales the columns of the matrix. 5508 5509 .seealso: [](chapter_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()` 5510 @*/ 5511 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r) 5512 { 5513 PetscFunctionBegin; 5514 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5515 PetscValidType(mat, 1); 5516 if (l) { 5517 PetscValidHeaderSpecific(l, VEC_CLASSID, 2); 5518 PetscCheckSameComm(mat, 1, l, 2); 5519 } 5520 if (r) { 5521 PetscValidHeaderSpecific(r, VEC_CLASSID, 3); 5522 PetscCheckSameComm(mat, 1, r, 3); 5523 } 5524 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5525 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5526 MatCheckPreallocated(mat, 1); 5527 if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS); 5528 5529 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5530 PetscUseTypeMethod(mat, diagonalscale, l, r); 5531 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5532 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5533 if (l != r) mat->symmetric = PETSC_BOOL3_FALSE; 5534 PetscFunctionReturn(PETSC_SUCCESS); 5535 } 5536 5537 /*@ 5538 MatScale - Scales all elements of a matrix by a given number. 5539 5540 Logically Collective 5541 5542 Input Parameters: 5543 + mat - the matrix to be scaled 5544 - a - the scaling value 5545 5546 Level: intermediate 5547 5548 .seealso: [](chapter_matrices), `Mat`, `MatDiagonalScale()` 5549 @*/ 5550 PetscErrorCode MatScale(Mat mat, PetscScalar a) 5551 { 5552 PetscFunctionBegin; 5553 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5554 PetscValidType(mat, 1); 5555 PetscCheck(a == (PetscScalar)1.0 || mat->ops->scale, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 5556 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5557 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5558 PetscValidLogicalCollectiveScalar(mat, a, 2); 5559 MatCheckPreallocated(mat, 1); 5560 5561 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5562 if (a != (PetscScalar)1.0) { 5563 PetscUseTypeMethod(mat, scale, a); 5564 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5565 } 5566 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5567 PetscFunctionReturn(PETSC_SUCCESS); 5568 } 5569 5570 /*@ 5571 MatNorm - Calculates various norms of a matrix. 5572 5573 Collective 5574 5575 Input Parameters: 5576 + mat - the matrix 5577 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY` 5578 5579 Output Parameter: 5580 . nrm - the resulting norm 5581 5582 Level: intermediate 5583 5584 .seealso: [](chapter_matrices), `Mat` 5585 @*/ 5586 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm) 5587 { 5588 PetscFunctionBegin; 5589 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5590 PetscValidType(mat, 1); 5591 PetscValidRealPointer(nrm, 3); 5592 5593 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5594 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5595 MatCheckPreallocated(mat, 1); 5596 5597 PetscUseTypeMethod(mat, norm, type, nrm); 5598 PetscFunctionReturn(PETSC_SUCCESS); 5599 } 5600 5601 /* 5602 This variable is used to prevent counting of MatAssemblyBegin() that 5603 are called from within a MatAssemblyEnd(). 5604 */ 5605 static PetscInt MatAssemblyEnd_InUse = 0; 5606 /*@ 5607 MatAssemblyBegin - Begins assembling the matrix. This routine should 5608 be called after completing all calls to `MatSetValues()`. 5609 5610 Collective 5611 5612 Input Parameters: 5613 + mat - the matrix 5614 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5615 5616 Level: beginner 5617 5618 Notes: 5619 `MatSetValues()` generally caches the values that belong to other MPI ranks. The matrix is ready to 5620 use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called. 5621 5622 Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES` 5623 in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before 5624 using the matrix. 5625 5626 ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the 5627 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 5628 a global collective operation requiring all processes that share the matrix. 5629 5630 Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed 5631 out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros 5632 before `MAT_FINAL_ASSEMBLY` so the space is not compressed out. 5633 5634 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()` 5635 @*/ 5636 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type) 5637 { 5638 PetscFunctionBegin; 5639 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5640 PetscValidType(mat, 1); 5641 MatCheckPreallocated(mat, 1); 5642 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?"); 5643 if (mat->assembled) { 5644 mat->was_assembled = PETSC_TRUE; 5645 mat->assembled = PETSC_FALSE; 5646 } 5647 5648 if (!MatAssemblyEnd_InUse) { 5649 PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0)); 5650 PetscTryTypeMethod(mat, assemblybegin, type); 5651 PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0)); 5652 } else PetscTryTypeMethod(mat, assemblybegin, type); 5653 PetscFunctionReturn(PETSC_SUCCESS); 5654 } 5655 5656 /*@ 5657 MatAssembled - Indicates if a matrix has been assembled and is ready for 5658 use; for example, in matrix-vector product. 5659 5660 Not Collective 5661 5662 Input Parameter: 5663 . mat - the matrix 5664 5665 Output Parameter: 5666 . assembled - `PETSC_TRUE` or `PETSC_FALSE` 5667 5668 Level: advanced 5669 5670 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()` 5671 @*/ 5672 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled) 5673 { 5674 PetscFunctionBegin; 5675 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5676 PetscValidBoolPointer(assembled, 2); 5677 *assembled = mat->assembled; 5678 PetscFunctionReturn(PETSC_SUCCESS); 5679 } 5680 5681 /*@ 5682 MatAssemblyEnd - Completes assembling the matrix. This routine should 5683 be called after `MatAssemblyBegin()`. 5684 5685 Collective 5686 5687 Input Parameters: 5688 + mat - the matrix 5689 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5690 5691 Options Database Keys: 5692 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatEndAssembly()` 5693 . -mat_view ::ascii_info_detail - Prints more detailed info 5694 . -mat_view - Prints matrix in ASCII format 5695 . -mat_view ::ascii_matlab - Prints matrix in Matlab format 5696 . -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 5697 . -display <name> - Sets display name (default is host) 5698 . -draw_pause <sec> - Sets number of seconds to pause after display 5699 . -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See [Using MATLAB with PETSc](ch_matlab)) 5700 . -viewer_socket_machine <machine> - Machine to use for socket 5701 . -viewer_socket_port <port> - Port number to use for socket 5702 - -mat_view binary:filename[:append] - Save matrix to file in binary format 5703 5704 Level: beginner 5705 5706 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()` 5707 @*/ 5708 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type) 5709 { 5710 static PetscInt inassm = 0; 5711 PetscBool flg = PETSC_FALSE; 5712 5713 PetscFunctionBegin; 5714 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5715 PetscValidType(mat, 1); 5716 5717 inassm++; 5718 MatAssemblyEnd_InUse++; 5719 if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */ 5720 PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0)); 5721 PetscTryTypeMethod(mat, assemblyend, type); 5722 PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0)); 5723 } else PetscTryTypeMethod(mat, assemblyend, type); 5724 5725 /* Flush assembly is not a true assembly */ 5726 if (type != MAT_FLUSH_ASSEMBLY) { 5727 if (mat->num_ass) { 5728 if (!mat->symmetry_eternal) { 5729 mat->symmetric = PETSC_BOOL3_UNKNOWN; 5730 mat->hermitian = PETSC_BOOL3_UNKNOWN; 5731 } 5732 if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN; 5733 if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN; 5734 } 5735 mat->num_ass++; 5736 mat->assembled = PETSC_TRUE; 5737 mat->ass_nonzerostate = mat->nonzerostate; 5738 } 5739 5740 mat->insertmode = NOT_SET_VALUES; 5741 MatAssemblyEnd_InUse--; 5742 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5743 if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) { 5744 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 5745 5746 if (mat->checksymmetryonassembly) { 5747 PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg)); 5748 if (flg) { 5749 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5750 } else { 5751 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5752 } 5753 } 5754 if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL)); 5755 } 5756 inassm--; 5757 PetscFunctionReturn(PETSC_SUCCESS); 5758 } 5759 5760 /*@ 5761 MatSetOption - Sets a parameter option for a matrix. Some options 5762 may be specific to certain storage formats. Some options 5763 determine how values will be inserted (or added). Sorted, 5764 row-oriented input will generally assemble the fastest. The default 5765 is row-oriented. 5766 5767 Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption` 5768 5769 Input Parameters: 5770 + mat - the matrix 5771 . option - the option, one of those listed below (and possibly others), 5772 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5773 5774 Options Describing Matrix Structure: 5775 + `MAT_SPD` - symmetric positive definite 5776 . `MAT_SYMMETRIC` - symmetric in terms of both structure and value 5777 . `MAT_HERMITIAN` - transpose is the complex conjugation 5778 . `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure 5779 . `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix 5780 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix 5781 - `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix 5782 5783 These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they 5784 do not need to be computed (usually at a high cost) 5785 5786 Options For Use with `MatSetValues()`: 5787 Insert a logically dense subblock, which can be 5788 . `MAT_ROW_ORIENTED` - row-oriented (default) 5789 5790 These options reflect the data you pass in with `MatSetValues()`; it has 5791 nothing to do with how the data is stored internally in the matrix 5792 data structure. 5793 5794 When (re)assembling a matrix, we can restrict the input for 5795 efficiency/debugging purposes. These options include 5796 + `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow) 5797 . `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated 5798 . `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries 5799 . `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry 5800 . `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly 5801 . `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if 5802 any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves 5803 performance for very large process counts. 5804 - `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset 5805 of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly 5806 functions, instead sending only neighbor messages. 5807 5808 Level: intermediate 5809 5810 Notes: 5811 Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg! 5812 5813 Some options are relevant only for particular matrix types and 5814 are thus ignored by others. Other options are not supported by 5815 certain matrix types and will generate an error message if set. 5816 5817 If using Fortran to compute a matrix, one may need to 5818 use the column-oriented option (or convert to the row-oriented 5819 format). 5820 5821 `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion 5822 that would generate a new entry in the nonzero structure is instead 5823 ignored. Thus, if memory has not already been allocated for this particular 5824 data, then the insertion is ignored. For dense matrices, in which 5825 the entire array is allocated, no entries are ever ignored. 5826 Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction 5827 5828 `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion 5829 that would generate a new entry in the nonzero structure instead produces 5830 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 5831 5832 `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion 5833 that would generate a new entry that has not been preallocated will 5834 instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats 5835 only.) This is a useful flag when debugging matrix memory preallocation. 5836 If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 5837 5838 `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for 5839 other processors should be dropped, rather than stashed. 5840 This is useful if you know that the "owning" processor is also 5841 always generating the correct matrix entries, so that PETSc need 5842 not transfer duplicate entries generated on another processor. 5843 5844 `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the 5845 searches during matrix assembly. When this flag is set, the hash table 5846 is created during the first matrix assembly. This hash table is 5847 used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()` 5848 to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag 5849 should be used with `MAT_USE_HASH_TABLE` flag. This option is currently 5850 supported by `MATMPIBAIJ` format only. 5851 5852 `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries 5853 are kept in the nonzero structure 5854 5855 `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating 5856 a zero location in the matrix 5857 5858 `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types 5859 5860 `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the 5861 zero row routines and thus improves performance for very large process counts. 5862 5863 `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular 5864 part of the matrix (since they should match the upper triangular part). 5865 5866 `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a 5867 single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common 5868 with finite difference schemes with non-periodic boundary conditions. 5869 5870 Developer Note: 5871 `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other 5872 places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRIC` or `MAT_SPD` would need to be changed back 5873 to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had 5874 not changed. 5875 5876 .seealso: [](chapter_matrices), `MatOption`, `Mat`, `MatGetOption()` 5877 @*/ 5878 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg) 5879 { 5880 PetscFunctionBegin; 5881 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5882 if (op > 0) { 5883 PetscValidLogicalCollectiveEnum(mat, op, 2); 5884 PetscValidLogicalCollectiveBool(mat, flg, 3); 5885 } 5886 5887 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); 5888 5889 switch (op) { 5890 case MAT_FORCE_DIAGONAL_ENTRIES: 5891 mat->force_diagonals = flg; 5892 PetscFunctionReturn(PETSC_SUCCESS); 5893 case MAT_NO_OFF_PROC_ENTRIES: 5894 mat->nooffprocentries = flg; 5895 PetscFunctionReturn(PETSC_SUCCESS); 5896 case MAT_SUBSET_OFF_PROC_ENTRIES: 5897 mat->assembly_subset = flg; 5898 if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */ 5899 #if !defined(PETSC_HAVE_MPIUNI) 5900 PetscCall(MatStashScatterDestroy_BTS(&mat->stash)); 5901 #endif 5902 mat->stash.first_assembly_done = PETSC_FALSE; 5903 } 5904 PetscFunctionReturn(PETSC_SUCCESS); 5905 case MAT_NO_OFF_PROC_ZERO_ROWS: 5906 mat->nooffproczerorows = flg; 5907 PetscFunctionReturn(PETSC_SUCCESS); 5908 case MAT_SPD: 5909 if (flg) { 5910 mat->spd = PETSC_BOOL3_TRUE; 5911 mat->symmetric = PETSC_BOOL3_TRUE; 5912 mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5913 } else { 5914 mat->spd = PETSC_BOOL3_FALSE; 5915 } 5916 break; 5917 case MAT_SYMMETRIC: 5918 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5919 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5920 #if !defined(PETSC_USE_COMPLEX) 5921 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5922 #endif 5923 break; 5924 case MAT_HERMITIAN: 5925 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5926 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5927 #if !defined(PETSC_USE_COMPLEX) 5928 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5929 #endif 5930 break; 5931 case MAT_STRUCTURALLY_SYMMETRIC: 5932 mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5933 break; 5934 case MAT_SYMMETRY_ETERNAL: 5935 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"); 5936 mat->symmetry_eternal = flg; 5937 if (flg) mat->structural_symmetry_eternal = PETSC_TRUE; 5938 break; 5939 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 5940 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"); 5941 mat->structural_symmetry_eternal = flg; 5942 break; 5943 case MAT_SPD_ETERNAL: 5944 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"); 5945 mat->spd_eternal = flg; 5946 if (flg) { 5947 mat->structural_symmetry_eternal = PETSC_TRUE; 5948 mat->symmetry_eternal = PETSC_TRUE; 5949 } 5950 break; 5951 case MAT_STRUCTURE_ONLY: 5952 mat->structure_only = flg; 5953 break; 5954 case MAT_SORTED_FULL: 5955 mat->sortedfull = flg; 5956 break; 5957 default: 5958 break; 5959 } 5960 PetscTryTypeMethod(mat, setoption, op, flg); 5961 PetscFunctionReturn(PETSC_SUCCESS); 5962 } 5963 5964 /*@ 5965 MatGetOption - Gets a parameter option that has been set for a matrix. 5966 5967 Logically Collective 5968 5969 Input Parameters: 5970 + mat - the matrix 5971 - option - the option, this only responds to certain options, check the code for which ones 5972 5973 Output Parameter: 5974 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5975 5976 Level: intermediate 5977 5978 Notes: 5979 Can only be called after `MatSetSizes()` and `MatSetType()` have been set. 5980 5981 Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or 5982 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 5983 5984 .seealso: [](chapter_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, 5985 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 5986 @*/ 5987 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg) 5988 { 5989 PetscFunctionBegin; 5990 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5991 PetscValidType(mat, 1); 5992 5993 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); 5994 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()"); 5995 5996 switch (op) { 5997 case MAT_NO_OFF_PROC_ENTRIES: 5998 *flg = mat->nooffprocentries; 5999 break; 6000 case MAT_NO_OFF_PROC_ZERO_ROWS: 6001 *flg = mat->nooffproczerorows; 6002 break; 6003 case MAT_SYMMETRIC: 6004 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()"); 6005 break; 6006 case MAT_HERMITIAN: 6007 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()"); 6008 break; 6009 case MAT_STRUCTURALLY_SYMMETRIC: 6010 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()"); 6011 break; 6012 case MAT_SPD: 6013 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()"); 6014 break; 6015 case MAT_SYMMETRY_ETERNAL: 6016 *flg = mat->symmetry_eternal; 6017 break; 6018 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6019 *flg = mat->symmetry_eternal; 6020 break; 6021 default: 6022 break; 6023 } 6024 PetscFunctionReturn(PETSC_SUCCESS); 6025 } 6026 6027 /*@ 6028 MatZeroEntries - Zeros all entries of a matrix. For sparse matrices 6029 this routine retains the old nonzero structure. 6030 6031 Logically Collective 6032 6033 Input Parameter: 6034 . mat - the matrix 6035 6036 Level: intermediate 6037 6038 Note: 6039 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. 6040 See the Performance chapter of the users manual for information on preallocating matrices. 6041 6042 .seealso: [](chapter_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()` 6043 @*/ 6044 PetscErrorCode MatZeroEntries(Mat mat) 6045 { 6046 PetscFunctionBegin; 6047 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6048 PetscValidType(mat, 1); 6049 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6050 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"); 6051 MatCheckPreallocated(mat, 1); 6052 6053 PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0)); 6054 PetscUseTypeMethod(mat, zeroentries); 6055 PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0)); 6056 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6057 PetscFunctionReturn(PETSC_SUCCESS); 6058 } 6059 6060 /*@ 6061 MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal) 6062 of a set of rows and columns of a matrix. 6063 6064 Collective 6065 6066 Input Parameters: 6067 + mat - the matrix 6068 . numRows - the number of rows/columns to zero 6069 . rows - the global row indices 6070 . diag - value put in the diagonal of the eliminated rows 6071 . x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call 6072 - b - optional vector of the right hand side, that will be adjusted by provided solution entries 6073 6074 Level: intermediate 6075 6076 Notes: 6077 This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6078 6079 For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`. 6080 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 6081 6082 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6083 Krylov method to take advantage of the known solution on the zeroed rows. 6084 6085 For the parallel case, all processes that share the matrix (i.e., 6086 those in the communicator used for matrix creation) MUST call this 6087 routine, regardless of whether any rows being zeroed are owned by 6088 them. 6089 6090 Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix. 6091 6092 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6093 list only rows local to itself). 6094 6095 The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine. 6096 6097 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6098 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6099 @*/ 6100 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6101 { 6102 PetscFunctionBegin; 6103 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6104 PetscValidType(mat, 1); 6105 if (numRows) PetscValidIntPointer(rows, 3); 6106 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6107 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6108 MatCheckPreallocated(mat, 1); 6109 6110 PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b); 6111 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6112 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6113 PetscFunctionReturn(PETSC_SUCCESS); 6114 } 6115 6116 /*@ 6117 MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal) 6118 of a set of rows and columns of a matrix. 6119 6120 Collective 6121 6122 Input Parameters: 6123 + mat - the matrix 6124 . is - the rows to zero 6125 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6126 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6127 - b - optional vector of right hand side, that will be adjusted by provided solution 6128 6129 Level: intermediate 6130 6131 Note: 6132 See `MatZeroRowsColumns()` for details on how this routine operates. 6133 6134 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6135 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()` 6136 @*/ 6137 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6138 { 6139 PetscInt numRows; 6140 const PetscInt *rows; 6141 6142 PetscFunctionBegin; 6143 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6144 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6145 PetscValidType(mat, 1); 6146 PetscValidType(is, 2); 6147 PetscCall(ISGetLocalSize(is, &numRows)); 6148 PetscCall(ISGetIndices(is, &rows)); 6149 PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b)); 6150 PetscCall(ISRestoreIndices(is, &rows)); 6151 PetscFunctionReturn(PETSC_SUCCESS); 6152 } 6153 6154 /*@ 6155 MatZeroRows - Zeros all entries (except possibly the main diagonal) 6156 of a set of rows of a matrix. 6157 6158 Collective 6159 6160 Input Parameters: 6161 + mat - the matrix 6162 . numRows - the number of rows to zero 6163 . rows - the global row indices 6164 . diag - value put in the diagonal of the zeroed rows 6165 . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call 6166 - b - optional vector of right hand side, that will be adjusted by provided solution entries 6167 6168 Level: intermediate 6169 6170 Notes: 6171 This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6172 6173 For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`. 6174 6175 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6176 Krylov method to take advantage of the known solution on the zeroed rows. 6177 6178 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) 6179 from the matrix. 6180 6181 Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix 6182 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 6183 formats this does not alter the nonzero structure. 6184 6185 If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure 6186 of the matrix is not changed the values are 6187 merely zeroed. 6188 6189 The user can set a value in the diagonal entry (or for the `MATAIJ` format 6190 formats can optionally remove the main diagonal entry from the 6191 nonzero structure as well, by passing 0.0 as the final argument). 6192 6193 For the parallel case, all processes that share the matrix (i.e., 6194 those in the communicator used for matrix creation) MUST call this 6195 routine, regardless of whether any rows being zeroed are owned by 6196 them. 6197 6198 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6199 list only rows local to itself). 6200 6201 You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it 6202 owns that are to be zeroed. This saves a global synchronization in the implementation. 6203 6204 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6205 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE` 6206 @*/ 6207 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6208 { 6209 PetscFunctionBegin; 6210 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6211 PetscValidType(mat, 1); 6212 if (numRows) PetscValidIntPointer(rows, 3); 6213 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6214 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6215 MatCheckPreallocated(mat, 1); 6216 6217 PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b); 6218 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6219 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6220 PetscFunctionReturn(PETSC_SUCCESS); 6221 } 6222 6223 /*@ 6224 MatZeroRowsIS - Zeros all entries (except possibly the main diagonal) 6225 of a set of rows of a matrix. 6226 6227 Collective 6228 6229 Input Parameters: 6230 + mat - the matrix 6231 . is - index set of rows to remove (if `NULL` then no row is removed) 6232 . diag - value put in all diagonals of eliminated rows 6233 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6234 - b - optional vector of right hand side, that will be adjusted by provided solution 6235 6236 Level: intermediate 6237 6238 Note: 6239 See `MatZeroRows()` for details on how this routine operates. 6240 6241 .seealso: [](chapter_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6242 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6243 @*/ 6244 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6245 { 6246 PetscInt numRows = 0; 6247 const PetscInt *rows = NULL; 6248 6249 PetscFunctionBegin; 6250 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6251 PetscValidType(mat, 1); 6252 if (is) { 6253 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6254 PetscCall(ISGetLocalSize(is, &numRows)); 6255 PetscCall(ISGetIndices(is, &rows)); 6256 } 6257 PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b)); 6258 if (is) PetscCall(ISRestoreIndices(is, &rows)); 6259 PetscFunctionReturn(PETSC_SUCCESS); 6260 } 6261 6262 /*@ 6263 MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal) 6264 of a set of rows of a matrix. These rows must be local to the process. 6265 6266 Collective 6267 6268 Input Parameters: 6269 + mat - the matrix 6270 . numRows - the number of rows to remove 6271 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6272 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6273 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6274 - b - optional vector of right hand side, that will be adjusted by provided solution 6275 6276 Level: intermediate 6277 6278 Notes: 6279 See `MatZeroRows()` for details on how this routine operates. 6280 6281 The grid coordinates are across the entire grid, not just the local portion 6282 6283 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6284 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6285 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6286 `DM_BOUNDARY_PERIODIC` boundary type. 6287 6288 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 6289 a single value per point) you can skip filling those indices. 6290 6291 Fortran Note: 6292 `idxm` and `idxn` should be declared as 6293 $ MatStencil idxm(4,m) 6294 and the values inserted using 6295 .vb 6296 idxm(MatStencil_i,1) = i 6297 idxm(MatStencil_j,1) = j 6298 idxm(MatStencil_k,1) = k 6299 idxm(MatStencil_c,1) = c 6300 etc 6301 .ve 6302 6303 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6304 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6305 @*/ 6306 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6307 { 6308 PetscInt dim = mat->stencil.dim; 6309 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6310 PetscInt *dims = mat->stencil.dims + 1; 6311 PetscInt *starts = mat->stencil.starts; 6312 PetscInt *dxm = (PetscInt *)rows; 6313 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6314 6315 PetscFunctionBegin; 6316 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6317 PetscValidType(mat, 1); 6318 if (numRows) PetscValidPointer(rows, 3); 6319 6320 PetscCall(PetscMalloc1(numRows, &jdxm)); 6321 for (i = 0; i < numRows; ++i) { 6322 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6323 for (j = 0; j < 3 - sdim; ++j) dxm++; 6324 /* Local index in X dir */ 6325 tmp = *dxm++ - starts[0]; 6326 /* Loop over remaining dimensions */ 6327 for (j = 0; j < dim - 1; ++j) { 6328 /* If nonlocal, set index to be negative */ 6329 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6330 /* Update local index */ 6331 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6332 } 6333 /* Skip component slot if necessary */ 6334 if (mat->stencil.noc) dxm++; 6335 /* Local row number */ 6336 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6337 } 6338 PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b)); 6339 PetscCall(PetscFree(jdxm)); 6340 PetscFunctionReturn(PETSC_SUCCESS); 6341 } 6342 6343 /*@ 6344 MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal) 6345 of a set of rows and columns of a matrix. 6346 6347 Collective 6348 6349 Input Parameters: 6350 + mat - the matrix 6351 . numRows - the number of rows/columns to remove 6352 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6353 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6354 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6355 - b - optional vector of right hand side, that will be adjusted by provided solution 6356 6357 Level: intermediate 6358 6359 Notes: 6360 See `MatZeroRowsColumns()` for details on how this routine operates. 6361 6362 The grid coordinates are across the entire grid, not just the local portion 6363 6364 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6365 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6366 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6367 `DM_BOUNDARY_PERIODIC` boundary type. 6368 6369 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 6370 a single value per point) you can skip filling those indices. 6371 6372 Fortran Note: 6373 `idxm` and `idxn` should be declared as 6374 $ MatStencil idxm(4,m) 6375 and the values inserted using 6376 .vb 6377 idxm(MatStencil_i,1) = i 6378 idxm(MatStencil_j,1) = j 6379 idxm(MatStencil_k,1) = k 6380 idxm(MatStencil_c,1) = c 6381 etc 6382 .ve 6383 6384 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6385 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()` 6386 @*/ 6387 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6388 { 6389 PetscInt dim = mat->stencil.dim; 6390 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6391 PetscInt *dims = mat->stencil.dims + 1; 6392 PetscInt *starts = mat->stencil.starts; 6393 PetscInt *dxm = (PetscInt *)rows; 6394 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6395 6396 PetscFunctionBegin; 6397 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6398 PetscValidType(mat, 1); 6399 if (numRows) PetscValidPointer(rows, 3); 6400 6401 PetscCall(PetscMalloc1(numRows, &jdxm)); 6402 for (i = 0; i < numRows; ++i) { 6403 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6404 for (j = 0; j < 3 - sdim; ++j) dxm++; 6405 /* Local index in X dir */ 6406 tmp = *dxm++ - starts[0]; 6407 /* Loop over remaining dimensions */ 6408 for (j = 0; j < dim - 1; ++j) { 6409 /* If nonlocal, set index to be negative */ 6410 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6411 /* Update local index */ 6412 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6413 } 6414 /* Skip component slot if necessary */ 6415 if (mat->stencil.noc) dxm++; 6416 /* Local row number */ 6417 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6418 } 6419 PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b)); 6420 PetscCall(PetscFree(jdxm)); 6421 PetscFunctionReturn(PETSC_SUCCESS); 6422 } 6423 6424 /*@C 6425 MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal) 6426 of a set of rows of a matrix; using local numbering of rows. 6427 6428 Collective 6429 6430 Input Parameters: 6431 + mat - the matrix 6432 . numRows - the number of rows to remove 6433 . rows - the local row indices 6434 . diag - value put in all diagonals of eliminated rows 6435 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6436 - b - optional vector of right hand side, that will be adjusted by provided solution 6437 6438 Level: intermediate 6439 6440 Notes: 6441 Before calling `MatZeroRowsLocal()`, the user must first set the 6442 local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`. 6443 6444 See `MatZeroRows()` for details on how this routine operates. 6445 6446 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`, 6447 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6448 @*/ 6449 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6450 { 6451 PetscFunctionBegin; 6452 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6453 PetscValidType(mat, 1); 6454 if (numRows) PetscValidIntPointer(rows, 3); 6455 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6456 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6457 MatCheckPreallocated(mat, 1); 6458 6459 if (mat->ops->zerorowslocal) { 6460 PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b); 6461 } else { 6462 IS is, newis; 6463 const PetscInt *newRows; 6464 6465 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6466 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6467 PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis)); 6468 PetscCall(ISGetIndices(newis, &newRows)); 6469 PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b); 6470 PetscCall(ISRestoreIndices(newis, &newRows)); 6471 PetscCall(ISDestroy(&newis)); 6472 PetscCall(ISDestroy(&is)); 6473 } 6474 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6475 PetscFunctionReturn(PETSC_SUCCESS); 6476 } 6477 6478 /*@ 6479 MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal) 6480 of a set of rows of a matrix; using local numbering of rows. 6481 6482 Collective 6483 6484 Input Parameters: 6485 + mat - the matrix 6486 . is - index set of rows to remove 6487 . diag - value put in all diagonals of eliminated rows 6488 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6489 - b - optional vector of right hand side, that will be adjusted by provided solution 6490 6491 Level: intermediate 6492 6493 Notes: 6494 Before calling `MatZeroRowsLocalIS()`, the user must first set the 6495 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6496 6497 See `MatZeroRows()` for details on how this routine operates. 6498 6499 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6500 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6501 @*/ 6502 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6503 { 6504 PetscInt numRows; 6505 const PetscInt *rows; 6506 6507 PetscFunctionBegin; 6508 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6509 PetscValidType(mat, 1); 6510 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6511 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6512 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6513 MatCheckPreallocated(mat, 1); 6514 6515 PetscCall(ISGetLocalSize(is, &numRows)); 6516 PetscCall(ISGetIndices(is, &rows)); 6517 PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b)); 6518 PetscCall(ISRestoreIndices(is, &rows)); 6519 PetscFunctionReturn(PETSC_SUCCESS); 6520 } 6521 6522 /*@ 6523 MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal) 6524 of a set of rows and columns of a matrix; using local numbering of rows. 6525 6526 Collective 6527 6528 Input Parameters: 6529 + mat - the matrix 6530 . numRows - the number of rows to remove 6531 . rows - the global row indices 6532 . diag - value put in all diagonals of eliminated rows 6533 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6534 - b - optional vector of right hand side, that will be adjusted by provided solution 6535 6536 Level: intermediate 6537 6538 Notes: 6539 Before calling `MatZeroRowsColumnsLocal()`, the user must first set the 6540 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6541 6542 See `MatZeroRowsColumns()` for details on how this routine operates. 6543 6544 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6545 `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6546 @*/ 6547 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6548 { 6549 IS is, newis; 6550 const PetscInt *newRows; 6551 6552 PetscFunctionBegin; 6553 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6554 PetscValidType(mat, 1); 6555 if (numRows) PetscValidIntPointer(rows, 3); 6556 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6557 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6558 MatCheckPreallocated(mat, 1); 6559 6560 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6561 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6562 PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis)); 6563 PetscCall(ISGetIndices(newis, &newRows)); 6564 PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b); 6565 PetscCall(ISRestoreIndices(newis, &newRows)); 6566 PetscCall(ISDestroy(&newis)); 6567 PetscCall(ISDestroy(&is)); 6568 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6569 PetscFunctionReturn(PETSC_SUCCESS); 6570 } 6571 6572 /*@ 6573 MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal) 6574 of a set of rows and columns of a matrix; using local numbering of rows. 6575 6576 Collective 6577 6578 Input Parameters: 6579 + mat - the matrix 6580 . is - index set of rows to remove 6581 . diag - value put in all diagonals of eliminated rows 6582 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6583 - b - optional vector of right hand side, that will be adjusted by provided solution 6584 6585 Level: intermediate 6586 6587 Notes: 6588 Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the 6589 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6590 6591 See `MatZeroRowsColumns()` for details on how this routine operates. 6592 6593 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6594 `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6595 @*/ 6596 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6597 { 6598 PetscInt numRows; 6599 const PetscInt *rows; 6600 6601 PetscFunctionBegin; 6602 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6603 PetscValidType(mat, 1); 6604 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6605 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6606 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6607 MatCheckPreallocated(mat, 1); 6608 6609 PetscCall(ISGetLocalSize(is, &numRows)); 6610 PetscCall(ISGetIndices(is, &rows)); 6611 PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b)); 6612 PetscCall(ISRestoreIndices(is, &rows)); 6613 PetscFunctionReturn(PETSC_SUCCESS); 6614 } 6615 6616 /*@C 6617 MatGetSize - Returns the numbers of rows and columns in a matrix. 6618 6619 Not Collective 6620 6621 Input Parameter: 6622 . mat - the matrix 6623 6624 Output Parameters: 6625 + m - the number of global rows 6626 - n - the number of global columns 6627 6628 Level: beginner 6629 6630 Note: 6631 Both output parameters can be `NULL` on input. 6632 6633 .seealso: [](chapter_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()` 6634 @*/ 6635 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n) 6636 { 6637 PetscFunctionBegin; 6638 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6639 if (m) *m = mat->rmap->N; 6640 if (n) *n = mat->cmap->N; 6641 PetscFunctionReturn(PETSC_SUCCESS); 6642 } 6643 6644 /*@C 6645 MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns 6646 of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`. 6647 6648 Not Collective 6649 6650 Input Parameter: 6651 . mat - the matrix 6652 6653 Output Parameters: 6654 + m - the number of local rows, use `NULL` to not obtain this value 6655 - n - the number of local columns, use `NULL` to not obtain this value 6656 6657 Level: beginner 6658 6659 .seealso: [](chapter_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()` 6660 @*/ 6661 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n) 6662 { 6663 PetscFunctionBegin; 6664 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6665 if (m) PetscValidIntPointer(m, 2); 6666 if (n) PetscValidIntPointer(n, 3); 6667 if (m) *m = mat->rmap->n; 6668 if (n) *n = mat->cmap->n; 6669 PetscFunctionReturn(PETSC_SUCCESS); 6670 } 6671 6672 /*@C 6673 MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by 6674 this processor. (The columns of the "diagonal block" for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts. 6675 6676 Not Collective, unless matrix has not been allocated, then collective 6677 6678 Input Parameter: 6679 . mat - the matrix 6680 6681 Output Parameters: 6682 + m - the global index of the first local column, use `NULL` to not obtain this value 6683 - n - one more than the global index of the last local column, use `NULL` to not obtain this value 6684 6685 Level: developer 6686 6687 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout` 6688 @*/ 6689 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n) 6690 { 6691 PetscFunctionBegin; 6692 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6693 PetscValidType(mat, 1); 6694 if (m) PetscValidIntPointer(m, 2); 6695 if (n) PetscValidIntPointer(n, 3); 6696 MatCheckPreallocated(mat, 1); 6697 if (m) *m = mat->cmap->rstart; 6698 if (n) *n = mat->cmap->rend; 6699 PetscFunctionReturn(PETSC_SUCCESS); 6700 } 6701 6702 /*@C 6703 MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6704 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 6705 vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts 6706 6707 Not Collective 6708 6709 Input Parameter: 6710 . mat - the matrix 6711 6712 Output Parameters: 6713 + m - the global index of the first local row, use `NULL` to not obtain this value 6714 - n - one more than the global index of the last local row, use `NULL` to not obtain this value 6715 6716 Level: beginner 6717 6718 Note: 6719 This function requires that the matrix be preallocated. If you have not preallocated, consider using 6720 `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N) 6721 and then `MPI_Scan()` to calculate prefix sums of the local sizes. 6722 6723 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, 6724 `PetscLayout` 6725 @*/ 6726 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n) 6727 { 6728 PetscFunctionBegin; 6729 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6730 PetscValidType(mat, 1); 6731 if (m) PetscValidIntPointer(m, 2); 6732 if (n) PetscValidIntPointer(n, 3); 6733 MatCheckPreallocated(mat, 1); 6734 if (m) *m = mat->rmap->rstart; 6735 if (n) *n = mat->rmap->rend; 6736 PetscFunctionReturn(PETSC_SUCCESS); 6737 } 6738 6739 /*@C 6740 MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6741 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 6742 vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts 6743 6744 Not Collective, unless matrix has not been allocated 6745 6746 Input Parameter: 6747 . mat - the matrix 6748 6749 Output Parameter: 6750 . ranges - start of each processors portion plus one more than the total length at the end 6751 6752 Level: beginner 6753 6754 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout` 6755 @*/ 6756 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges) 6757 { 6758 PetscFunctionBegin; 6759 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6760 PetscValidType(mat, 1); 6761 MatCheckPreallocated(mat, 1); 6762 PetscCall(PetscLayoutGetRanges(mat->rmap, ranges)); 6763 PetscFunctionReturn(PETSC_SUCCESS); 6764 } 6765 6766 /*@C 6767 MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by 6768 each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts. 6769 6770 Not Collective, unless matrix has not been allocated 6771 6772 Input Parameter: 6773 . mat - the matrix 6774 6775 Output Parameter: 6776 . ranges - start of each processors portion plus one more then the total length at the end 6777 6778 Level: beginner 6779 6780 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()` 6781 @*/ 6782 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges) 6783 { 6784 PetscFunctionBegin; 6785 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6786 PetscValidType(mat, 1); 6787 MatCheckPreallocated(mat, 1); 6788 PetscCall(PetscLayoutGetRanges(mat->cmap, ranges)); 6789 PetscFunctionReturn(PETSC_SUCCESS); 6790 } 6791 6792 /*@C 6793 MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this 6794 corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership 6795 is more complicated. See :any:`<sec_matlayout>` for details on matrix layouts. 6796 6797 Not Collective 6798 6799 Input Parameter: 6800 . A - matrix 6801 6802 Output Parameters: 6803 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value 6804 - cols - columns in which this process owns elements, use `NULL` to not obtain this value 6805 6806 Level: intermediate 6807 6808 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK`` 6809 @*/ 6810 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols) 6811 { 6812 PetscErrorCode (*f)(Mat, IS *, IS *); 6813 6814 PetscFunctionBegin; 6815 MatCheckPreallocated(A, 1); 6816 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f)); 6817 if (f) { 6818 PetscCall((*f)(A, rows, cols)); 6819 } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */ 6820 if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows)); 6821 if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols)); 6822 } 6823 PetscFunctionReturn(PETSC_SUCCESS); 6824 } 6825 6826 /*@C 6827 MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()` 6828 Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()` 6829 to complete the factorization. 6830 6831 Collective 6832 6833 Input Parameters: 6834 + fact - the factorized matrix obtained with `MatGetFactor()` 6835 . mat - the matrix 6836 . row - row permutation 6837 . col - column permutation 6838 - info - structure containing 6839 .vb 6840 levels - number of levels of fill. 6841 expected fill - as ratio of original fill. 6842 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 6843 missing diagonal entries) 6844 .ve 6845 6846 Level: developer 6847 6848 Notes: 6849 See [Matrix Factorization](sec_matfactor) for additional information. 6850 6851 Most users should employ the `KSP` interface for linear solvers 6852 instead of working directly with matrix algebra routines such as this. 6853 See, e.g., `KSPCreate()`. 6854 6855 Uses the definition of level of fill as in Y. Saad, 2003 6856 6857 Developer Note: 6858 The Fortran interface is not autogenerated as the 6859 interface definition cannot be generated correctly [due to `MatFactorInfo`] 6860 6861 References: 6862 . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003 6863 6864 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 6865 `MatGetOrdering()`, `MatFactorInfo` 6866 @*/ 6867 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 6868 { 6869 PetscFunctionBegin; 6870 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 6871 PetscValidType(mat, 2); 6872 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 6873 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 6874 PetscValidPointer(info, 5); 6875 PetscValidPointer(fact, 1); 6876 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels); 6877 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 6878 if (!fact->ops->ilufactorsymbolic) { 6879 MatSolverType stype; 6880 PetscCall(MatFactorGetSolverType(fact, &stype)); 6881 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ILU using solver type %s", ((PetscObject)mat)->type_name, stype); 6882 } 6883 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6884 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6885 MatCheckPreallocated(mat, 2); 6886 6887 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0)); 6888 PetscCall((fact->ops->ilufactorsymbolic)(fact, mat, row, col, info)); 6889 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0)); 6890 PetscFunctionReturn(PETSC_SUCCESS); 6891 } 6892 6893 /*@C 6894 MatICCFactorSymbolic - Performs symbolic incomplete 6895 Cholesky factorization for a symmetric matrix. Use 6896 `MatCholeskyFactorNumeric()` to complete the factorization. 6897 6898 Collective 6899 6900 Input Parameters: 6901 + fact - the factorized matrix obtained with `MatGetFactor()` 6902 . mat - the matrix to be factored 6903 . perm - row and column permutation 6904 - info - structure containing 6905 .vb 6906 levels - number of levels of fill. 6907 expected fill - as ratio of original fill. 6908 .ve 6909 6910 Level: developer 6911 6912 Notes: 6913 Most users should employ the `KSP` interface for linear solvers 6914 instead of working directly with matrix algebra routines such as this. 6915 See, e.g., `KSPCreate()`. 6916 6917 This uses the definition of level of fill as in Y. Saad, 2003 6918 6919 Developer Note: 6920 The Fortran interface is not autogenerated as the 6921 interface definition cannot be generated correctly [due to `MatFactorInfo`] 6922 6923 References: 6924 . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003 6925 6926 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 6927 @*/ 6928 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 6929 { 6930 PetscFunctionBegin; 6931 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 6932 PetscValidType(mat, 2); 6933 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 6934 PetscValidPointer(info, 4); 6935 PetscValidPointer(fact, 1); 6936 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6937 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels); 6938 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 6939 if (!(fact)->ops->iccfactorsymbolic) { 6940 MatSolverType stype; 6941 PetscCall(MatFactorGetSolverType(fact, &stype)); 6942 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ICC using solver type %s", ((PetscObject)mat)->type_name, stype); 6943 } 6944 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6945 MatCheckPreallocated(mat, 2); 6946 6947 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 6948 PetscCall((fact->ops->iccfactorsymbolic)(fact, mat, perm, info)); 6949 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 6950 PetscFunctionReturn(PETSC_SUCCESS); 6951 } 6952 6953 /*@C 6954 MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat 6955 points to an array of valid matrices, they may be reused to store the new 6956 submatrices. 6957 6958 Collective 6959 6960 Input Parameters: 6961 + mat - the matrix 6962 . n - the number of submatrixes to be extracted (on this processor, may be zero) 6963 . irow - index set of rows to extract 6964 . icol - index set of columns to extract 6965 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 6966 6967 Output Parameter: 6968 . submat - the array of submatrices 6969 6970 Level: advanced 6971 6972 Notes: 6973 `MatCreateSubMatrices()` can extract ONLY sequential submatrices 6974 (from both sequential and parallel matrices). Use `MatCreateSubMatrix()` 6975 to extract a parallel submatrix. 6976 6977 Some matrix types place restrictions on the row and column 6978 indices, such as that they be sorted or that they be equal to each other. 6979 6980 The index sets may not have duplicate entries. 6981 6982 When extracting submatrices from a parallel matrix, each processor can 6983 form a different submatrix by setting the rows and columns of its 6984 individual index sets according to the local submatrix desired. 6985 6986 When finished using the submatrices, the user should destroy 6987 them with `MatDestroySubMatrices()`. 6988 6989 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 6990 original matrix has not changed from that last call to `MatCreateSubMatrices()`. 6991 6992 This routine creates the matrices in submat; you should NOT create them before 6993 calling it. It also allocates the array of matrix pointers submat. 6994 6995 For `MATBAIJ` matrices the index sets must respect the block structure, that is if they 6996 request one row/column in a block, they must request all rows/columns that are in 6997 that block. For example, if the block size is 2 you cannot request just row 0 and 6998 column 0. 6999 7000 Fortran Note: 7001 The Fortran interface is slightly different from that given below; it 7002 requires one to pass in as `submat` a `Mat` (integer) array of size at least n+1. 7003 7004 .seealso: [](chapter_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7005 @*/ 7006 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7007 { 7008 PetscInt i; 7009 PetscBool eq; 7010 7011 PetscFunctionBegin; 7012 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7013 PetscValidType(mat, 1); 7014 if (n) { 7015 PetscValidPointer(irow, 3); 7016 for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3); 7017 PetscValidPointer(icol, 4); 7018 for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4); 7019 } 7020 PetscValidPointer(submat, 6); 7021 if (n && scall == MAT_REUSE_MATRIX) { 7022 PetscValidPointer(*submat, 6); 7023 for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6); 7024 } 7025 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7026 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7027 MatCheckPreallocated(mat, 1); 7028 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7029 PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat); 7030 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7031 for (i = 0; i < n; i++) { 7032 (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */ 7033 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7034 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7035 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 7036 if (mat->boundtocpu && mat->bindingpropagates) { 7037 PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE)); 7038 PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE)); 7039 } 7040 #endif 7041 } 7042 PetscFunctionReturn(PETSC_SUCCESS); 7043 } 7044 7045 /*@C 7046 MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms). 7047 7048 Collective 7049 7050 Input Parameters: 7051 + mat - the matrix 7052 . n - the number of submatrixes to be extracted 7053 . irow - index set of rows to extract 7054 . icol - index set of columns to extract 7055 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7056 7057 Output Parameter: 7058 . submat - the array of submatrices 7059 7060 Level: advanced 7061 7062 Note: 7063 This is used by `PCGASM` 7064 7065 .seealso: [](chapter_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7066 @*/ 7067 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7068 { 7069 PetscInt i; 7070 PetscBool eq; 7071 7072 PetscFunctionBegin; 7073 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7074 PetscValidType(mat, 1); 7075 if (n) { 7076 PetscValidPointer(irow, 3); 7077 PetscValidHeaderSpecific(*irow, IS_CLASSID, 3); 7078 PetscValidPointer(icol, 4); 7079 PetscValidHeaderSpecific(*icol, IS_CLASSID, 4); 7080 } 7081 PetscValidPointer(submat, 6); 7082 if (n && scall == MAT_REUSE_MATRIX) { 7083 PetscValidPointer(*submat, 6); 7084 PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6); 7085 } 7086 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7087 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7088 MatCheckPreallocated(mat, 1); 7089 7090 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7091 PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat); 7092 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7093 for (i = 0; i < n; i++) { 7094 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7095 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7096 } 7097 PetscFunctionReturn(PETSC_SUCCESS); 7098 } 7099 7100 /*@C 7101 MatDestroyMatrices - Destroys an array of matrices. 7102 7103 Collective 7104 7105 Input Parameters: 7106 + n - the number of local matrices 7107 - mat - the matrices (this is a pointer to the array of matrices) 7108 7109 Level: advanced 7110 7111 Note: 7112 Frees not only the matrices, but also the array that contains the matrices 7113 7114 Fortran Note: 7115 This does not free the array. 7116 7117 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()` 7118 @*/ 7119 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[]) 7120 { 7121 PetscInt i; 7122 7123 PetscFunctionBegin; 7124 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7125 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7126 PetscValidPointer(mat, 2); 7127 7128 for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i])); 7129 7130 /* memory is allocated even if n = 0 */ 7131 PetscCall(PetscFree(*mat)); 7132 PetscFunctionReturn(PETSC_SUCCESS); 7133 } 7134 7135 /*@C 7136 MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`. 7137 7138 Collective 7139 7140 Input Parameters: 7141 + n - the number of local matrices 7142 - mat - the matrices (this is a pointer to the array of matrices, just to match the calling 7143 sequence of `MatCreateSubMatrices()`) 7144 7145 Level: advanced 7146 7147 Note: 7148 Frees not only the matrices, but also the array that contains the matrices 7149 7150 Fortran Note: 7151 This does not free the array. 7152 7153 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7154 @*/ 7155 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[]) 7156 { 7157 Mat mat0; 7158 7159 PetscFunctionBegin; 7160 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7161 /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */ 7162 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7163 PetscValidPointer(mat, 2); 7164 7165 mat0 = (*mat)[0]; 7166 if (mat0 && mat0->ops->destroysubmatrices) { 7167 PetscCall((mat0->ops->destroysubmatrices)(n, mat)); 7168 } else { 7169 PetscCall(MatDestroyMatrices(n, mat)); 7170 } 7171 PetscFunctionReturn(PETSC_SUCCESS); 7172 } 7173 7174 /*@C 7175 MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process 7176 7177 Collective 7178 7179 Input Parameter: 7180 . mat - the matrix 7181 7182 Output Parameter: 7183 . matstruct - the sequential matrix with the nonzero structure of mat 7184 7185 Level: developer 7186 7187 .seealso: [](chapter_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7188 @*/ 7189 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct) 7190 { 7191 PetscFunctionBegin; 7192 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7193 PetscValidPointer(matstruct, 2); 7194 7195 PetscValidType(mat, 1); 7196 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7197 MatCheckPreallocated(mat, 1); 7198 7199 PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7200 PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct); 7201 PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7202 PetscFunctionReturn(PETSC_SUCCESS); 7203 } 7204 7205 /*@C 7206 MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`. 7207 7208 Collective 7209 7210 Input Parameter: 7211 . mat - the matrix (this is a pointer to the array of matrices, just to match the calling 7212 sequence of `MatGetSequentialNonzeroStructure()`) 7213 7214 Level: advanced 7215 7216 Note: 7217 Frees not only the matrices, but also the array that contains the matrices 7218 7219 .seealso: [](chapter_matrices), `Mat`, `MatGetSeqNonzeroStructure()` 7220 @*/ 7221 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat) 7222 { 7223 PetscFunctionBegin; 7224 PetscValidPointer(mat, 1); 7225 PetscCall(MatDestroy(mat)); 7226 PetscFunctionReturn(PETSC_SUCCESS); 7227 } 7228 7229 /*@ 7230 MatIncreaseOverlap - Given a set of submatrices indicated by index sets, 7231 replaces the index sets by larger ones that represent submatrices with 7232 additional overlap. 7233 7234 Collective 7235 7236 Input Parameters: 7237 + mat - the matrix 7238 . n - the number of index sets 7239 . is - the array of index sets (these index sets will changed during the call) 7240 - ov - the additional overlap requested 7241 7242 Options Database Key: 7243 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7244 7245 Level: developer 7246 7247 Note: 7248 The computed overlap preserves the matrix block sizes when the blocks are square. 7249 That is: if a matrix nonzero for a given block would increase the overlap all columns associated with 7250 that block are included in the overlap regardless of whether each specific column would increase the overlap. 7251 7252 .seealso: [](chapter_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()` 7253 @*/ 7254 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov) 7255 { 7256 PetscInt i, bs, cbs; 7257 7258 PetscFunctionBegin; 7259 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7260 PetscValidType(mat, 1); 7261 PetscValidLogicalCollectiveInt(mat, n, 2); 7262 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7263 if (n) { 7264 PetscValidPointer(is, 3); 7265 for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3); 7266 } 7267 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7268 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7269 MatCheckPreallocated(mat, 1); 7270 7271 if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS); 7272 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7273 PetscUseTypeMethod(mat, increaseoverlap, n, is, ov); 7274 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7275 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 7276 if (bs == cbs) { 7277 for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs)); 7278 } 7279 PetscFunctionReturn(PETSC_SUCCESS); 7280 } 7281 7282 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt); 7283 7284 /*@ 7285 MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across 7286 a sub communicator, replaces the index sets by larger ones that represent submatrices with 7287 additional overlap. 7288 7289 Collective 7290 7291 Input Parameters: 7292 + mat - the matrix 7293 . n - the number of index sets 7294 . is - the array of index sets (these index sets will changed during the call) 7295 - ov - the additional overlap requested 7296 7297 ` Options Database Key: 7298 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7299 7300 Level: developer 7301 7302 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()` 7303 @*/ 7304 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov) 7305 { 7306 PetscInt i; 7307 7308 PetscFunctionBegin; 7309 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7310 PetscValidType(mat, 1); 7311 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7312 if (n) { 7313 PetscValidPointer(is, 3); 7314 PetscValidHeaderSpecific(*is, IS_CLASSID, 3); 7315 } 7316 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7317 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7318 MatCheckPreallocated(mat, 1); 7319 if (!ov) PetscFunctionReturn(PETSC_SUCCESS); 7320 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7321 for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov)); 7322 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7323 PetscFunctionReturn(PETSC_SUCCESS); 7324 } 7325 7326 /*@ 7327 MatGetBlockSize - Returns the matrix block size. 7328 7329 Not Collective 7330 7331 Input Parameter: 7332 . mat - the matrix 7333 7334 Output Parameter: 7335 . bs - block size 7336 7337 Level: intermediate 7338 7339 Notes: 7340 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7341 7342 If the block size has not been set yet this routine returns 1. 7343 7344 .seealso: [](chapter_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()` 7345 @*/ 7346 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs) 7347 { 7348 PetscFunctionBegin; 7349 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7350 PetscValidIntPointer(bs, 2); 7351 *bs = PetscAbs(mat->rmap->bs); 7352 PetscFunctionReturn(PETSC_SUCCESS); 7353 } 7354 7355 /*@ 7356 MatGetBlockSizes - Returns the matrix block row and column sizes. 7357 7358 Not Collective 7359 7360 Input Parameter: 7361 . mat - the matrix 7362 7363 Output Parameters: 7364 + rbs - row block size 7365 - cbs - column block size 7366 7367 Level: intermediate 7368 7369 Notes: 7370 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7371 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7372 7373 If a block size has not been set yet this routine returns 1. 7374 7375 .seealso: [](chapter_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()` 7376 @*/ 7377 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs) 7378 { 7379 PetscFunctionBegin; 7380 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7381 if (rbs) PetscValidIntPointer(rbs, 2); 7382 if (cbs) PetscValidIntPointer(cbs, 3); 7383 if (rbs) *rbs = PetscAbs(mat->rmap->bs); 7384 if (cbs) *cbs = PetscAbs(mat->cmap->bs); 7385 PetscFunctionReturn(PETSC_SUCCESS); 7386 } 7387 7388 /*@ 7389 MatSetBlockSize - Sets the matrix block size. 7390 7391 Logically Collective 7392 7393 Input Parameters: 7394 + mat - the matrix 7395 - bs - block size 7396 7397 Level: intermediate 7398 7399 Notes: 7400 Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix. 7401 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7402 7403 For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size 7404 is compatible with the matrix local sizes. 7405 7406 .seealso: [](chapter_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()` 7407 @*/ 7408 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs) 7409 { 7410 PetscFunctionBegin; 7411 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7412 PetscValidLogicalCollectiveInt(mat, bs, 2); 7413 PetscCall(MatSetBlockSizes(mat, bs, bs)); 7414 PetscFunctionReturn(PETSC_SUCCESS); 7415 } 7416 7417 typedef struct { 7418 PetscInt n; 7419 IS *is; 7420 Mat *mat; 7421 PetscObjectState nonzerostate; 7422 Mat C; 7423 } EnvelopeData; 7424 7425 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata) 7426 { 7427 for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i])); 7428 PetscCall(PetscFree(edata->is)); 7429 PetscCall(PetscFree(edata)); 7430 return PETSC_SUCCESS; 7431 } 7432 7433 /* 7434 MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores 7435 the sizes of these blocks in the matrix. An individual block may lie over several processes. 7436 7437 Collective 7438 7439 Input Parameter: 7440 . mat - the matrix 7441 7442 Notes: 7443 There can be zeros within the blocks 7444 7445 The blocks can overlap between processes, including laying on more than two processes 7446 7447 .seealso: [](chapter_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()` 7448 */ 7449 static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat) 7450 { 7451 PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend; 7452 PetscInt *diag, *odiag, sc; 7453 VecScatter scatter; 7454 PetscScalar *seqv; 7455 const PetscScalar *parv; 7456 const PetscInt *ia, *ja; 7457 PetscBool set, flag, done; 7458 Mat AA = mat, A; 7459 MPI_Comm comm; 7460 PetscMPIInt rank, size, tag; 7461 MPI_Status status; 7462 PetscContainer container; 7463 EnvelopeData *edata; 7464 Vec seq, par; 7465 IS isglobal; 7466 7467 PetscFunctionBegin; 7468 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7469 PetscCall(MatIsSymmetricKnown(mat, &set, &flag)); 7470 if (!set || !flag) { 7471 /* TOO: only needs nonzero structure of transpose */ 7472 PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA)); 7473 PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN)); 7474 } 7475 PetscCall(MatAIJGetLocalMat(AA, &A)); 7476 PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7477 PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix"); 7478 7479 PetscCall(MatGetLocalSize(mat, &n, NULL)); 7480 PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag)); 7481 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 7482 PetscCallMPI(MPI_Comm_size(comm, &size)); 7483 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7484 7485 PetscCall(PetscMalloc2(n, &sizes, n, &starts)); 7486 7487 if (rank > 0) { 7488 PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7489 PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7490 } 7491 PetscCall(MatGetOwnershipRange(mat, &rstart, NULL)); 7492 for (i = 0; i < n; i++) { 7493 env = PetscMax(env, ja[ia[i + 1] - 1]); 7494 II = rstart + i; 7495 if (env == II) { 7496 starts[lblocks] = tbs; 7497 sizes[lblocks++] = 1 + II - tbs; 7498 tbs = 1 + II; 7499 } 7500 } 7501 if (rank < size - 1) { 7502 PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm)); 7503 PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm)); 7504 } 7505 7506 PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7507 if (!set || !flag) PetscCall(MatDestroy(&AA)); 7508 PetscCall(MatDestroy(&A)); 7509 7510 PetscCall(PetscNew(&edata)); 7511 PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate)); 7512 edata->n = lblocks; 7513 /* create IS needed for extracting blocks from the original matrix */ 7514 PetscCall(PetscMalloc1(lblocks, &edata->is)); 7515 for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i])); 7516 7517 /* Create the resulting inverse matrix structure with preallocation information */ 7518 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C)); 7519 PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 7520 PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat)); 7521 PetscCall(MatSetType(edata->C, MATAIJ)); 7522 7523 /* Communicate the start and end of each row, from each block to the correct rank */ 7524 /* TODO: Use PetscSF instead of VecScatter */ 7525 for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i]; 7526 PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq)); 7527 PetscCall(VecGetArrayWrite(seq, &seqv)); 7528 for (PetscInt i = 0; i < lblocks; i++) { 7529 for (PetscInt j = 0; j < sizes[i]; j++) { 7530 seqv[cnt] = starts[i]; 7531 seqv[cnt + 1] = starts[i] + sizes[i]; 7532 cnt += 2; 7533 } 7534 } 7535 PetscCall(VecRestoreArrayWrite(seq, &seqv)); 7536 PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 7537 sc -= cnt; 7538 PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par)); 7539 PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal)); 7540 PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter)); 7541 PetscCall(ISDestroy(&isglobal)); 7542 PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7543 PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7544 PetscCall(VecScatterDestroy(&scatter)); 7545 PetscCall(VecDestroy(&seq)); 7546 PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend)); 7547 PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag)); 7548 PetscCall(VecGetArrayRead(par, &parv)); 7549 cnt = 0; 7550 PetscCall(MatGetSize(mat, NULL, &n)); 7551 for (PetscInt i = 0; i < mat->rmap->n; i++) { 7552 PetscInt start, end, d = 0, od = 0; 7553 7554 start = (PetscInt)PetscRealPart(parv[cnt]); 7555 end = (PetscInt)PetscRealPart(parv[cnt + 1]); 7556 cnt += 2; 7557 7558 if (start < cstart) { 7559 od += cstart - start + n - cend; 7560 d += cend - cstart; 7561 } else if (start < cend) { 7562 od += n - cend; 7563 d += cend - start; 7564 } else od += n - start; 7565 if (end <= cstart) { 7566 od -= cstart - end + n - cend; 7567 d -= cend - cstart; 7568 } else if (end < cend) { 7569 od -= n - cend; 7570 d -= cend - end; 7571 } else od -= n - end; 7572 7573 odiag[i] = od; 7574 diag[i] = d; 7575 } 7576 PetscCall(VecRestoreArrayRead(par, &parv)); 7577 PetscCall(VecDestroy(&par)); 7578 PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL)); 7579 PetscCall(PetscFree2(diag, odiag)); 7580 PetscCall(PetscFree2(sizes, starts)); 7581 7582 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container)); 7583 PetscCall(PetscContainerSetPointer(container, edata)); 7584 PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy)); 7585 PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container)); 7586 PetscCall(PetscObjectDereference((PetscObject)container)); 7587 PetscFunctionReturn(PETSC_SUCCESS); 7588 } 7589 7590 /*@ 7591 MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A 7592 7593 Collective 7594 7595 Input Parameters: 7596 + A - the matrix 7597 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine 7598 7599 Output Parameter: 7600 . C - matrix with inverted block diagonal of `A` 7601 7602 Level: advanced 7603 7604 Note: 7605 For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal. 7606 7607 .seealso: [](chapter_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()` 7608 @*/ 7609 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C) 7610 { 7611 PetscContainer container; 7612 EnvelopeData *edata; 7613 PetscObjectState nonzerostate; 7614 7615 PetscFunctionBegin; 7616 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7617 if (!container) { 7618 PetscCall(MatComputeVariableBlockEnvelope(A)); 7619 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7620 } 7621 PetscCall(PetscContainerGetPointer(container, (void **)&edata)); 7622 PetscCall(MatGetNonzeroState(A, &nonzerostate)); 7623 PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure"); 7624 PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output"); 7625 7626 PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat)); 7627 *C = edata->C; 7628 7629 for (PetscInt i = 0; i < edata->n; i++) { 7630 Mat D; 7631 PetscScalar *dvalues; 7632 7633 PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D)); 7634 PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE)); 7635 PetscCall(MatSeqDenseInvert(D)); 7636 PetscCall(MatDenseGetArray(D, &dvalues)); 7637 PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES)); 7638 PetscCall(MatDestroy(&D)); 7639 } 7640 PetscCall(MatDestroySubMatrices(edata->n, &edata->mat)); 7641 PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY)); 7642 PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY)); 7643 PetscFunctionReturn(PETSC_SUCCESS); 7644 } 7645 7646 /*@ 7647 MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size 7648 7649 Logically Collective 7650 7651 Input Parameters: 7652 + mat - the matrix 7653 . nblocks - the number of blocks on this process, each block can only exist on a single process 7654 - bsizes - the block sizes 7655 7656 Level: intermediate 7657 7658 Notes: 7659 Currently used by `PCVPBJACOBI` for `MATAIJ` matrices 7660 7661 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. 7662 7663 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, 7664 `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI` 7665 @*/ 7666 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes) 7667 { 7668 PetscInt i, ncnt = 0, nlocal; 7669 7670 PetscFunctionBegin; 7671 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7672 PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero"); 7673 PetscCall(MatGetLocalSize(mat, &nlocal, NULL)); 7674 for (i = 0; i < nblocks; i++) ncnt += bsizes[i]; 7675 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); 7676 PetscCall(PetscFree(mat->bsizes)); 7677 mat->nblocks = nblocks; 7678 PetscCall(PetscMalloc1(nblocks, &mat->bsizes)); 7679 PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks)); 7680 PetscFunctionReturn(PETSC_SUCCESS); 7681 } 7682 7683 /*@C 7684 MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size 7685 7686 Logically Collective; No Fortran Support 7687 7688 Input Parameter: 7689 . mat - the matrix 7690 7691 Output Parameters: 7692 + nblocks - the number of blocks on this process 7693 - bsizes - the block sizes 7694 7695 Level: intermediate 7696 7697 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()` 7698 @*/ 7699 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes) 7700 { 7701 PetscFunctionBegin; 7702 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7703 *nblocks = mat->nblocks; 7704 *bsizes = mat->bsizes; 7705 PetscFunctionReturn(PETSC_SUCCESS); 7706 } 7707 7708 /*@ 7709 MatSetBlockSizes - Sets the matrix block row and column sizes. 7710 7711 Logically Collective 7712 7713 Input Parameters: 7714 + mat - the matrix 7715 . rbs - row block size 7716 - cbs - column block size 7717 7718 Level: intermediate 7719 7720 Notes: 7721 Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix. 7722 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7723 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7724 7725 For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes 7726 are compatible with the matrix local sizes. 7727 7728 The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`. 7729 7730 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()` 7731 @*/ 7732 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs) 7733 { 7734 PetscFunctionBegin; 7735 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7736 PetscValidLogicalCollectiveInt(mat, rbs, 2); 7737 PetscValidLogicalCollectiveInt(mat, cbs, 3); 7738 PetscTryTypeMethod(mat, setblocksizes, rbs, cbs); 7739 if (mat->rmap->refcnt) { 7740 ISLocalToGlobalMapping l2g = NULL; 7741 PetscLayout nmap = NULL; 7742 7743 PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap)); 7744 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g)); 7745 PetscCall(PetscLayoutDestroy(&mat->rmap)); 7746 mat->rmap = nmap; 7747 mat->rmap->mapping = l2g; 7748 } 7749 if (mat->cmap->refcnt) { 7750 ISLocalToGlobalMapping l2g = NULL; 7751 PetscLayout nmap = NULL; 7752 7753 PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap)); 7754 if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g)); 7755 PetscCall(PetscLayoutDestroy(&mat->cmap)); 7756 mat->cmap = nmap; 7757 mat->cmap->mapping = l2g; 7758 } 7759 PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs)); 7760 PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs)); 7761 PetscFunctionReturn(PETSC_SUCCESS); 7762 } 7763 7764 /*@ 7765 MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices 7766 7767 Logically Collective 7768 7769 Input Parameters: 7770 + mat - the matrix 7771 . fromRow - matrix from which to copy row block size 7772 - fromCol - matrix from which to copy column block size (can be same as fromRow) 7773 7774 Level: developer 7775 7776 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()` 7777 @*/ 7778 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol) 7779 { 7780 PetscFunctionBegin; 7781 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7782 PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2); 7783 PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3); 7784 if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs)); 7785 if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs)); 7786 PetscFunctionReturn(PETSC_SUCCESS); 7787 } 7788 7789 /*@ 7790 MatResidual - Default routine to calculate the residual r = b - Ax 7791 7792 Collective 7793 7794 Input Parameters: 7795 + mat - the matrix 7796 . b - the right-hand-side 7797 - x - the approximate solution 7798 7799 Output Parameter: 7800 . r - location to store the residual 7801 7802 Level: developer 7803 7804 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()` 7805 @*/ 7806 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r) 7807 { 7808 PetscFunctionBegin; 7809 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7810 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 7811 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 7812 PetscValidHeaderSpecific(r, VEC_CLASSID, 4); 7813 PetscValidType(mat, 1); 7814 MatCheckPreallocated(mat, 1); 7815 PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0)); 7816 if (!mat->ops->residual) { 7817 PetscCall(MatMult(mat, x, r)); 7818 PetscCall(VecAYPX(r, -1.0, b)); 7819 } else { 7820 PetscUseTypeMethod(mat, residual, b, x, r); 7821 } 7822 PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0)); 7823 PetscFunctionReturn(PETSC_SUCCESS); 7824 } 7825 7826 /*MC 7827 MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix 7828 7829 Synopsis: 7830 MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 7831 7832 Not Collective 7833 7834 Input Parameters: 7835 + A - the matrix 7836 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7837 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7838 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7839 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7840 always used. 7841 7842 Output Parameters: 7843 + n - number of local rows in the (possibly compressed) matrix 7844 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 7845 . ja - the column indices 7846 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7847 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7848 7849 Level: developer 7850 7851 Note: 7852 Use `MatRestoreRowIJF90()` when you no longer need access to the data 7853 7854 .seealso: [](chapter_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()` 7855 M*/ 7856 7857 /*MC 7858 MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()` 7859 7860 Synopsis: 7861 MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 7862 7863 Not Collective 7864 7865 Input Parameters: 7866 + A - the matrix 7867 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7868 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7869 inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7870 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7871 always used. 7872 . n - number of local rows in the (possibly compressed) matrix 7873 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 7874 . ja - the column indices 7875 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7876 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7877 7878 Level: developer 7879 7880 .seealso: [](chapter_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()` 7881 M*/ 7882 7883 /*@C 7884 MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix 7885 7886 Collective 7887 7888 Input Parameters: 7889 + mat - the matrix 7890 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7891 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7892 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7893 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7894 always used. 7895 7896 Output Parameters: 7897 + n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed 7898 . 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 7899 . ja - the column indices, use `NULL` if not needed 7900 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7901 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7902 7903 Level: developer 7904 7905 Notes: 7906 You CANNOT change any of the ia[] or ja[] values. 7907 7908 Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values. 7909 7910 Fortran Notes: 7911 Use 7912 .vb 7913 PetscInt, pointer :: ia(:),ja(:) 7914 call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr) 7915 ! Access the ith and jth entries via ia(i) and ja(j) 7916 .ve 7917 `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()` 7918 7919 .seealso: [](chapter_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()` 7920 @*/ 7921 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7922 { 7923 PetscFunctionBegin; 7924 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7925 PetscValidType(mat, 1); 7926 if (n) PetscValidIntPointer(n, 5); 7927 if (ia) PetscValidPointer(ia, 6); 7928 if (ja) PetscValidPointer(ja, 7); 7929 if (done) PetscValidBoolPointer(done, 8); 7930 MatCheckPreallocated(mat, 1); 7931 if (!mat->ops->getrowij && done) *done = PETSC_FALSE; 7932 else { 7933 if (done) *done = PETSC_TRUE; 7934 PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0)); 7935 PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done); 7936 PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0)); 7937 } 7938 PetscFunctionReturn(PETSC_SUCCESS); 7939 } 7940 7941 /*@C 7942 MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices. 7943 7944 Collective 7945 7946 Input Parameters: 7947 + mat - the matrix 7948 . shift - 1 or zero indicating we want the indices starting at 0 or 1 7949 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be 7950 symmetrized 7951 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7952 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7953 always used. 7954 . n - number of columns in the (possibly compressed) matrix 7955 . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix 7956 - ja - the row indices 7957 7958 Output Parameter: 7959 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned 7960 7961 Level: developer 7962 7963 .seealso: [](chapter_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 7964 @*/ 7965 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7966 { 7967 PetscFunctionBegin; 7968 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7969 PetscValidType(mat, 1); 7970 PetscValidIntPointer(n, 5); 7971 if (ia) PetscValidPointer(ia, 6); 7972 if (ja) PetscValidPointer(ja, 7); 7973 PetscValidBoolPointer(done, 8); 7974 MatCheckPreallocated(mat, 1); 7975 if (!mat->ops->getcolumnij) *done = PETSC_FALSE; 7976 else { 7977 *done = PETSC_TRUE; 7978 PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 7979 } 7980 PetscFunctionReturn(PETSC_SUCCESS); 7981 } 7982 7983 /*@C 7984 MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`. 7985 7986 Collective 7987 7988 Input Parameters: 7989 + mat - the matrix 7990 . shift - 1 or zero indicating we want the indices starting at 0 or 1 7991 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7992 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7993 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7994 always used. 7995 . n - size of (possibly compressed) matrix 7996 . ia - the row pointers 7997 - ja - the column indices 7998 7999 Output Parameter: 8000 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8001 8002 Level: developer 8003 8004 Note: 8005 This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental 8006 us of the array after it has been restored. If you pass `NULL`, it will 8007 not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid. 8008 8009 Fortran Note: 8010 `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()` 8011 8012 .seealso: [](chapter_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()` 8013 @*/ 8014 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8015 { 8016 PetscFunctionBegin; 8017 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8018 PetscValidType(mat, 1); 8019 if (ia) PetscValidPointer(ia, 6); 8020 if (ja) PetscValidPointer(ja, 7); 8021 if (done) PetscValidBoolPointer(done, 8); 8022 MatCheckPreallocated(mat, 1); 8023 8024 if (!mat->ops->restorerowij && done) *done = PETSC_FALSE; 8025 else { 8026 if (done) *done = PETSC_TRUE; 8027 PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8028 if (n) *n = 0; 8029 if (ia) *ia = NULL; 8030 if (ja) *ja = NULL; 8031 } 8032 PetscFunctionReturn(PETSC_SUCCESS); 8033 } 8034 8035 /*@C 8036 MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`. 8037 8038 Collective 8039 8040 Input Parameters: 8041 + mat - the matrix 8042 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8043 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8044 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8045 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8046 always used. 8047 8048 Output Parameters: 8049 + n - size of (possibly compressed) matrix 8050 . ia - the column pointers 8051 . ja - the row indices 8052 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8053 8054 Level: developer 8055 8056 .seealso: [](chapter_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()` 8057 @*/ 8058 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8059 { 8060 PetscFunctionBegin; 8061 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8062 PetscValidType(mat, 1); 8063 if (ia) PetscValidPointer(ia, 6); 8064 if (ja) PetscValidPointer(ja, 7); 8065 PetscValidBoolPointer(done, 8); 8066 MatCheckPreallocated(mat, 1); 8067 8068 if (!mat->ops->restorecolumnij) *done = PETSC_FALSE; 8069 else { 8070 *done = PETSC_TRUE; 8071 PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8072 if (n) *n = 0; 8073 if (ia) *ia = NULL; 8074 if (ja) *ja = NULL; 8075 } 8076 PetscFunctionReturn(PETSC_SUCCESS); 8077 } 8078 8079 /*@C 8080 MatColoringPatch -Used inside matrix coloring routines that use `MatGetRowIJ()` and/or `MatGetColumnIJ()`. 8081 8082 Collective 8083 8084 Input Parameters: 8085 + mat - the matrix 8086 . ncolors - maximum color value 8087 . n - number of entries in colorarray 8088 - colorarray - array indicating color for each column 8089 8090 Output Parameter: 8091 . iscoloring - coloring generated using colorarray information 8092 8093 Level: developer 8094 8095 .seealso: [](chapter_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()` 8096 @*/ 8097 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring) 8098 { 8099 PetscFunctionBegin; 8100 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8101 PetscValidType(mat, 1); 8102 PetscValidIntPointer(colorarray, 4); 8103 PetscValidPointer(iscoloring, 5); 8104 MatCheckPreallocated(mat, 1); 8105 8106 if (!mat->ops->coloringpatch) { 8107 PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring)); 8108 } else { 8109 PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring); 8110 } 8111 PetscFunctionReturn(PETSC_SUCCESS); 8112 } 8113 8114 /*@ 8115 MatSetUnfactored - Resets a factored matrix to be treated as unfactored. 8116 8117 Logically Collective 8118 8119 Input Parameter: 8120 . mat - the factored matrix to be reset 8121 8122 Level: developer 8123 8124 Notes: 8125 This routine should be used only with factored matrices formed by in-place 8126 factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE` 8127 format). This option can save memory, for example, when solving nonlinear 8128 systems with a matrix-free Newton-Krylov method and a matrix-based, in-place 8129 ILU(0) preconditioner. 8130 8131 One can specify in-place ILU(0) factorization by calling 8132 .vb 8133 PCType(pc,PCILU); 8134 PCFactorSeUseInPlace(pc); 8135 .ve 8136 or by using the options -pc_type ilu -pc_factor_in_place 8137 8138 In-place factorization ILU(0) can also be used as a local 8139 solver for the blocks within the block Jacobi or additive Schwarz 8140 methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc 8141 for details on setting local solver options. 8142 8143 Most users should employ the `KSP` interface for linear solvers 8144 instead of working directly with matrix algebra routines such as this. 8145 See, e.g., `KSPCreate()`. 8146 8147 .seealso: [](chapter_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()` 8148 @*/ 8149 PetscErrorCode MatSetUnfactored(Mat mat) 8150 { 8151 PetscFunctionBegin; 8152 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8153 PetscValidType(mat, 1); 8154 MatCheckPreallocated(mat, 1); 8155 mat->factortype = MAT_FACTOR_NONE; 8156 if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS); 8157 PetscUseTypeMethod(mat, setunfactored); 8158 PetscFunctionReturn(PETSC_SUCCESS); 8159 } 8160 8161 /*MC 8162 MatDenseGetArrayF90 - Accesses a matrix array from Fortran 8163 8164 Synopsis: 8165 MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8166 8167 Not Collective 8168 8169 Input Parameter: 8170 . x - matrix 8171 8172 Output Parameters: 8173 + xx_v - the Fortran pointer to the array 8174 - ierr - error code 8175 8176 Example of Usage: 8177 .vb 8178 PetscScalar, pointer xx_v(:,:) 8179 .... 8180 call MatDenseGetArrayF90(x,xx_v,ierr) 8181 a = xx_v(3) 8182 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8183 .ve 8184 8185 Level: advanced 8186 8187 .seealso: [](chapter_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()` 8188 M*/ 8189 8190 /*MC 8191 MatDenseRestoreArrayF90 - Restores a matrix array that has been 8192 accessed with `MatDenseGetArrayF90()`. 8193 8194 Synopsis: 8195 MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8196 8197 Not Collective 8198 8199 Input Parameters: 8200 + x - matrix 8201 - xx_v - the Fortran90 pointer to the array 8202 8203 Output Parameter: 8204 . ierr - error code 8205 8206 Example of Usage: 8207 .vb 8208 PetscScalar, pointer xx_v(:,:) 8209 .... 8210 call MatDenseGetArrayF90(x,xx_v,ierr) 8211 a = xx_v(3) 8212 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8213 .ve 8214 8215 Level: advanced 8216 8217 .seealso: [](chapter_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()` 8218 M*/ 8219 8220 /*MC 8221 MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran. 8222 8223 Synopsis: 8224 MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8225 8226 Not Collective 8227 8228 Input Parameter: 8229 . x - matrix 8230 8231 Output Parameters: 8232 + xx_v - the Fortran pointer to the array 8233 - ierr - error code 8234 8235 Example of Usage: 8236 .vb 8237 PetscScalar, pointer xx_v(:) 8238 .... 8239 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8240 a = xx_v(3) 8241 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8242 .ve 8243 8244 Level: advanced 8245 8246 .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()` 8247 M*/ 8248 8249 /*MC 8250 MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been 8251 accessed with `MatSeqAIJGetArrayF90()`. 8252 8253 Synopsis: 8254 MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8255 8256 Not Collective 8257 8258 Input Parameters: 8259 + x - matrix 8260 - xx_v - the Fortran90 pointer to the array 8261 8262 Output Parameter: 8263 . ierr - error code 8264 8265 Example of Usage: 8266 .vb 8267 PetscScalar, pointer xx_v(:) 8268 .... 8269 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8270 a = xx_v(3) 8271 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8272 .ve 8273 8274 Level: advanced 8275 8276 .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()` 8277 M*/ 8278 8279 /*@ 8280 MatCreateSubMatrix - Gets a single submatrix on the same number of processors 8281 as the original matrix. 8282 8283 Collective 8284 8285 Input Parameters: 8286 + mat - the original matrix 8287 . isrow - parallel `IS` containing the rows this processor should obtain 8288 . 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. 8289 - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 8290 8291 Output Parameter: 8292 . newmat - the new submatrix, of the same type as the original matrix 8293 8294 Level: advanced 8295 8296 Notes: 8297 The submatrix will be able to be multiplied with vectors using the same layout as `iscol`. 8298 8299 Some matrix types place restrictions on the row and column indices, such 8300 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; 8301 for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row. 8302 8303 The index sets may not have duplicate entries. 8304 8305 The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`, 8306 the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls 8307 to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX` 8308 will reuse the matrix generated the first time. You should call `MatDestroy()` on `newmat` when 8309 you are finished using it. 8310 8311 The communicator of the newly obtained matrix is ALWAYS the same as the communicator of 8312 the input matrix. 8313 8314 If `iscol` is `NULL` then all columns are obtained (not supported in Fortran). 8315 8316 Example usage: 8317 Consider the following 8x8 matrix with 34 non-zero values, that is 8318 assembled across 3 processors. Let's assume that proc0 owns 3 rows, 8319 proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 8320 as follows 8321 .vb 8322 1 2 0 | 0 3 0 | 0 4 8323 Proc0 0 5 6 | 7 0 0 | 8 0 8324 9 0 10 | 11 0 0 | 12 0 8325 ------------------------------------- 8326 13 0 14 | 15 16 17 | 0 0 8327 Proc1 0 18 0 | 19 20 21 | 0 0 8328 0 0 0 | 22 23 0 | 24 0 8329 ------------------------------------- 8330 Proc2 25 26 27 | 0 0 28 | 29 0 8331 30 0 0 | 31 32 33 | 0 34 8332 .ve 8333 8334 Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6]. The resulting submatrix is 8335 8336 .vb 8337 2 0 | 0 3 0 | 0 8338 Proc0 5 6 | 7 0 0 | 8 8339 ------------------------------- 8340 Proc1 18 0 | 19 20 21 | 0 8341 ------------------------------- 8342 Proc2 26 27 | 0 0 28 | 29 8343 0 0 | 31 32 33 | 0 8344 .ve 8345 8346 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()` 8347 @*/ 8348 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat) 8349 { 8350 PetscMPIInt size; 8351 Mat *local; 8352 IS iscoltmp; 8353 PetscBool flg; 8354 8355 PetscFunctionBegin; 8356 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8357 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 8358 if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 8359 PetscValidPointer(newmat, 5); 8360 if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5); 8361 PetscValidType(mat, 1); 8362 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8363 PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX"); 8364 8365 MatCheckPreallocated(mat, 1); 8366 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8367 8368 if (!iscol || isrow == iscol) { 8369 PetscBool stride; 8370 PetscMPIInt grabentirematrix = 0, grab; 8371 PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride)); 8372 if (stride) { 8373 PetscInt first, step, n, rstart, rend; 8374 PetscCall(ISStrideGetInfo(isrow, &first, &step)); 8375 if (step == 1) { 8376 PetscCall(MatGetOwnershipRange(mat, &rstart, &rend)); 8377 if (rstart == first) { 8378 PetscCall(ISGetLocalSize(isrow, &n)); 8379 if (n == rend - rstart) grabentirematrix = 1; 8380 } 8381 } 8382 } 8383 PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat))); 8384 if (grab) { 8385 PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n")); 8386 if (cll == MAT_INITIAL_MATRIX) { 8387 *newmat = mat; 8388 PetscCall(PetscObjectReference((PetscObject)mat)); 8389 } 8390 PetscFunctionReturn(PETSC_SUCCESS); 8391 } 8392 } 8393 8394 if (!iscol) { 8395 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp)); 8396 } else { 8397 iscoltmp = iscol; 8398 } 8399 8400 /* if original matrix is on just one processor then use submatrix generated */ 8401 if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) { 8402 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat)); 8403 goto setproperties; 8404 } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) { 8405 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local)); 8406 *newmat = *local; 8407 PetscCall(PetscFree(local)); 8408 goto setproperties; 8409 } else if (!mat->ops->createsubmatrix) { 8410 /* Create a new matrix type that implements the operation using the full matrix */ 8411 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8412 switch (cll) { 8413 case MAT_INITIAL_MATRIX: 8414 PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat)); 8415 break; 8416 case MAT_REUSE_MATRIX: 8417 PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp)); 8418 break; 8419 default: 8420 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX"); 8421 } 8422 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8423 goto setproperties; 8424 } 8425 8426 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8427 PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat); 8428 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8429 8430 setproperties: 8431 PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg)); 8432 if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat)); 8433 if (!iscol) PetscCall(ISDestroy(&iscoltmp)); 8434 if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat)); 8435 PetscFunctionReturn(PETSC_SUCCESS); 8436 } 8437 8438 /*@ 8439 MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix 8440 8441 Not Collective 8442 8443 Input Parameters: 8444 + A - the matrix we wish to propagate options from 8445 - B - the matrix we wish to propagate options to 8446 8447 Level: beginner 8448 8449 Note: 8450 Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL` 8451 8452 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, MatIsStructurallySymmetricKnown()` 8453 @*/ 8454 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B) 8455 { 8456 PetscFunctionBegin; 8457 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8458 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 8459 B->symmetry_eternal = A->symmetry_eternal; 8460 B->structural_symmetry_eternal = A->structural_symmetry_eternal; 8461 B->symmetric = A->symmetric; 8462 B->structurally_symmetric = A->structurally_symmetric; 8463 B->spd = A->spd; 8464 B->hermitian = A->hermitian; 8465 PetscFunctionReturn(PETSC_SUCCESS); 8466 } 8467 8468 /*@ 8469 MatStashSetInitialSize - sets the sizes of the matrix stash, that is 8470 used during the assembly process to store values that belong to 8471 other processors. 8472 8473 Not Collective 8474 8475 Input Parameters: 8476 + mat - the matrix 8477 . size - the initial size of the stash. 8478 - bsize - the initial size of the block-stash(if used). 8479 8480 Options Database Keys: 8481 + -matstash_initial_size <size> or <size0,size1,...sizep-1> 8482 - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1> 8483 8484 Level: intermediate 8485 8486 Notes: 8487 The block-stash is used for values set with `MatSetValuesBlocked()` while 8488 the stash is used for values set with `MatSetValues()` 8489 8490 Run with the option -info and look for output of the form 8491 MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs. 8492 to determine the appropriate value, MM, to use for size and 8493 MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs. 8494 to determine the value, BMM to use for bsize 8495 8496 .seealso: [](chapter_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()` 8497 @*/ 8498 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize) 8499 { 8500 PetscFunctionBegin; 8501 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8502 PetscValidType(mat, 1); 8503 PetscCall(MatStashSetInitialSize_Private(&mat->stash, size)); 8504 PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize)); 8505 PetscFunctionReturn(PETSC_SUCCESS); 8506 } 8507 8508 /*@ 8509 MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of 8510 the matrix 8511 8512 Neighbor-wise Collective 8513 8514 Input Parameters: 8515 + mat - the matrix 8516 . x - the vector to be multiplied by the interpolation operator 8517 - y - the vector to be added to the result 8518 8519 Output Parameter: 8520 . w - the resulting vector 8521 8522 Level: intermediate 8523 8524 Notes: 8525 `w` may be the same vector as `y`. 8526 8527 This allows one to use either the restriction or interpolation (its transpose) 8528 matrix to do the interpolation 8529 8530 .seealso: [](chapter_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8531 @*/ 8532 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w) 8533 { 8534 PetscInt M, N, Ny; 8535 8536 PetscFunctionBegin; 8537 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8538 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8539 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8540 PetscValidHeaderSpecific(w, VEC_CLASSID, 4); 8541 PetscCall(MatGetSize(A, &M, &N)); 8542 PetscCall(VecGetSize(y, &Ny)); 8543 if (M == Ny) { 8544 PetscCall(MatMultAdd(A, x, y, w)); 8545 } else { 8546 PetscCall(MatMultTransposeAdd(A, x, y, w)); 8547 } 8548 PetscFunctionReturn(PETSC_SUCCESS); 8549 } 8550 8551 /*@ 8552 MatInterpolate - y = A*x or A'*x depending on the shape of 8553 the matrix 8554 8555 Neighbor-wise Collective 8556 8557 Input Parameters: 8558 + mat - the matrix 8559 - x - the vector to be interpolated 8560 8561 Output Parameter: 8562 . y - the resulting vector 8563 8564 Level: intermediate 8565 8566 Note: 8567 This allows one to use either the restriction or interpolation (its transpose) 8568 matrix to do the interpolation 8569 8570 .seealso: [](chapter_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8571 @*/ 8572 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y) 8573 { 8574 PetscInt M, N, Ny; 8575 8576 PetscFunctionBegin; 8577 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8578 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8579 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8580 PetscCall(MatGetSize(A, &M, &N)); 8581 PetscCall(VecGetSize(y, &Ny)); 8582 if (M == Ny) { 8583 PetscCall(MatMult(A, x, y)); 8584 } else { 8585 PetscCall(MatMultTranspose(A, x, y)); 8586 } 8587 PetscFunctionReturn(PETSC_SUCCESS); 8588 } 8589 8590 /*@ 8591 MatRestrict - y = A*x or A'*x 8592 8593 Neighbor-wise Collective 8594 8595 Input Parameters: 8596 + mat - the matrix 8597 - x - the vector to be restricted 8598 8599 Output Parameter: 8600 . y - the resulting vector 8601 8602 Level: intermediate 8603 8604 Note: 8605 This allows one to use either the restriction or interpolation (its transpose) 8606 matrix to do the restriction 8607 8608 .seealso: [](chapter_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG` 8609 @*/ 8610 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y) 8611 { 8612 PetscInt M, N, Ny; 8613 8614 PetscFunctionBegin; 8615 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8616 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8617 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8618 PetscCall(MatGetSize(A, &M, &N)); 8619 PetscCall(VecGetSize(y, &Ny)); 8620 if (M == Ny) { 8621 PetscCall(MatMult(A, x, y)); 8622 } else { 8623 PetscCall(MatMultTranspose(A, x, y)); 8624 } 8625 PetscFunctionReturn(PETSC_SUCCESS); 8626 } 8627 8628 /*@ 8629 MatMatInterpolateAdd - Y = W + A*X or W + A'*X 8630 8631 Neighbor-wise Collective 8632 8633 Input Parameters: 8634 + mat - the matrix 8635 . x - the input dense matrix to be multiplied 8636 - w - the input dense matrix to be added to the result 8637 8638 Output Parameter: 8639 . y - the output dense matrix 8640 8641 Level: intermediate 8642 8643 Note: 8644 This allows one to use either the restriction or interpolation (its transpose) 8645 matrix to do the interpolation. y matrix can be reused if already created with the proper sizes, 8646 otherwise it will be recreated. y must be initialized to `NULL` if not supplied. 8647 8648 .seealso: [](chapter_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG` 8649 @*/ 8650 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y) 8651 { 8652 PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0; 8653 PetscBool trans = PETSC_TRUE; 8654 MatReuse reuse = MAT_INITIAL_MATRIX; 8655 8656 PetscFunctionBegin; 8657 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8658 PetscValidHeaderSpecific(x, MAT_CLASSID, 2); 8659 PetscValidType(x, 2); 8660 if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3); 8661 if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4); 8662 PetscCall(MatGetSize(A, &M, &N)); 8663 PetscCall(MatGetSize(x, &Mx, &Nx)); 8664 if (N == Mx) trans = PETSC_FALSE; 8665 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); 8666 Mo = trans ? N : M; 8667 if (*y) { 8668 PetscCall(MatGetSize(*y, &My, &Ny)); 8669 if (Mo == My && Nx == Ny) { 8670 reuse = MAT_REUSE_MATRIX; 8671 } else { 8672 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); 8673 PetscCall(MatDestroy(y)); 8674 } 8675 } 8676 8677 if (w && *y == w) { /* this is to minimize changes in PCMG */ 8678 PetscBool flg; 8679 8680 PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w)); 8681 if (w) { 8682 PetscInt My, Ny, Mw, Nw; 8683 8684 PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg)); 8685 PetscCall(MatGetSize(*y, &My, &Ny)); 8686 PetscCall(MatGetSize(w, &Mw, &Nw)); 8687 if (!flg || My != Mw || Ny != Nw) w = NULL; 8688 } 8689 if (!w) { 8690 PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w)); 8691 PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w)); 8692 PetscCall(PetscObjectDereference((PetscObject)w)); 8693 } else { 8694 PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN)); 8695 } 8696 } 8697 if (!trans) { 8698 PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8699 } else { 8700 PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8701 } 8702 if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN)); 8703 PetscFunctionReturn(PETSC_SUCCESS); 8704 } 8705 8706 /*@ 8707 MatMatInterpolate - Y = A*X or A'*X 8708 8709 Neighbor-wise Collective 8710 8711 Input Parameters: 8712 + mat - the matrix 8713 - x - the input dense matrix 8714 8715 Output Parameter: 8716 . y - the output dense matrix 8717 8718 Level: intermediate 8719 8720 Note: 8721 This allows one to use either the restriction or interpolation (its transpose) 8722 matrix to do the interpolation. y matrix can be reused if already created with the proper sizes, 8723 otherwise it will be recreated. y must be initialized to `NULL` if not supplied. 8724 8725 .seealso: [](chapter_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG` 8726 @*/ 8727 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y) 8728 { 8729 PetscFunctionBegin; 8730 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8731 PetscFunctionReturn(PETSC_SUCCESS); 8732 } 8733 8734 /*@ 8735 MatMatRestrict - Y = A*X or A'*X 8736 8737 Neighbor-wise Collective 8738 8739 Input Parameters: 8740 + mat - the matrix 8741 - x - the input dense matrix 8742 8743 Output Parameter: 8744 . y - the output dense matrix 8745 8746 Level: intermediate 8747 8748 Note: 8749 This allows one to use either the restriction or interpolation (its transpose) 8750 matrix to do the restriction. y matrix can be reused if already created with the proper sizes, 8751 otherwise it will be recreated. y must be initialized to `NULL` if not supplied. 8752 8753 .seealso: [](chapter_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG` 8754 @*/ 8755 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y) 8756 { 8757 PetscFunctionBegin; 8758 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8759 PetscFunctionReturn(PETSC_SUCCESS); 8760 } 8761 8762 /*@ 8763 MatGetNullSpace - retrieves the null space of a matrix. 8764 8765 Logically Collective 8766 8767 Input Parameters: 8768 + mat - the matrix 8769 - nullsp - the null space object 8770 8771 Level: developer 8772 8773 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace` 8774 @*/ 8775 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp) 8776 { 8777 PetscFunctionBegin; 8778 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8779 PetscValidPointer(nullsp, 2); 8780 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp; 8781 PetscFunctionReturn(PETSC_SUCCESS); 8782 } 8783 8784 /*@ 8785 MatSetNullSpace - attaches a null space to a matrix. 8786 8787 Logically Collective 8788 8789 Input Parameters: 8790 + mat - the matrix 8791 - nullsp - the null space object 8792 8793 Level: advanced 8794 8795 Notes: 8796 This null space is used by the `KSP` linear solvers to solve singular systems. 8797 8798 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` 8799 8800 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 8801 to zero but the linear system will still be solved in a least squares sense. 8802 8803 The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that 8804 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). 8805 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 8806 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 8807 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). 8808 This \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix. 8809 8810 If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called 8811 `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this 8812 routine also automatically calls `MatSetTransposeNullSpace()`. 8813 8814 The user should call `MatNullSpaceDestroy()`. 8815 8816 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, 8817 `KSPSetPCSide()` 8818 @*/ 8819 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp) 8820 { 8821 PetscFunctionBegin; 8822 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8823 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8824 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8825 PetscCall(MatNullSpaceDestroy(&mat->nullsp)); 8826 mat->nullsp = nullsp; 8827 if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp)); 8828 PetscFunctionReturn(PETSC_SUCCESS); 8829 } 8830 8831 /*@ 8832 MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix. 8833 8834 Logically Collective 8835 8836 Input Parameters: 8837 + mat - the matrix 8838 - nullsp - the null space object 8839 8840 Level: developer 8841 8842 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()` 8843 @*/ 8844 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp) 8845 { 8846 PetscFunctionBegin; 8847 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8848 PetscValidType(mat, 1); 8849 PetscValidPointer(nullsp, 2); 8850 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp; 8851 PetscFunctionReturn(PETSC_SUCCESS); 8852 } 8853 8854 /*@ 8855 MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix 8856 8857 Logically Collective 8858 8859 Input Parameters: 8860 + mat - the matrix 8861 - nullsp - the null space object 8862 8863 Level: advanced 8864 8865 Notes: 8866 This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning. 8867 8868 See `MatSetNullSpace()` 8869 8870 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()` 8871 @*/ 8872 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp) 8873 { 8874 PetscFunctionBegin; 8875 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8876 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8877 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8878 PetscCall(MatNullSpaceDestroy(&mat->transnullsp)); 8879 mat->transnullsp = nullsp; 8880 PetscFunctionReturn(PETSC_SUCCESS); 8881 } 8882 8883 /*@ 8884 MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions 8885 This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix. 8886 8887 Logically Collective 8888 8889 Input Parameters: 8890 + mat - the matrix 8891 - nullsp - the null space object 8892 8893 Level: advanced 8894 8895 Notes: 8896 Overwrites any previous near null space that may have been attached 8897 8898 You can remove the null space by calling this routine with an nullsp of `NULL` 8899 8900 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()` 8901 @*/ 8902 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp) 8903 { 8904 PetscFunctionBegin; 8905 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8906 PetscValidType(mat, 1); 8907 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8908 MatCheckPreallocated(mat, 1); 8909 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8910 PetscCall(MatNullSpaceDestroy(&mat->nearnullsp)); 8911 mat->nearnullsp = nullsp; 8912 PetscFunctionReturn(PETSC_SUCCESS); 8913 } 8914 8915 /*@ 8916 MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()` 8917 8918 Not Collective 8919 8920 Input Parameter: 8921 . mat - the matrix 8922 8923 Output Parameter: 8924 . nullsp - the null space object, `NULL` if not set 8925 8926 Level: advanced 8927 8928 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()` 8929 @*/ 8930 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp) 8931 { 8932 PetscFunctionBegin; 8933 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8934 PetscValidType(mat, 1); 8935 PetscValidPointer(nullsp, 2); 8936 MatCheckPreallocated(mat, 1); 8937 *nullsp = mat->nearnullsp; 8938 PetscFunctionReturn(PETSC_SUCCESS); 8939 } 8940 8941 /*@C 8942 MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix. 8943 8944 Collective 8945 8946 Input Parameters: 8947 + mat - the matrix 8948 . row - row/column permutation 8949 - info - information on desired factorization process 8950 8951 Level: developer 8952 8953 Notes: 8954 Probably really in-place only when level of fill is zero, otherwise allocates 8955 new space to store factored matrix and deletes previous memory. 8956 8957 Most users should employ the `KSP` interface for linear solvers 8958 instead of working directly with matrix algebra routines such as this. 8959 See, e.g., `KSPCreate()`. 8960 8961 Developer Note: 8962 The Fortran interface is not autogenerated as the 8963 interface definition cannot be generated correctly [due to `MatFactorInfo`] 8964 8965 .seealso: [](chapter_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 8966 @*/ 8967 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info) 8968 { 8969 PetscFunctionBegin; 8970 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8971 PetscValidType(mat, 1); 8972 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 8973 PetscValidPointer(info, 3); 8974 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 8975 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 8976 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8977 MatCheckPreallocated(mat, 1); 8978 PetscUseTypeMethod(mat, iccfactor, row, info); 8979 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 8980 PetscFunctionReturn(PETSC_SUCCESS); 8981 } 8982 8983 /*@ 8984 MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the 8985 ghosted ones. 8986 8987 Not Collective 8988 8989 Input Parameters: 8990 + mat - the matrix 8991 - diag - the diagonal values, including ghost ones 8992 8993 Level: developer 8994 8995 Notes: 8996 Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices 8997 8998 This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()` 8999 9000 .seealso: [](chapter_matrices), `Mat`, `MatDiagonalScale()` 9001 @*/ 9002 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag) 9003 { 9004 PetscMPIInt size; 9005 9006 PetscFunctionBegin; 9007 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9008 PetscValidHeaderSpecific(diag, VEC_CLASSID, 2); 9009 PetscValidType(mat, 1); 9010 9011 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled"); 9012 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 9013 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 9014 if (size == 1) { 9015 PetscInt n, m; 9016 PetscCall(VecGetSize(diag, &n)); 9017 PetscCall(MatGetSize(mat, NULL, &m)); 9018 PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions"); 9019 PetscCall(MatDiagonalScale(mat, NULL, diag)); 9020 } else { 9021 PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag)); 9022 } 9023 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 9024 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9025 PetscFunctionReturn(PETSC_SUCCESS); 9026 } 9027 9028 /*@ 9029 MatGetInertia - Gets the inertia from a factored matrix 9030 9031 Collective 9032 9033 Input Parameter: 9034 . mat - the matrix 9035 9036 Output Parameters: 9037 + nneg - number of negative eigenvalues 9038 . nzero - number of zero eigenvalues 9039 - npos - number of positive eigenvalues 9040 9041 Level: advanced 9042 9043 Note: 9044 Matrix must have been factored by `MatCholeskyFactor()` 9045 9046 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()` 9047 @*/ 9048 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos) 9049 { 9050 PetscFunctionBegin; 9051 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9052 PetscValidType(mat, 1); 9053 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9054 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled"); 9055 PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos); 9056 PetscFunctionReturn(PETSC_SUCCESS); 9057 } 9058 9059 /*@C 9060 MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors 9061 9062 Neighbor-wise Collective 9063 9064 Input Parameters: 9065 + mat - the factored matrix obtained with `MatGetFactor()` 9066 - b - the right-hand-side vectors 9067 9068 Output Parameter: 9069 . x - the result vectors 9070 9071 Level: developer 9072 9073 Note: 9074 The vectors `b` and `x` cannot be the same. I.e., one cannot 9075 call `MatSolves`(A,x,x). 9076 9077 .seealso: [](chapter_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()` 9078 @*/ 9079 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x) 9080 { 9081 PetscFunctionBegin; 9082 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9083 PetscValidType(mat, 1); 9084 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 9085 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9086 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 9087 9088 MatCheckPreallocated(mat, 1); 9089 PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0)); 9090 PetscUseTypeMethod(mat, solves, b, x); 9091 PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0)); 9092 PetscFunctionReturn(PETSC_SUCCESS); 9093 } 9094 9095 /*@ 9096 MatIsSymmetric - Test whether a matrix is symmetric 9097 9098 Collective 9099 9100 Input Parameters: 9101 + A - the matrix to test 9102 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose) 9103 9104 Output Parameter: 9105 . flg - the result 9106 9107 Level: intermediate 9108 9109 Notes: 9110 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9111 9112 If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()` 9113 9114 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9115 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9116 9117 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`, 9118 `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()` 9119 @*/ 9120 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg) 9121 { 9122 PetscFunctionBegin; 9123 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9124 PetscValidBoolPointer(flg, 3); 9125 9126 if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE; 9127 else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE; 9128 else { 9129 if (!A->ops->issymmetric) { 9130 MatType mattype; 9131 PetscCall(MatGetType(A, &mattype)); 9132 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for symmetric", mattype); 9133 } 9134 PetscUseTypeMethod(A, issymmetric, tol, flg); 9135 if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg)); 9136 } 9137 PetscFunctionReturn(PETSC_SUCCESS); 9138 } 9139 9140 /*@ 9141 MatIsHermitian - Test whether a matrix is Hermitian 9142 9143 Collective 9144 9145 Input Parameters: 9146 + A - the matrix to test 9147 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian) 9148 9149 Output Parameter: 9150 . flg - the result 9151 9152 Level: intermediate 9153 9154 Notes: 9155 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9156 9157 If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()` 9158 9159 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9160 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`) 9161 9162 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, 9163 `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()` 9164 @*/ 9165 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg) 9166 { 9167 PetscFunctionBegin; 9168 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9169 PetscValidBoolPointer(flg, 3); 9170 9171 if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE; 9172 else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE; 9173 else { 9174 if (!A->ops->ishermitian) { 9175 MatType mattype; 9176 PetscCall(MatGetType(A, &mattype)); 9177 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for hermitian", mattype); 9178 } 9179 PetscUseTypeMethod(A, ishermitian, tol, flg); 9180 if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg)); 9181 } 9182 PetscFunctionReturn(PETSC_SUCCESS); 9183 } 9184 9185 /*@ 9186 MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state 9187 9188 Not Collective 9189 9190 Input Parameter: 9191 . A - the matrix to check 9192 9193 Output Parameters: 9194 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid) 9195 - flg - the result (only valid if set is `PETSC_TRUE`) 9196 9197 Level: advanced 9198 9199 Notes: 9200 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()` 9201 if you want it explicitly checked 9202 9203 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9204 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9205 9206 .seealso: [](chapter_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9207 @*/ 9208 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9209 { 9210 PetscFunctionBegin; 9211 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9212 PetscValidBoolPointer(set, 2); 9213 PetscValidBoolPointer(flg, 3); 9214 if (A->symmetric != PETSC_BOOL3_UNKNOWN) { 9215 *set = PETSC_TRUE; 9216 *flg = PetscBool3ToBool(A->symmetric); 9217 } else { 9218 *set = PETSC_FALSE; 9219 } 9220 PetscFunctionReturn(PETSC_SUCCESS); 9221 } 9222 9223 /*@ 9224 MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state 9225 9226 Not Collective 9227 9228 Input Parameter: 9229 . A - the matrix to check 9230 9231 Output Parameters: 9232 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid) 9233 - flg - the result (only valid if set is `PETSC_TRUE`) 9234 9235 Level: advanced 9236 9237 Notes: 9238 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). 9239 9240 One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD 9241 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`) 9242 9243 .seealso: [](chapter_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9244 @*/ 9245 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg) 9246 { 9247 PetscFunctionBegin; 9248 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9249 PetscValidBoolPointer(set, 2); 9250 PetscValidBoolPointer(flg, 3); 9251 if (A->spd != PETSC_BOOL3_UNKNOWN) { 9252 *set = PETSC_TRUE; 9253 *flg = PetscBool3ToBool(A->spd); 9254 } else { 9255 *set = PETSC_FALSE; 9256 } 9257 PetscFunctionReturn(PETSC_SUCCESS); 9258 } 9259 9260 /*@ 9261 MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state 9262 9263 Not Collective 9264 9265 Input Parameter: 9266 . A - the matrix to check 9267 9268 Output Parameters: 9269 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid) 9270 - flg - the result (only valid if set is `PETSC_TRUE`) 9271 9272 Level: advanced 9273 9274 Notes: 9275 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()` 9276 if you want it explicitly checked 9277 9278 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9279 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9280 9281 .seealso: [](chapter_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()` 9282 @*/ 9283 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg) 9284 { 9285 PetscFunctionBegin; 9286 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9287 PetscValidBoolPointer(set, 2); 9288 PetscValidBoolPointer(flg, 3); 9289 if (A->hermitian != PETSC_BOOL3_UNKNOWN) { 9290 *set = PETSC_TRUE; 9291 *flg = PetscBool3ToBool(A->hermitian); 9292 } else { 9293 *set = PETSC_FALSE; 9294 } 9295 PetscFunctionReturn(PETSC_SUCCESS); 9296 } 9297 9298 /*@ 9299 MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric 9300 9301 Collective 9302 9303 Input Parameter: 9304 . A - the matrix to test 9305 9306 Output Parameter: 9307 . flg - the result 9308 9309 Level: intermediate 9310 9311 Notes: 9312 If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()` 9313 9314 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 9315 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9316 9317 .seealso: [](chapter_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()` 9318 @*/ 9319 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg) 9320 { 9321 PetscFunctionBegin; 9322 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9323 PetscValidBoolPointer(flg, 2); 9324 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9325 *flg = PetscBool3ToBool(A->structurally_symmetric); 9326 } else { 9327 PetscUseTypeMethod(A, isstructurallysymmetric, flg); 9328 PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg)); 9329 } 9330 PetscFunctionReturn(PETSC_SUCCESS); 9331 } 9332 9333 /*@ 9334 MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state 9335 9336 Not Collective 9337 9338 Input Parameter: 9339 . A - the matrix to check 9340 9341 Output Parameters: 9342 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid) 9343 - flg - the result (only valid if set is PETSC_TRUE) 9344 9345 Level: advanced 9346 9347 Notes: 9348 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 9349 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9350 9351 Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation) 9352 9353 .seealso: [](chapter_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9354 @*/ 9355 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9356 { 9357 PetscFunctionBegin; 9358 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9359 PetscValidBoolPointer(set, 2); 9360 PetscValidBoolPointer(flg, 3); 9361 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9362 *set = PETSC_TRUE; 9363 *flg = PetscBool3ToBool(A->structurally_symmetric); 9364 } else { 9365 *set = PETSC_FALSE; 9366 } 9367 PetscFunctionReturn(PETSC_SUCCESS); 9368 } 9369 9370 /*@ 9371 MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need 9372 to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process 9373 9374 Not Collective 9375 9376 Input Parameter: 9377 . mat - the matrix 9378 9379 Output Parameters: 9380 + nstash - the size of the stash 9381 . reallocs - the number of additional mallocs incurred. 9382 . bnstash - the size of the block stash 9383 - breallocs - the number of additional mallocs incurred.in the block stash 9384 9385 Level: advanced 9386 9387 .seealso: [](chapter_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()` 9388 @*/ 9389 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs) 9390 { 9391 PetscFunctionBegin; 9392 PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs)); 9393 PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs)); 9394 PetscFunctionReturn(PETSC_SUCCESS); 9395 } 9396 9397 /*@C 9398 MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same 9399 parallel layout, `PetscLayout` for rows and columns 9400 9401 Collective 9402 9403 Input Parameter: 9404 . mat - the matrix 9405 9406 Output Parameters: 9407 + right - (optional) vector that the matrix can be multiplied against 9408 - left - (optional) vector that the matrix vector product can be stored in 9409 9410 Level: advanced 9411 9412 Notes: 9413 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()`. 9414 9415 These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed 9416 9417 .seealso: [](chapter_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()` 9418 @*/ 9419 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left) 9420 { 9421 PetscFunctionBegin; 9422 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9423 PetscValidType(mat, 1); 9424 if (mat->ops->getvecs) { 9425 PetscUseTypeMethod(mat, getvecs, right, left); 9426 } else { 9427 PetscInt rbs, cbs; 9428 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 9429 if (right) { 9430 PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup"); 9431 PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), right)); 9432 PetscCall(VecSetSizes(*right, mat->cmap->n, PETSC_DETERMINE)); 9433 PetscCall(VecSetBlockSize(*right, cbs)); 9434 PetscCall(VecSetType(*right, mat->defaultvectype)); 9435 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9436 if (mat->boundtocpu && mat->bindingpropagates) { 9437 PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE)); 9438 PetscCall(VecBindToCPU(*right, PETSC_TRUE)); 9439 } 9440 #endif 9441 PetscCall(PetscLayoutReference(mat->cmap, &(*right)->map)); 9442 } 9443 if (left) { 9444 PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup"); 9445 PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), left)); 9446 PetscCall(VecSetSizes(*left, mat->rmap->n, PETSC_DETERMINE)); 9447 PetscCall(VecSetBlockSize(*left, rbs)); 9448 PetscCall(VecSetType(*left, mat->defaultvectype)); 9449 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9450 if (mat->boundtocpu && mat->bindingpropagates) { 9451 PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE)); 9452 PetscCall(VecBindToCPU(*left, PETSC_TRUE)); 9453 } 9454 #endif 9455 PetscCall(PetscLayoutReference(mat->rmap, &(*left)->map)); 9456 } 9457 } 9458 PetscFunctionReturn(PETSC_SUCCESS); 9459 } 9460 9461 /*@C 9462 MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure 9463 with default values. 9464 9465 Not Collective 9466 9467 Input Parameter: 9468 . info - the `MatFactorInfo` data structure 9469 9470 Level: developer 9471 9472 Notes: 9473 The solvers are generally used through the `KSP` and `PC` objects, for example 9474 `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC` 9475 9476 Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed 9477 9478 Developer Note: 9479 The Fortran interface is not autogenerated as the 9480 interface definition cannot be generated correctly [due to `MatFactorInfo`] 9481 9482 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo` 9483 @*/ 9484 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info) 9485 { 9486 PetscFunctionBegin; 9487 PetscCall(PetscMemzero(info, sizeof(MatFactorInfo))); 9488 PetscFunctionReturn(PETSC_SUCCESS); 9489 } 9490 9491 /*@ 9492 MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed 9493 9494 Collective 9495 9496 Input Parameters: 9497 + mat - the factored matrix 9498 - is - the index set defining the Schur indices (0-based) 9499 9500 Level: advanced 9501 9502 Notes: 9503 Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system. 9504 9505 You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call. 9506 9507 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9508 9509 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`, 9510 `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9511 @*/ 9512 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is) 9513 { 9514 PetscErrorCode (*f)(Mat, IS); 9515 9516 PetscFunctionBegin; 9517 PetscValidType(mat, 1); 9518 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9519 PetscValidType(is, 2); 9520 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 9521 PetscCheckSameComm(mat, 1, is, 2); 9522 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 9523 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f)); 9524 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO"); 9525 PetscCall(MatDestroy(&mat->schur)); 9526 PetscCall((*f)(mat, is)); 9527 PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created"); 9528 PetscFunctionReturn(PETSC_SUCCESS); 9529 } 9530 9531 /*@ 9532 MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step 9533 9534 Logically Collective 9535 9536 Input Parameters: 9537 + F - the factored matrix obtained by calling `MatGetFactor()` 9538 . S - location where to return the Schur complement, can be `NULL` 9539 - status - the status of the Schur complement matrix, can be `NULL` 9540 9541 Level: advanced 9542 9543 Notes: 9544 You must call `MatFactorSetSchurIS()` before calling this routine. 9545 9546 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9547 9548 The routine provides a copy of the Schur matrix stored within the solver data structures. 9549 The caller must destroy the object when it is no longer needed. 9550 If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse. 9551 9552 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) 9553 9554 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9555 9556 Developer Note: 9557 The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc 9558 matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix. 9559 9560 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9561 @*/ 9562 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9563 { 9564 PetscFunctionBegin; 9565 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9566 if (S) PetscValidPointer(S, 2); 9567 if (status) PetscValidPointer(status, 3); 9568 if (S) { 9569 PetscErrorCode (*f)(Mat, Mat *); 9570 9571 PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f)); 9572 if (f) { 9573 PetscCall((*f)(F, S)); 9574 } else { 9575 PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S)); 9576 } 9577 } 9578 if (status) *status = F->schur_status; 9579 PetscFunctionReturn(PETSC_SUCCESS); 9580 } 9581 9582 /*@ 9583 MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix 9584 9585 Logically Collective 9586 9587 Input Parameters: 9588 + F - the factored matrix obtained by calling `MatGetFactor()` 9589 . *S - location where to return the Schur complement, can be `NULL` 9590 - status - the status of the Schur complement matrix, can be `NULL` 9591 9592 Level: advanced 9593 9594 Notes: 9595 You must call `MatFactorSetSchurIS()` before calling this routine. 9596 9597 Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS` 9598 9599 The routine returns a the Schur Complement stored within the data structures of the solver. 9600 9601 If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement. 9602 9603 The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed. 9604 9605 Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix 9606 9607 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9608 9609 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9610 @*/ 9611 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9612 { 9613 PetscFunctionBegin; 9614 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9615 if (S) PetscValidPointer(S, 2); 9616 if (status) PetscValidPointer(status, 3); 9617 if (S) *S = F->schur; 9618 if (status) *status = F->schur_status; 9619 PetscFunctionReturn(PETSC_SUCCESS); 9620 } 9621 9622 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F) 9623 { 9624 Mat S = F->schur; 9625 9626 PetscFunctionBegin; 9627 switch (F->schur_status) { 9628 case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through 9629 case MAT_FACTOR_SCHUR_INVERTED: 9630 if (S) { 9631 S->ops->solve = NULL; 9632 S->ops->matsolve = NULL; 9633 S->ops->solvetranspose = NULL; 9634 S->ops->matsolvetranspose = NULL; 9635 S->ops->solveadd = NULL; 9636 S->ops->solvetransposeadd = NULL; 9637 S->factortype = MAT_FACTOR_NONE; 9638 PetscCall(PetscFree(S->solvertype)); 9639 } 9640 case MAT_FACTOR_SCHUR_FACTORED: // fall-through 9641 break; 9642 default: 9643 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9644 } 9645 PetscFunctionReturn(PETSC_SUCCESS); 9646 } 9647 9648 /*@ 9649 MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()` 9650 9651 Logically Collective 9652 9653 Input Parameters: 9654 + F - the factored matrix obtained by calling `MatGetFactor()` 9655 . *S - location where the Schur complement is stored 9656 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`) 9657 9658 Level: advanced 9659 9660 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9661 @*/ 9662 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status) 9663 { 9664 PetscFunctionBegin; 9665 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9666 if (S) { 9667 PetscValidHeaderSpecific(*S, MAT_CLASSID, 2); 9668 *S = NULL; 9669 } 9670 F->schur_status = status; 9671 PetscCall(MatFactorUpdateSchurStatus_Private(F)); 9672 PetscFunctionReturn(PETSC_SUCCESS); 9673 } 9674 9675 /*@ 9676 MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step 9677 9678 Logically Collective 9679 9680 Input Parameters: 9681 + F - the factored matrix obtained by calling `MatGetFactor()` 9682 . rhs - location where the right hand side of the Schur complement system is stored 9683 - sol - location where the solution of the Schur complement system has to be returned 9684 9685 Level: advanced 9686 9687 Notes: 9688 The sizes of the vectors should match the size of the Schur complement 9689 9690 Must be called after `MatFactorSetSchurIS()` 9691 9692 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()` 9693 @*/ 9694 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol) 9695 { 9696 PetscFunctionBegin; 9697 PetscValidType(F, 1); 9698 PetscValidType(rhs, 2); 9699 PetscValidType(sol, 3); 9700 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9701 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9702 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9703 PetscCheckSameComm(F, 1, rhs, 2); 9704 PetscCheckSameComm(F, 1, sol, 3); 9705 PetscCall(MatFactorFactorizeSchurComplement(F)); 9706 switch (F->schur_status) { 9707 case MAT_FACTOR_SCHUR_FACTORED: 9708 PetscCall(MatSolveTranspose(F->schur, rhs, sol)); 9709 break; 9710 case MAT_FACTOR_SCHUR_INVERTED: 9711 PetscCall(MatMultTranspose(F->schur, rhs, sol)); 9712 break; 9713 default: 9714 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9715 } 9716 PetscFunctionReturn(PETSC_SUCCESS); 9717 } 9718 9719 /*@ 9720 MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step 9721 9722 Logically Collective 9723 9724 Input Parameters: 9725 + F - the factored matrix obtained by calling `MatGetFactor()` 9726 . rhs - location where the right hand side of the Schur complement system is stored 9727 - sol - location where the solution of the Schur complement system has to be returned 9728 9729 Level: advanced 9730 9731 Notes: 9732 The sizes of the vectors should match the size of the Schur complement 9733 9734 Must be called after `MatFactorSetSchurIS()` 9735 9736 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()` 9737 @*/ 9738 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol) 9739 { 9740 PetscFunctionBegin; 9741 PetscValidType(F, 1); 9742 PetscValidType(rhs, 2); 9743 PetscValidType(sol, 3); 9744 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9745 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9746 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9747 PetscCheckSameComm(F, 1, rhs, 2); 9748 PetscCheckSameComm(F, 1, sol, 3); 9749 PetscCall(MatFactorFactorizeSchurComplement(F)); 9750 switch (F->schur_status) { 9751 case MAT_FACTOR_SCHUR_FACTORED: 9752 PetscCall(MatSolve(F->schur, rhs, sol)); 9753 break; 9754 case MAT_FACTOR_SCHUR_INVERTED: 9755 PetscCall(MatMult(F->schur, rhs, sol)); 9756 break; 9757 default: 9758 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9759 } 9760 PetscFunctionReturn(PETSC_SUCCESS); 9761 } 9762 9763 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat); 9764 #if PetscDefined(HAVE_CUDA) 9765 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat); 9766 #endif 9767 9768 /* Schur status updated in the interface */ 9769 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F) 9770 { 9771 Mat S = F->schur; 9772 9773 PetscFunctionBegin; 9774 if (S) { 9775 PetscMPIInt size; 9776 PetscBool isdense, isdensecuda; 9777 9778 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size)); 9779 PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented"); 9780 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense)); 9781 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda)); 9782 PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name); 9783 PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0)); 9784 if (isdense) { 9785 PetscCall(MatSeqDenseInvertFactors_Private(S)); 9786 } else if (isdensecuda) { 9787 #if defined(PETSC_HAVE_CUDA) 9788 PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S)); 9789 #endif 9790 } 9791 // HIP?????????????? 9792 PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0)); 9793 } 9794 PetscFunctionReturn(PETSC_SUCCESS); 9795 } 9796 9797 /*@ 9798 MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step 9799 9800 Logically Collective 9801 9802 Input Parameter: 9803 . F - the factored matrix obtained by calling `MatGetFactor()` 9804 9805 Level: advanced 9806 9807 Notes: 9808 Must be called after `MatFactorSetSchurIS()`. 9809 9810 Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it. 9811 9812 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()` 9813 @*/ 9814 PetscErrorCode MatFactorInvertSchurComplement(Mat F) 9815 { 9816 PetscFunctionBegin; 9817 PetscValidType(F, 1); 9818 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9819 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS); 9820 PetscCall(MatFactorFactorizeSchurComplement(F)); 9821 PetscCall(MatFactorInvertSchurComplement_Private(F)); 9822 F->schur_status = MAT_FACTOR_SCHUR_INVERTED; 9823 PetscFunctionReturn(PETSC_SUCCESS); 9824 } 9825 9826 /*@ 9827 MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step 9828 9829 Logically Collective 9830 9831 Input Parameter: 9832 . F - the factored matrix obtained by calling `MatGetFactor()` 9833 9834 Level: advanced 9835 9836 Note: 9837 Must be called after `MatFactorSetSchurIS()` 9838 9839 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()` 9840 @*/ 9841 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F) 9842 { 9843 MatFactorInfo info; 9844 9845 PetscFunctionBegin; 9846 PetscValidType(F, 1); 9847 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9848 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS); 9849 PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0)); 9850 PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo))); 9851 if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */ 9852 PetscCall(MatCholeskyFactor(F->schur, NULL, &info)); 9853 } else { 9854 PetscCall(MatLUFactor(F->schur, NULL, NULL, &info)); 9855 } 9856 PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0)); 9857 F->schur_status = MAT_FACTOR_SCHUR_FACTORED; 9858 PetscFunctionReturn(PETSC_SUCCESS); 9859 } 9860 9861 /*@ 9862 MatPtAP - Creates the matrix product C = P^T * A * P 9863 9864 Neighbor-wise Collective 9865 9866 Input Parameters: 9867 + A - the matrix 9868 . P - the projection matrix 9869 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9870 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate 9871 if the result is a dense matrix this is irrelevant 9872 9873 Output Parameter: 9874 . C - the product matrix 9875 9876 Level: intermediate 9877 9878 Notes: 9879 C will be created and must be destroyed by the user with `MatDestroy()`. 9880 9881 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9882 9883 Developer Note: 9884 For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`. 9885 9886 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()` 9887 @*/ 9888 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C) 9889 { 9890 PetscFunctionBegin; 9891 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 9892 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9893 9894 if (scall == MAT_INITIAL_MATRIX) { 9895 PetscCall(MatProductCreate(A, P, NULL, C)); 9896 PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP)); 9897 PetscCall(MatProductSetAlgorithm(*C, "default")); 9898 PetscCall(MatProductSetFill(*C, fill)); 9899 9900 (*C)->product->api_user = PETSC_TRUE; 9901 PetscCall(MatProductSetFromOptions(*C)); 9902 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); 9903 PetscCall(MatProductSymbolic(*C)); 9904 } else { /* scall == MAT_REUSE_MATRIX */ 9905 PetscCall(MatProductReplaceMats(A, P, NULL, *C)); 9906 } 9907 9908 PetscCall(MatProductNumeric(*C)); 9909 (*C)->symmetric = A->symmetric; 9910 (*C)->spd = A->spd; 9911 PetscFunctionReturn(PETSC_SUCCESS); 9912 } 9913 9914 /*@ 9915 MatRARt - Creates the matrix product C = R * A * R^T 9916 9917 Neighbor-wise Collective 9918 9919 Input Parameters: 9920 + A - the matrix 9921 . R - the projection matrix 9922 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9923 - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate 9924 if the result is a dense matrix this is irrelevant 9925 9926 Output Parameter: 9927 . C - the product matrix 9928 9929 Level: intermediate 9930 9931 Notes: 9932 C will be created and must be destroyed by the user with `MatDestroy()`. 9933 9934 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9935 9936 This routine is currently only implemented for pairs of `MATAIJ` matrices and classes 9937 which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes, 9938 parallel MatRARt is implemented via explicit transpose of R, which could be very expensive. 9939 We recommend using MatPtAP(). 9940 9941 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()` 9942 @*/ 9943 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C) 9944 { 9945 PetscFunctionBegin; 9946 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 9947 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9948 9949 if (scall == MAT_INITIAL_MATRIX) { 9950 PetscCall(MatProductCreate(A, R, NULL, C)); 9951 PetscCall(MatProductSetType(*C, MATPRODUCT_RARt)); 9952 PetscCall(MatProductSetAlgorithm(*C, "default")); 9953 PetscCall(MatProductSetFill(*C, fill)); 9954 9955 (*C)->product->api_user = PETSC_TRUE; 9956 PetscCall(MatProductSetFromOptions(*C)); 9957 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); 9958 PetscCall(MatProductSymbolic(*C)); 9959 } else { /* scall == MAT_REUSE_MATRIX */ 9960 PetscCall(MatProductReplaceMats(A, R, NULL, *C)); 9961 } 9962 9963 PetscCall(MatProductNumeric(*C)); 9964 if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 9965 PetscFunctionReturn(PETSC_SUCCESS); 9966 } 9967 9968 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C) 9969 { 9970 PetscFunctionBegin; 9971 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9972 9973 if (scall == MAT_INITIAL_MATRIX) { 9974 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype])); 9975 PetscCall(MatProductCreate(A, B, NULL, C)); 9976 PetscCall(MatProductSetType(*C, ptype)); 9977 PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT)); 9978 PetscCall(MatProductSetFill(*C, fill)); 9979 9980 (*C)->product->api_user = PETSC_TRUE; 9981 PetscCall(MatProductSetFromOptions(*C)); 9982 PetscCall(MatProductSymbolic(*C)); 9983 } else { /* scall == MAT_REUSE_MATRIX */ 9984 Mat_Product *product = (*C)->product; 9985 PetscBool isdense; 9986 9987 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, "")); 9988 if (isdense && product && product->type != ptype) { 9989 PetscCall(MatProductClear(*C)); 9990 product = NULL; 9991 } 9992 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype])); 9993 if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */ 9994 PetscCheck(isdense, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first"); 9995 PetscCall(MatProductCreate_Private(A, B, NULL, *C)); 9996 product = (*C)->product; 9997 product->fill = fill; 9998 product->api_user = PETSC_TRUE; 9999 product->clear = PETSC_TRUE; 10000 10001 PetscCall(MatProductSetType(*C, ptype)); 10002 PetscCall(MatProductSetFromOptions(*C)); 10003 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); 10004 PetscCall(MatProductSymbolic(*C)); 10005 } else { /* user may change input matrices A or B when REUSE */ 10006 PetscCall(MatProductReplaceMats(A, B, NULL, *C)); 10007 } 10008 } 10009 PetscCall(MatProductNumeric(*C)); 10010 PetscFunctionReturn(PETSC_SUCCESS); 10011 } 10012 10013 /*@ 10014 MatMatMult - Performs matrix-matrix multiplication C=A*B. 10015 10016 Neighbor-wise Collective 10017 10018 Input Parameters: 10019 + A - the left matrix 10020 . B - the right matrix 10021 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10022 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate 10023 if the result is a dense matrix this is irrelevant 10024 10025 Output Parameter: 10026 . C - the product matrix 10027 10028 Notes: 10029 Unless scall is `MAT_REUSE_MATRIX` C will be created. 10030 10031 `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 10032 call to this function with `MAT_INITIAL_MATRIX`. 10033 10034 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed. 10035 10036 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`, 10037 rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse. 10038 10039 Example of Usage: 10040 .vb 10041 MatProductCreate(A,B,NULL,&C); 10042 MatProductSetType(C,MATPRODUCT_AB); 10043 MatProductSymbolic(C); 10044 MatProductNumeric(C); // compute C=A * B 10045 MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1 10046 MatProductNumeric(C); 10047 MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1 10048 MatProductNumeric(C); 10049 .ve 10050 10051 Level: intermediate 10052 10053 .seealso: [](chapter_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()` 10054 @*/ 10055 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10056 { 10057 PetscFunctionBegin; 10058 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C)); 10059 PetscFunctionReturn(PETSC_SUCCESS); 10060 } 10061 10062 /*@ 10063 MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T. 10064 10065 Neighbor-wise Collective 10066 10067 Input Parameters: 10068 + A - the left matrix 10069 . B - the right matrix 10070 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10071 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 10072 10073 Output Parameter: 10074 . C - the product matrix 10075 10076 Level: intermediate 10077 10078 Notes: 10079 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10080 10081 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call 10082 10083 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10084 actually needed. 10085 10086 This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class, 10087 and for pairs of `MATMPIDENSE` matrices. 10088 10089 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt` 10090 10091 Options Database Keys: 10092 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the 10093 first redundantly copies the transposed B matrix on each process and requiers O(log P) communication complexity; 10094 the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity. 10095 10096 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductCreate()`, `MatProductAlgorithm`, `MatProductType`, `MATPRODUCT_ABt` 10097 @*/ 10098 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10099 { 10100 PetscFunctionBegin; 10101 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C)); 10102 if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10103 PetscFunctionReturn(PETSC_SUCCESS); 10104 } 10105 10106 /*@ 10107 MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B. 10108 10109 Neighbor-wise Collective 10110 10111 Input Parameters: 10112 + A - the left matrix 10113 . B - the right matrix 10114 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10115 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 10116 10117 Output Parameter: 10118 . C - the product matrix 10119 10120 Level: intermediate 10121 10122 Notes: 10123 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10124 10125 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call. 10126 10127 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB` 10128 10129 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10130 actually needed. 10131 10132 This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes 10133 which inherit from `MATSEQAIJ`. C will be of the same type as the input matrices. 10134 10135 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()` 10136 @*/ 10137 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10138 { 10139 PetscFunctionBegin; 10140 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C)); 10141 PetscFunctionReturn(PETSC_SUCCESS); 10142 } 10143 10144 /*@ 10145 MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C. 10146 10147 Neighbor-wise Collective 10148 10149 Input Parameters: 10150 + A - the left matrix 10151 . B - the middle matrix 10152 . C - the right matrix 10153 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10154 - 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 10155 if the result is a dense matrix this is irrelevant 10156 10157 Output Parameter: 10158 . D - the product matrix 10159 10160 Level: intermediate 10161 10162 Notes: 10163 Unless scall is `MAT_REUSE_MATRIX` D will be created. 10164 10165 `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call 10166 10167 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC` 10168 10169 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10170 actually needed. 10171 10172 If you have many matrices with the same non-zero structure to multiply, you 10173 should use `MAT_REUSE_MATRIX` in all calls but the first 10174 10175 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()` 10176 @*/ 10177 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D) 10178 { 10179 PetscFunctionBegin; 10180 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6); 10181 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10182 10183 if (scall == MAT_INITIAL_MATRIX) { 10184 PetscCall(MatProductCreate(A, B, C, D)); 10185 PetscCall(MatProductSetType(*D, MATPRODUCT_ABC)); 10186 PetscCall(MatProductSetAlgorithm(*D, "default")); 10187 PetscCall(MatProductSetFill(*D, fill)); 10188 10189 (*D)->product->api_user = PETSC_TRUE; 10190 PetscCall(MatProductSetFromOptions(*D)); 10191 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, 10192 ((PetscObject)C)->type_name); 10193 PetscCall(MatProductSymbolic(*D)); 10194 } else { /* user may change input matrices when REUSE */ 10195 PetscCall(MatProductReplaceMats(A, B, C, *D)); 10196 } 10197 PetscCall(MatProductNumeric(*D)); 10198 PetscFunctionReturn(PETSC_SUCCESS); 10199 } 10200 10201 /*@ 10202 MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators. 10203 10204 Collective 10205 10206 Input Parameters: 10207 + mat - the matrix 10208 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices) 10209 . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used) 10210 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10211 10212 Output Parameter: 10213 . matredundant - redundant matrix 10214 10215 Level: advanced 10216 10217 Notes: 10218 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 10219 original matrix has not changed from that last call to MatCreateRedundantMatrix(). 10220 10221 This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before 10222 calling it. 10223 10224 `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be. 10225 10226 .seealso: [](chapter_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubComm` 10227 @*/ 10228 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant) 10229 { 10230 MPI_Comm comm; 10231 PetscMPIInt size; 10232 PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs; 10233 Mat_Redundant *redund = NULL; 10234 PetscSubcomm psubcomm = NULL; 10235 MPI_Comm subcomm_in = subcomm; 10236 Mat *matseq; 10237 IS isrow, iscol; 10238 PetscBool newsubcomm = PETSC_FALSE; 10239 10240 PetscFunctionBegin; 10241 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10242 if (nsubcomm && reuse == MAT_REUSE_MATRIX) { 10243 PetscValidPointer(*matredundant, 5); 10244 PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5); 10245 } 10246 10247 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10248 if (size == 1 || nsubcomm == 1) { 10249 if (reuse == MAT_INITIAL_MATRIX) { 10250 PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant)); 10251 } else { 10252 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"); 10253 PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN)); 10254 } 10255 PetscFunctionReturn(PETSC_SUCCESS); 10256 } 10257 10258 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10259 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10260 MatCheckPreallocated(mat, 1); 10261 10262 PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0)); 10263 if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */ 10264 /* create psubcomm, then get subcomm */ 10265 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10266 PetscCallMPI(MPI_Comm_size(comm, &size)); 10267 PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size); 10268 10269 PetscCall(PetscSubcommCreate(comm, &psubcomm)); 10270 PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm)); 10271 PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS)); 10272 PetscCall(PetscSubcommSetFromOptions(psubcomm)); 10273 PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL)); 10274 newsubcomm = PETSC_TRUE; 10275 PetscCall(PetscSubcommDestroy(&psubcomm)); 10276 } 10277 10278 /* get isrow, iscol and a local sequential matrix matseq[0] */ 10279 if (reuse == MAT_INITIAL_MATRIX) { 10280 mloc_sub = PETSC_DECIDE; 10281 nloc_sub = PETSC_DECIDE; 10282 if (bs < 1) { 10283 PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M)); 10284 PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N)); 10285 } else { 10286 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M)); 10287 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N)); 10288 } 10289 PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm)); 10290 rstart = rend - mloc_sub; 10291 PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow)); 10292 PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol)); 10293 } else { /* reuse == MAT_REUSE_MATRIX */ 10294 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"); 10295 /* retrieve subcomm */ 10296 PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm)); 10297 redund = (*matredundant)->redundant; 10298 isrow = redund->isrow; 10299 iscol = redund->iscol; 10300 matseq = redund->matseq; 10301 } 10302 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq)); 10303 10304 /* get matredundant over subcomm */ 10305 if (reuse == MAT_INITIAL_MATRIX) { 10306 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant)); 10307 10308 /* create a supporting struct and attach it to C for reuse */ 10309 PetscCall(PetscNew(&redund)); 10310 (*matredundant)->redundant = redund; 10311 redund->isrow = isrow; 10312 redund->iscol = iscol; 10313 redund->matseq = matseq; 10314 if (newsubcomm) { 10315 redund->subcomm = subcomm; 10316 } else { 10317 redund->subcomm = MPI_COMM_NULL; 10318 } 10319 } else { 10320 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant)); 10321 } 10322 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 10323 if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) { 10324 PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE)); 10325 PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE)); 10326 } 10327 #endif 10328 PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0)); 10329 PetscFunctionReturn(PETSC_SUCCESS); 10330 } 10331 10332 /*@C 10333 MatGetMultiProcBlock - Create multiple 'parallel submatrices' from 10334 a given `Mat`. Each submatrix can span multiple procs. 10335 10336 Collective 10337 10338 Input Parameters: 10339 + mat - the matrix 10340 . subcomm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))` 10341 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10342 10343 Output Parameter: 10344 . subMat - parallel sub-matrices each spanning a given `subcomm` 10345 10346 Level: advanced 10347 10348 Notes: 10349 The submatrix partition across processors is dictated by `subComm` a 10350 communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm` 10351 is not restricted to be grouped with consecutive original ranks. 10352 10353 Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices 10354 map directly to the layout of the original matrix [wrt the local 10355 row,col partitioning]. So the original 'DiagonalMat' naturally maps 10356 into the 'DiagonalMat' of the `subMat`, hence it is used directly from 10357 the `subMat`. However the offDiagMat looses some columns - and this is 10358 reconstructed with `MatSetValues()` 10359 10360 This is used by `PCBJACOBI` when a single block spans multiple MPI ranks 10361 10362 .seealso: [](chapter_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI` 10363 @*/ 10364 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) 10365 { 10366 PetscMPIInt commsize, subCommSize; 10367 10368 PetscFunctionBegin; 10369 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize)); 10370 PetscCallMPI(MPI_Comm_size(subComm, &subCommSize)); 10371 PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize); 10372 10373 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"); 10374 PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10375 PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat); 10376 PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10377 PetscFunctionReturn(PETSC_SUCCESS); 10378 } 10379 10380 /*@ 10381 MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering 10382 10383 Not Collective 10384 10385 Input Parameters: 10386 + mat - matrix to extract local submatrix from 10387 . isrow - local row indices for submatrix 10388 - iscol - local column indices for submatrix 10389 10390 Output Parameter: 10391 . submat - the submatrix 10392 10393 Level: intermediate 10394 10395 Notes: 10396 `submat` should be disposed of with `MatRestoreLocalSubMatrix()`. 10397 10398 Depending on the format of `mat`, the returned submat may not implement `MatMult()`. Its communicator may be 10399 the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of `mat`'s. 10400 10401 `submat` always implements `MatSetValuesLocal()`. If `isrow` and `iscol` have the same block size, then 10402 `MatSetValuesBlockedLocal()` will also be implemented. 10403 10404 `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`. 10405 Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided. 10406 10407 .seealso: [](chapter_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()` 10408 @*/ 10409 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10410 { 10411 PetscFunctionBegin; 10412 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10413 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10414 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10415 PetscCheckSameComm(isrow, 2, iscol, 3); 10416 PetscValidPointer(submat, 4); 10417 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call"); 10418 10419 if (mat->ops->getlocalsubmatrix) { 10420 PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat); 10421 } else { 10422 PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat)); 10423 } 10424 PetscFunctionReturn(PETSC_SUCCESS); 10425 } 10426 10427 /*@ 10428 MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()` 10429 10430 Not Collective 10431 10432 Input Parameters: 10433 + mat - matrix to extract local submatrix from 10434 . isrow - local row indices for submatrix 10435 . iscol - local column indices for submatrix 10436 - submat - the submatrix 10437 10438 Level: intermediate 10439 10440 .seealso: [](chapter_matrices), `Mat`, `MatGetLocalSubMatrix()` 10441 @*/ 10442 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10443 { 10444 PetscFunctionBegin; 10445 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10446 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10447 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10448 PetscCheckSameComm(isrow, 2, iscol, 3); 10449 PetscValidPointer(submat, 4); 10450 if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4); 10451 10452 if (mat->ops->restorelocalsubmatrix) { 10453 PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat); 10454 } else { 10455 PetscCall(MatDestroy(submat)); 10456 } 10457 *submat = NULL; 10458 PetscFunctionReturn(PETSC_SUCCESS); 10459 } 10460 10461 /*@ 10462 MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix 10463 10464 Collective 10465 10466 Input Parameter: 10467 . mat - the matrix 10468 10469 Output Parameter: 10470 . is - if any rows have zero diagonals this contains the list of them 10471 10472 Level: developer 10473 10474 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10475 @*/ 10476 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is) 10477 { 10478 PetscFunctionBegin; 10479 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10480 PetscValidType(mat, 1); 10481 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10482 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10483 10484 if (!mat->ops->findzerodiagonals) { 10485 Vec diag; 10486 const PetscScalar *a; 10487 PetscInt *rows; 10488 PetscInt rStart, rEnd, r, nrow = 0; 10489 10490 PetscCall(MatCreateVecs(mat, &diag, NULL)); 10491 PetscCall(MatGetDiagonal(mat, diag)); 10492 PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd)); 10493 PetscCall(VecGetArrayRead(diag, &a)); 10494 for (r = 0; r < rEnd - rStart; ++r) 10495 if (a[r] == 0.0) ++nrow; 10496 PetscCall(PetscMalloc1(nrow, &rows)); 10497 nrow = 0; 10498 for (r = 0; r < rEnd - rStart; ++r) 10499 if (a[r] == 0.0) rows[nrow++] = r + rStart; 10500 PetscCall(VecRestoreArrayRead(diag, &a)); 10501 PetscCall(VecDestroy(&diag)); 10502 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is)); 10503 } else { 10504 PetscUseTypeMethod(mat, findzerodiagonals, is); 10505 } 10506 PetscFunctionReturn(PETSC_SUCCESS); 10507 } 10508 10509 /*@ 10510 MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size) 10511 10512 Collective 10513 10514 Input Parameter: 10515 . mat - the matrix 10516 10517 Output Parameter: 10518 . is - contains the list of rows with off block diagonal entries 10519 10520 Level: developer 10521 10522 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10523 @*/ 10524 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is) 10525 { 10526 PetscFunctionBegin; 10527 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10528 PetscValidType(mat, 1); 10529 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10530 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10531 10532 PetscUseTypeMethod(mat, findoffblockdiagonalentries, is); 10533 PetscFunctionReturn(PETSC_SUCCESS); 10534 } 10535 10536 /*@C 10537 MatInvertBlockDiagonal - Inverts the block diagonal entries. 10538 10539 Collective; No Fortran Support 10540 10541 Input Parameter: 10542 . mat - the matrix 10543 10544 Output Parameter: 10545 . values - the block inverses in column major order (FORTRAN-like) 10546 10547 Level: advanced 10548 10549 Notes: 10550 The size of the blocks is determined by the block size of the matrix. 10551 10552 The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case 10553 10554 The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size 10555 10556 .seealso: [](chapter_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()` 10557 @*/ 10558 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values) 10559 { 10560 PetscFunctionBegin; 10561 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10562 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10563 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10564 PetscUseTypeMethod(mat, invertblockdiagonal, values); 10565 PetscFunctionReturn(PETSC_SUCCESS); 10566 } 10567 10568 /*@C 10569 MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries. 10570 10571 Collective; No Fortran Support 10572 10573 Input Parameters: 10574 + mat - the matrix 10575 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()` 10576 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()` 10577 10578 Output Parameter: 10579 . values - the block inverses in column major order (FORTRAN-like) 10580 10581 Level: advanced 10582 10583 Notes: 10584 Use `MatInvertBlockDiagonal()` if all blocks have the same size 10585 10586 The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case 10587 10588 .seealso: [](chapter_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()` 10589 @*/ 10590 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values) 10591 { 10592 PetscFunctionBegin; 10593 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10594 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10595 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10596 PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values); 10597 PetscFunctionReturn(PETSC_SUCCESS); 10598 } 10599 10600 /*@ 10601 MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A 10602 10603 Collective 10604 10605 Input Parameters: 10606 + A - the matrix 10607 - C - matrix with inverted block diagonal of `A`. This matrix should be created and may have its type set. 10608 10609 Level: advanced 10610 10611 Note: 10612 The blocksize of the matrix is used to determine the blocks on the diagonal of `C` 10613 10614 .seealso: [](chapter_matrices), `Mat`, `MatInvertBlockDiagonal()` 10615 @*/ 10616 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C) 10617 { 10618 const PetscScalar *vals; 10619 PetscInt *dnnz; 10620 PetscInt m, rstart, rend, bs, i, j; 10621 10622 PetscFunctionBegin; 10623 PetscCall(MatInvertBlockDiagonal(A, &vals)); 10624 PetscCall(MatGetBlockSize(A, &bs)); 10625 PetscCall(MatGetLocalSize(A, &m, NULL)); 10626 PetscCall(MatSetLayouts(C, A->rmap, A->cmap)); 10627 PetscCall(PetscMalloc1(m / bs, &dnnz)); 10628 for (j = 0; j < m / bs; j++) dnnz[j] = 1; 10629 PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL)); 10630 PetscCall(PetscFree(dnnz)); 10631 PetscCall(MatGetOwnershipRange(C, &rstart, &rend)); 10632 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE)); 10633 for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES)); 10634 PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 10635 PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 10636 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE)); 10637 PetscFunctionReturn(PETSC_SUCCESS); 10638 } 10639 10640 /*@C 10641 MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created 10642 via `MatTransposeColoringCreate()`. 10643 10644 Collective 10645 10646 Input Parameter: 10647 . c - coloring context 10648 10649 Level: intermediate 10650 10651 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringCreate()` 10652 @*/ 10653 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c) 10654 { 10655 MatTransposeColoring matcolor = *c; 10656 10657 PetscFunctionBegin; 10658 if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS); 10659 if (--((PetscObject)matcolor)->refct > 0) { 10660 matcolor = NULL; 10661 PetscFunctionReturn(PETSC_SUCCESS); 10662 } 10663 10664 PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow)); 10665 PetscCall(PetscFree(matcolor->rows)); 10666 PetscCall(PetscFree(matcolor->den2sp)); 10667 PetscCall(PetscFree(matcolor->colorforcol)); 10668 PetscCall(PetscFree(matcolor->columns)); 10669 if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart)); 10670 PetscCall(PetscHeaderDestroy(c)); 10671 PetscFunctionReturn(PETSC_SUCCESS); 10672 } 10673 10674 /*@C 10675 MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which 10676 a `MatTransposeColoring` context has been created, computes a dense B^T by applying 10677 `MatTransposeColoring` to sparse B. 10678 10679 Collective 10680 10681 Input Parameters: 10682 + coloring - coloring context created with `MatTransposeColoringCreate()` 10683 - B - sparse matrix 10684 10685 Output Parameter: 10686 . Btdense - dense matrix B^T 10687 10688 Level: developer 10689 10690 Note: 10691 These are used internally for some implementations of `MatRARt()` 10692 10693 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()` 10694 @*/ 10695 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense) 10696 { 10697 PetscFunctionBegin; 10698 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 10699 PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3); 10700 PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10701 10702 PetscCall((B->ops->transcoloringapplysptoden)(coloring, B, Btdense)); 10703 PetscFunctionReturn(PETSC_SUCCESS); 10704 } 10705 10706 /*@C 10707 MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which 10708 a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense 10709 in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix 10710 `Csp` from `Cden`. 10711 10712 Collective 10713 10714 Input Parameters: 10715 + matcoloring - coloring context created with `MatTransposeColoringCreate()` 10716 - Cden - matrix product of a sparse matrix and a dense matrix Btdense 10717 10718 Output Parameter: 10719 . Csp - sparse matrix 10720 10721 Level: developer 10722 10723 Note: 10724 These are used internally for some implementations of `MatRARt()` 10725 10726 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()` 10727 @*/ 10728 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp) 10729 { 10730 PetscFunctionBegin; 10731 PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10732 PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2); 10733 PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3); 10734 10735 PetscCall((Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp)); 10736 PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY)); 10737 PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY)); 10738 PetscFunctionReturn(PETSC_SUCCESS); 10739 } 10740 10741 /*@C 10742 MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T. 10743 10744 Collective 10745 10746 Input Parameters: 10747 + mat - the matrix product C 10748 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()` 10749 10750 Output Parameter: 10751 . color - the new coloring context 10752 10753 Level: intermediate 10754 10755 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`, 10756 `MatTransColoringApplyDenToSp()` 10757 @*/ 10758 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color) 10759 { 10760 MatTransposeColoring c; 10761 MPI_Comm comm; 10762 10763 PetscFunctionBegin; 10764 PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10765 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10766 PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL)); 10767 10768 c->ctype = iscoloring->ctype; 10769 PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c); 10770 10771 *color = c; 10772 PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10773 PetscFunctionReturn(PETSC_SUCCESS); 10774 } 10775 10776 /*@ 10777 MatGetNonzeroState - Returns a 64 bit integer representing the current state of nonzeros in the matrix. If the 10778 matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the 10779 same, otherwise it will be larger 10780 10781 Not Collective 10782 10783 Input Parameter: 10784 . A - the matrix 10785 10786 Output Parameter: 10787 . state - the current state 10788 10789 Level: intermediate 10790 10791 Notes: 10792 You can only compare states from two different calls to the SAME matrix, you cannot compare calls between 10793 different matrices 10794 10795 Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix 10796 10797 Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers. 10798 10799 .seealso: [](chapter_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()` 10800 @*/ 10801 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state) 10802 { 10803 PetscFunctionBegin; 10804 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10805 *state = mat->nonzerostate; 10806 PetscFunctionReturn(PETSC_SUCCESS); 10807 } 10808 10809 /*@ 10810 MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential 10811 matrices from each processor 10812 10813 Collective 10814 10815 Input Parameters: 10816 + comm - the communicators the parallel matrix will live on 10817 . seqmat - the input sequential matrices 10818 . n - number of local columns (or `PETSC_DECIDE`) 10819 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10820 10821 Output Parameter: 10822 . mpimat - the parallel matrix generated 10823 10824 Level: developer 10825 10826 Note: 10827 The number of columns of the matrix in EACH processor MUST be the same. 10828 10829 .seealso: [](chapter_matrices), `Mat` 10830 @*/ 10831 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat) 10832 { 10833 PetscMPIInt size; 10834 10835 PetscFunctionBegin; 10836 PetscCallMPI(MPI_Comm_size(comm, &size)); 10837 if (size == 1) { 10838 if (reuse == MAT_INITIAL_MATRIX) { 10839 PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat)); 10840 } else { 10841 PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN)); 10842 } 10843 PetscFunctionReturn(PETSC_SUCCESS); 10844 } 10845 10846 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"); 10847 10848 PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0)); 10849 PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat)); 10850 PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0)); 10851 PetscFunctionReturn(PETSC_SUCCESS); 10852 } 10853 10854 /*@ 10855 MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent ranks' ownership ranges. 10856 10857 Collective 10858 10859 Input Parameters: 10860 + A - the matrix to create subdomains from 10861 - N - requested number of subdomains 10862 10863 Output Parameters: 10864 + n - number of subdomains resulting on this rank 10865 - iss - `IS` list with indices of subdomains on this rank 10866 10867 Level: advanced 10868 10869 Note: 10870 The number of subdomains must be smaller than the communicator size 10871 10872 .seealso: [](chapter_matrices), `Mat`, `IS` 10873 @*/ 10874 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[]) 10875 { 10876 MPI_Comm comm, subcomm; 10877 PetscMPIInt size, rank, color; 10878 PetscInt rstart, rend, k; 10879 10880 PetscFunctionBegin; 10881 PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 10882 PetscCallMPI(MPI_Comm_size(comm, &size)); 10883 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 10884 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); 10885 *n = 1; 10886 k = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */ 10887 color = rank / k; 10888 PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm)); 10889 PetscCall(PetscMalloc1(1, iss)); 10890 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 10891 PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0])); 10892 PetscCallMPI(MPI_Comm_free(&subcomm)); 10893 PetscFunctionReturn(PETSC_SUCCESS); 10894 } 10895 10896 /*@ 10897 MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection. 10898 10899 If the interpolation and restriction operators are the same, uses `MatPtAP()`. 10900 If they are not the same, uses `MatMatMatMult()`. 10901 10902 Once the coarse grid problem is constructed, correct for interpolation operators 10903 that are not of full rank, which can legitimately happen in the case of non-nested 10904 geometric multigrid. 10905 10906 Input Parameters: 10907 + restrct - restriction operator 10908 . dA - fine grid matrix 10909 . interpolate - interpolation operator 10910 . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10911 - fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate 10912 10913 Output Parameter: 10914 . A - the Galerkin coarse matrix 10915 10916 Options Database Key: 10917 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used 10918 10919 Level: developer 10920 10921 .seealso: [](chapter_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()` 10922 @*/ 10923 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A) 10924 { 10925 IS zerorows; 10926 Vec diag; 10927 10928 PetscFunctionBegin; 10929 PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10930 /* Construct the coarse grid matrix */ 10931 if (interpolate == restrct) { 10932 PetscCall(MatPtAP(dA, interpolate, reuse, fill, A)); 10933 } else { 10934 PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A)); 10935 } 10936 10937 /* If the interpolation matrix is not of full rank, A will have zero rows. 10938 This can legitimately happen in the case of non-nested geometric multigrid. 10939 In that event, we set the rows of the matrix to the rows of the identity, 10940 ignoring the equations (as the RHS will also be zero). */ 10941 10942 PetscCall(MatFindZeroRows(*A, &zerorows)); 10943 10944 if (zerorows != NULL) { /* if there are any zero rows */ 10945 PetscCall(MatCreateVecs(*A, &diag, NULL)); 10946 PetscCall(MatGetDiagonal(*A, diag)); 10947 PetscCall(VecISSet(diag, zerorows, 1.0)); 10948 PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES)); 10949 PetscCall(VecDestroy(&diag)); 10950 PetscCall(ISDestroy(&zerorows)); 10951 } 10952 PetscFunctionReturn(PETSC_SUCCESS); 10953 } 10954 10955 /*@C 10956 MatSetOperation - Allows user to set a matrix operation for any matrix type 10957 10958 Logically Collective 10959 10960 Input Parameters: 10961 + mat - the matrix 10962 . op - the name of the operation 10963 - f - the function that provides the operation 10964 10965 Level: developer 10966 10967 Usage: 10968 .vb 10969 extern PetscErrorCode usermult(Mat, Vec, Vec); 10970 10971 PetscCall(MatCreateXXX(comm, ..., &A)); 10972 PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFunction)usermult)); 10973 .ve 10974 10975 Notes: 10976 See the file `include/petscmat.h` for a complete list of matrix 10977 operations, which all have the form MATOP_<OPERATION>, where 10978 <OPERATION> is the name (in all capital letters) of the 10979 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 10980 10981 All user-provided functions (except for `MATOP_DESTROY`) should have the same calling 10982 sequence as the usual matrix interface routines, since they 10983 are intended to be accessed via the usual matrix interface 10984 routines, e.g., 10985 .vb 10986 MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec) 10987 .ve 10988 10989 In particular each function MUST return `PETSC_SUCCESS` on success and 10990 nonzero on failure. 10991 10992 This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type. 10993 10994 .seealso: [](chapter_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()` 10995 @*/ 10996 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void)) 10997 { 10998 PetscFunctionBegin; 10999 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11000 if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view; 11001 (((void (**)(void))mat->ops)[op]) = f; 11002 PetscFunctionReturn(PETSC_SUCCESS); 11003 } 11004 11005 /*@C 11006 MatGetOperation - Gets a matrix operation for any matrix type. 11007 11008 Not Collective 11009 11010 Input Parameters: 11011 + mat - the matrix 11012 - op - the name of the operation 11013 11014 Output Parameter: 11015 . f - the function that provides the operation 11016 11017 Level: developer 11018 11019 Usage: 11020 .vb 11021 PetscErrorCode (*usermult)(Mat, Vec, Vec); 11022 MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult); 11023 .ve 11024 11025 Notes: 11026 See the file include/petscmat.h for a complete list of matrix 11027 operations, which all have the form MATOP_<OPERATION>, where 11028 <OPERATION> is the name (in all capital letters) of the 11029 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11030 11031 This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type. 11032 11033 .seealso: [](chapter_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()` 11034 @*/ 11035 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void)) 11036 { 11037 PetscFunctionBegin; 11038 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11039 *f = (((void (**)(void))mat->ops)[op]); 11040 PetscFunctionReturn(PETSC_SUCCESS); 11041 } 11042 11043 /*@ 11044 MatHasOperation - Determines whether the given matrix supports the particular operation. 11045 11046 Not Collective 11047 11048 Input Parameters: 11049 + mat - the matrix 11050 - op - the operation, for example, `MATOP_GET_DIAGONAL` 11051 11052 Output Parameter: 11053 . has - either `PETSC_TRUE` or `PETSC_FALSE` 11054 11055 Level: advanced 11056 11057 Note: 11058 See `MatSetOperation()` for additional discussion on naming convention and usage of `op`. 11059 11060 .seealso: [](chapter_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()` 11061 @*/ 11062 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has) 11063 { 11064 PetscFunctionBegin; 11065 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11066 PetscValidBoolPointer(has, 3); 11067 if (mat->ops->hasoperation) { 11068 PetscUseTypeMethod(mat, hasoperation, op, has); 11069 } else { 11070 if (((void **)mat->ops)[op]) *has = PETSC_TRUE; 11071 else { 11072 *has = PETSC_FALSE; 11073 if (op == MATOP_CREATE_SUBMATRIX) { 11074 PetscMPIInt size; 11075 11076 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 11077 if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has)); 11078 } 11079 } 11080 } 11081 PetscFunctionReturn(PETSC_SUCCESS); 11082 } 11083 11084 /*@ 11085 MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent 11086 11087 Collective 11088 11089 Input Parameter: 11090 . mat - the matrix 11091 11092 Output Parameter: 11093 . cong - either `PETSC_TRUE` or `PETSC_FALSE` 11094 11095 Level: beginner 11096 11097 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout` 11098 @*/ 11099 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong) 11100 { 11101 PetscFunctionBegin; 11102 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11103 PetscValidType(mat, 1); 11104 PetscValidBoolPointer(cong, 2); 11105 if (!mat->rmap || !mat->cmap) { 11106 *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE; 11107 PetscFunctionReturn(PETSC_SUCCESS); 11108 } 11109 if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */ 11110 PetscCall(PetscLayoutSetUp(mat->rmap)); 11111 PetscCall(PetscLayoutSetUp(mat->cmap)); 11112 PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong)); 11113 if (*cong) mat->congruentlayouts = 1; 11114 else mat->congruentlayouts = 0; 11115 } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE; 11116 PetscFunctionReturn(PETSC_SUCCESS); 11117 } 11118 11119 PetscErrorCode MatSetInf(Mat A) 11120 { 11121 PetscFunctionBegin; 11122 PetscUseTypeMethod(A, setinf); 11123 PetscFunctionReturn(PETSC_SUCCESS); 11124 } 11125 11126 /*@C 11127 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 11128 and possibly removes small values from the graph structure. 11129 11130 Collective 11131 11132 Input Parameters: 11133 + A - the matrix 11134 . sym - `PETSC_TRUE` indicates that the graph should be symmetrized 11135 . scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry 11136 - filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value 11137 11138 Output Parameter: 11139 . graph - the resulting graph 11140 11141 Level: advanced 11142 11143 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `PCGAMG` 11144 @*/ 11145 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph) 11146 { 11147 PetscFunctionBegin; 11148 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11149 PetscValidType(A, 1); 11150 PetscValidLogicalCollectiveBool(A, scale, 3); 11151 PetscValidPointer(graph, 5); 11152 PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph); 11153 PetscFunctionReturn(PETSC_SUCCESS); 11154 } 11155 11156 /*@ 11157 MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place, 11158 meaning the same memory is used for the matrix, and no new memory is allocated. 11159 11160 Collective 11161 11162 Input Parameter: 11163 . A - the matrix 11164 11165 Level: intermediate 11166 11167 Developer Note: 11168 The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end 11169 of the arrays in the data structure are unneeded. 11170 11171 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatChop()` 11172 @*/ 11173 PetscErrorCode MatEliminateZeros(Mat A) 11174 { 11175 PetscFunctionBegin; 11176 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11177 PetscUseTypeMethod(A, eliminatezeros); 11178 PetscFunctionReturn(PETSC_SUCCESS); 11179 } 11180