1 /* 2 This is where the abstract matrix operations are defined 3 Portions of this code are under: 4 Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved. 5 */ 6 7 #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/ 8 #include <petsc/private/isimpl.h> 9 #include <petsc/private/vecimpl.h> 10 11 /* Logging support */ 12 PetscClassId MAT_CLASSID; 13 PetscClassId MAT_COLORING_CLASSID; 14 PetscClassId MAT_FDCOLORING_CLASSID; 15 PetscClassId MAT_TRANSPOSECOLORING_CLASSID; 16 17 PetscLogEvent MAT_Mult, MAT_MultAdd, MAT_MultTranspose; 18 PetscLogEvent MAT_MultTransposeAdd, MAT_Solve, MAT_Solves, MAT_SolveAdd, MAT_SolveTranspose, MAT_MatSolve, MAT_MatTrSolve; 19 PetscLogEvent MAT_SolveTransposeAdd, MAT_SOR, MAT_ForwardSolve, MAT_BackwardSolve, MAT_LUFactor, MAT_LUFactorSymbolic; 20 PetscLogEvent MAT_LUFactorNumeric, MAT_CholeskyFactor, MAT_CholeskyFactorSymbolic, MAT_CholeskyFactorNumeric, MAT_ILUFactor; 21 PetscLogEvent MAT_ILUFactorSymbolic, MAT_ICCFactorSymbolic, MAT_Copy, MAT_Convert, MAT_Scale, MAT_AssemblyBegin; 22 PetscLogEvent MAT_QRFactorNumeric, MAT_QRFactorSymbolic, MAT_QRFactor; 23 PetscLogEvent MAT_AssemblyEnd, MAT_SetValues, MAT_GetValues, MAT_GetRow, MAT_GetRowIJ, MAT_CreateSubMats, MAT_GetOrdering, MAT_RedundantMat, MAT_GetSeqNonzeroStructure; 24 PetscLogEvent MAT_IncreaseOverlap, MAT_Partitioning, MAT_PartitioningND, MAT_Coarsen, MAT_ZeroEntries, MAT_Load, MAT_View, MAT_AXPY, MAT_FDColoringCreate; 25 PetscLogEvent MAT_FDColoringSetUp, MAT_FDColoringApply, MAT_Transpose, MAT_FDColoringFunction, MAT_CreateSubMat; 26 PetscLogEvent MAT_TransposeColoringCreate; 27 PetscLogEvent MAT_MatMult, MAT_MatMultSymbolic, MAT_MatMultNumeric; 28 PetscLogEvent MAT_PtAP, MAT_PtAPSymbolic, MAT_PtAPNumeric, MAT_RARt, MAT_RARtSymbolic, MAT_RARtNumeric; 29 PetscLogEvent MAT_MatTransposeMult, MAT_MatTransposeMultSymbolic, MAT_MatTransposeMultNumeric; 30 PetscLogEvent MAT_TransposeMatMult, MAT_TransposeMatMultSymbolic, MAT_TransposeMatMultNumeric; 31 PetscLogEvent MAT_MatMatMult, MAT_MatMatMultSymbolic, MAT_MatMatMultNumeric; 32 PetscLogEvent MAT_MultHermitianTranspose, MAT_MultHermitianTransposeAdd; 33 PetscLogEvent MAT_Getsymtransreduced, MAT_GetBrowsOfAcols; 34 PetscLogEvent MAT_GetBrowsOfAocols, MAT_Getlocalmat, MAT_Getlocalmatcondensed, MAT_Seqstompi, MAT_Seqstompinum, MAT_Seqstompisym; 35 PetscLogEvent MAT_GetMultiProcBlock; 36 PetscLogEvent MAT_CUSPARSECopyToGPU, MAT_CUSPARSECopyFromGPU, MAT_CUSPARSEGenerateTranspose, MAT_CUSPARSESolveAnalysis; 37 PetscLogEvent MAT_HIPSPARSECopyToGPU, MAT_HIPSPARSECopyFromGPU, MAT_HIPSPARSEGenerateTranspose, MAT_HIPSPARSESolveAnalysis; 38 PetscLogEvent MAT_PreallCOO, MAT_SetVCOO; 39 PetscLogEvent MAT_SetValuesBatch; 40 PetscLogEvent MAT_ViennaCLCopyToGPU; 41 PetscLogEvent MAT_CUDACopyToGPU; 42 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU; 43 PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom; 44 PetscLogEvent MAT_FactorFactS, MAT_FactorInvS; 45 PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights; 46 PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR; 47 48 const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL}; 49 50 /*@ 51 MatSetRandom - Sets all components of a matrix to random numbers. 52 53 Logically Collective 54 55 Input Parameters: 56 + x - the matrix 57 - rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or `NULL` and 58 it will create one internally. 59 60 Example: 61 .vb 62 PetscRandomCreate(PETSC_COMM_WORLD,&rctx); 63 MatSetRandom(x,rctx); 64 PetscRandomDestroy(rctx); 65 .ve 66 67 Level: intermediate 68 69 Notes: 70 For sparse matrices that have been preallocated but not been assembled it randomly selects appropriate locations, 71 72 for sparse matrices that already have locations it fills the locations with random numbers. 73 74 It generates an error if used on sparse matrices that have not been preallocated. 75 76 .seealso: [](ch_matrices), `Mat`, `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `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: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, 129 `MAT_FACTOR_NUMERIC_ZEROPIVOT` 130 @*/ 131 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row) 132 { 133 PetscFunctionBegin; 134 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 135 PetscValidRealPointer(pivot, 2); 136 PetscValidIntPointer(row, 3); 137 *pivot = mat->factorerror_zeropivot_value; 138 *row = mat->factorerror_zeropivot_row; 139 PetscFunctionReturn(PETSC_SUCCESS); 140 } 141 142 /*@ 143 MatFactorGetError - gets the error code from a factorization 144 145 Logically Collective 146 147 Input Parameter: 148 . mat - the factored matrix 149 150 Output Parameter: 151 . err - the error code 152 153 Level: advanced 154 155 Note: 156 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 157 158 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, 159 `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, `MatFactorError` 160 @*/ 161 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err) 162 { 163 PetscFunctionBegin; 164 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 165 PetscValidPointer(err, 2); 166 *err = mat->factorerrortype; 167 PetscFunctionReturn(PETSC_SUCCESS); 168 } 169 170 /*@ 171 MatFactorClearError - clears the error code in a factorization 172 173 Logically Collective 174 175 Input Parameter: 176 . mat - the factored matrix 177 178 Level: developer 179 180 Note: 181 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 182 183 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`, 184 `MatGetErrorCode()`, `MatFactorError` 185 @*/ 186 PetscErrorCode MatFactorClearError(Mat mat) 187 { 188 PetscFunctionBegin; 189 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 190 mat->factorerrortype = MAT_FACTOR_NOERROR; 191 mat->factorerror_zeropivot_value = 0.0; 192 mat->factorerror_zeropivot_row = 0; 193 PetscFunctionReturn(PETSC_SUCCESS); 194 } 195 196 PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero) 197 { 198 Vec r, l; 199 const PetscScalar *al; 200 PetscInt i, nz, gnz, N, n; 201 202 PetscFunctionBegin; 203 PetscCall(MatCreateVecs(mat, &r, &l)); 204 if (!cols) { /* nonzero rows */ 205 PetscCall(MatGetSize(mat, &N, NULL)); 206 PetscCall(MatGetLocalSize(mat, &n, NULL)); 207 PetscCall(VecSet(l, 0.0)); 208 PetscCall(VecSetRandom(r, NULL)); 209 PetscCall(MatMult(mat, r, l)); 210 PetscCall(VecGetArrayRead(l, &al)); 211 } else { /* nonzero columns */ 212 PetscCall(MatGetSize(mat, NULL, &N)); 213 PetscCall(MatGetLocalSize(mat, NULL, &n)); 214 PetscCall(VecSet(r, 0.0)); 215 PetscCall(VecSetRandom(l, NULL)); 216 PetscCall(MatMultTranspose(mat, l, r)); 217 PetscCall(VecGetArrayRead(r, &al)); 218 } 219 if (tol <= 0.0) { 220 for (i = 0, nz = 0; i < n; i++) 221 if (al[i] != 0.0) nz++; 222 } else { 223 for (i = 0, nz = 0; i < n; i++) 224 if (PetscAbsScalar(al[i]) > tol) nz++; 225 } 226 PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 227 if (gnz != N) { 228 PetscInt *nzr; 229 PetscCall(PetscMalloc1(nz, &nzr)); 230 if (nz) { 231 if (tol < 0) { 232 for (i = 0, nz = 0; i < n; i++) 233 if (al[i] != 0.0) nzr[nz++] = i; 234 } else { 235 for (i = 0, nz = 0; i < n; i++) 236 if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i; 237 } 238 } 239 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero)); 240 } else *nonzero = NULL; 241 if (!cols) { /* nonzero rows */ 242 PetscCall(VecRestoreArrayRead(l, &al)); 243 } else { 244 PetscCall(VecRestoreArrayRead(r, &al)); 245 } 246 PetscCall(VecDestroy(&l)); 247 PetscCall(VecDestroy(&r)); 248 PetscFunctionReturn(PETSC_SUCCESS); 249 } 250 251 /*@ 252 MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix 253 254 Input Parameter: 255 . 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: [](ch_matrices), `Mat`, `MatFindZeroRows()` 266 @*/ 267 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows) 268 { 269 PetscFunctionBegin; 270 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 271 PetscValidType(mat, 1); 272 PetscValidPointer(keptrows, 2); 273 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 274 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 275 if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows); 276 else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows)); 277 PetscFunctionReturn(PETSC_SUCCESS); 278 } 279 280 /*@ 281 MatFindZeroRows - Locate all rows that are completely zero in the matrix 282 283 Input Parameter: 284 . 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: [](ch_matrices), `Mat`, `MatFindNonzeroRows()` 295 @*/ 296 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows) 297 { 298 IS keptrows; 299 PetscInt m, n; 300 301 PetscFunctionBegin; 302 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 303 PetscValidType(mat, 1); 304 PetscValidPointer(zerorows, 2); 305 PetscCall(MatFindNonzeroRows(mat, &keptrows)); 306 /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows. 307 In keeping with this convention, we set zerorows to NULL if there are no zero 308 rows. */ 309 if (keptrows == NULL) { 310 *zerorows = NULL; 311 } else { 312 PetscCall(MatGetOwnershipRange(mat, &m, &n)); 313 PetscCall(ISComplement(keptrows, m, n, zerorows)); 314 PetscCall(ISDestroy(&keptrows)); 315 } 316 PetscFunctionReturn(PETSC_SUCCESS); 317 } 318 319 /*@ 320 MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling 321 322 Not Collective 323 324 Input Parameter: 325 . A - the matrix 326 327 Output Parameter: 328 . a - the diagonal part (which is a SEQUENTIAL matrix) 329 330 Level: advanced 331 332 Notes: 333 See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix. 334 335 Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation. 336 337 .seealso: [](ch_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ` 338 @*/ 339 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a) 340 { 341 PetscFunctionBegin; 342 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 343 PetscValidType(A, 1); 344 PetscValidPointer(a, 2); 345 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 346 if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a); 347 else { 348 PetscMPIInt size; 349 350 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 351 PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name); 352 *a = A; 353 } 354 PetscFunctionReturn(PETSC_SUCCESS); 355 } 356 357 /*@ 358 MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries. 359 360 Collective 361 362 Input Parameter: 363 . mat - the matrix 364 365 Output Parameter: 366 . trace - the sum of the diagonal entries 367 368 Level: advanced 369 370 .seealso: [](ch_matrices), `Mat` 371 @*/ 372 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace) 373 { 374 Vec diag; 375 376 PetscFunctionBegin; 377 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 378 PetscValidScalarPointer(trace, 2); 379 PetscCall(MatCreateVecs(mat, &diag, NULL)); 380 PetscCall(MatGetDiagonal(mat, diag)); 381 PetscCall(VecSum(diag, trace)); 382 PetscCall(VecDestroy(&diag)); 383 PetscFunctionReturn(PETSC_SUCCESS); 384 } 385 386 /*@ 387 MatRealPart - Zeros out the imaginary part of the matrix 388 389 Logically Collective 390 391 Input Parameter: 392 . mat - the matrix 393 394 Level: advanced 395 396 .seealso: [](ch_matrices), `Mat`, `MatImaginaryPart()` 397 @*/ 398 PetscErrorCode MatRealPart(Mat mat) 399 { 400 PetscFunctionBegin; 401 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 402 PetscValidType(mat, 1); 403 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 404 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 405 MatCheckPreallocated(mat, 1); 406 PetscUseTypeMethod(mat, realpart); 407 PetscFunctionReturn(PETSC_SUCCESS); 408 } 409 410 /*@C 411 MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix 412 413 Collective 414 415 Input Parameter: 416 . mat - the matrix 417 418 Output Parameters: 419 + nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each block) 420 - ghosts - the global indices of the ghost points 421 422 Level: advanced 423 424 Note: 425 `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()` 426 427 .seealso: [](ch_matrices), `Mat`, `VecCreateGhost()` 428 @*/ 429 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[]) 430 { 431 PetscFunctionBegin; 432 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 433 PetscValidType(mat, 1); 434 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 435 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 436 if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts); 437 else { 438 if (nghosts) *nghosts = 0; 439 if (ghosts) *ghosts = NULL; 440 } 441 PetscFunctionReturn(PETSC_SUCCESS); 442 } 443 444 /*@ 445 MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part 446 447 Logically Collective 448 449 Input Parameter: 450 . mat - the matrix 451 452 Level: advanced 453 454 .seealso: [](ch_matrices), `Mat`, `MatRealPart()` 455 @*/ 456 PetscErrorCode MatImaginaryPart(Mat mat) 457 { 458 PetscFunctionBegin; 459 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 460 PetscValidType(mat, 1); 461 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 462 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 463 MatCheckPreallocated(mat, 1); 464 PetscUseTypeMethod(mat, imaginarypart); 465 PetscFunctionReturn(PETSC_SUCCESS); 466 } 467 468 /*@ 469 MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices) 470 471 Not Collective 472 473 Input Parameter: 474 . mat - the matrix 475 476 Output Parameters: 477 + missing - is any diagonal missing 478 - dd - first diagonal entry that is missing (optional) on this process 479 480 Level: advanced 481 482 .seealso: [](ch_matrices), `Mat` 483 @*/ 484 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd) 485 { 486 PetscFunctionBegin; 487 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 488 PetscValidType(mat, 1); 489 PetscValidBoolPointer(missing, 2); 490 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name); 491 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 492 PetscUseTypeMethod(mat, missingdiagonal, missing, dd); 493 PetscFunctionReturn(PETSC_SUCCESS); 494 } 495 496 /*@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: [](ch_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 PetscUseTypeMethod(mat, getrow, 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: [](ch_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: [](ch_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 PetscUseTypeMethod(mat, restorerow, 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: [](ch_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: [](ch_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: [](ch_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: [](ch_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: [](ch_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: [](ch_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: [](ch_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: [](ch_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 PetscCheck(A->insertmode == NOT_SET_VALUES, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot reset preallocation after setting some values but not yet calling MatAssemblyBegin()/MatAsssemblyEnd()"); 899 if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS); 900 PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A)); 901 PetscFunctionReturn(PETSC_SUCCESS); 902 } 903 904 /*@ 905 MatSetUp - Sets up the internal matrix data structures for later use. 906 907 Collective 908 909 Input Parameter: 910 . A - the matrix 911 912 Level: intermediate 913 914 Notes: 915 If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of 916 setting values in the matrix. 917 918 If a suitable preallocation routine is used, this function does not need to be called. 919 920 This routine is called internally by other matrix functions when needed so rarely needs to be called by users 921 922 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()` 923 @*/ 924 PetscErrorCode MatSetUp(Mat A) 925 { 926 PetscFunctionBegin; 927 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 928 if (!((PetscObject)A)->type_name) { 929 PetscMPIInt size; 930 931 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 932 PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ)); 933 } 934 if (!A->preallocated) PetscTryTypeMethod(A, setup); 935 PetscCall(PetscLayoutSetUp(A->rmap)); 936 PetscCall(PetscLayoutSetUp(A->cmap)); 937 A->preallocated = PETSC_TRUE; 938 PetscFunctionReturn(PETSC_SUCCESS); 939 } 940 941 #if defined(PETSC_HAVE_SAWS) 942 #include <petscviewersaws.h> 943 #endif 944 945 /* 946 If threadsafety is on extraneous matrices may be printed 947 948 This flag cannot be stored in the matrix because the original matrix in MatView() may assemble a new matrix which is passed into MatViewFromOptions() 949 */ 950 #if !defined(PETSC_HAVE_THREADSAFETY) 951 static PetscInt insidematview = 0; 952 #endif 953 954 /*@C 955 MatViewFromOptions - View properties of the matrix based on options set in the options database 956 957 Collective 958 959 Input Parameters: 960 + A - the matrix 961 . obj - optional additional object that provides the options prefix to use 962 - name - command line option 963 964 Options Database Key: 965 . -mat_view [viewertype]:... - the viewer and its options 966 967 Level: intermediate 968 969 Notes: 970 .vb 971 If no value is provided ascii:stdout is used 972 ascii[:[filename][:[format][:append]]] defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab, 973 for example ascii::ascii_info prints just the information about the object not all details 974 unless :append is given filename opens in write mode, overwriting what was already there 975 binary[:[filename][:[format][:append]]] defaults to the file binaryoutput 976 draw[:drawtype[:filename]] for example, draw:tikz, draw:tikz:figure.tex or draw:x 977 socket[:port] defaults to the standard output port 978 saws[:communicatorname] publishes object to the Scientific Application Webserver (SAWs) 979 .ve 980 981 .seealso: [](ch_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()` 982 @*/ 983 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[]) 984 { 985 PetscFunctionBegin; 986 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 987 #if !defined(PETSC_HAVE_THREADSAFETY) 988 if (insidematview) PetscFunctionReturn(PETSC_SUCCESS); 989 #endif 990 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 991 PetscFunctionReturn(PETSC_SUCCESS); 992 } 993 994 /*@C 995 MatView - display information about a matrix in a variety ways 996 997 Collective 998 999 Input Parameters: 1000 + mat - the matrix 1001 - viewer - visualization context 1002 1003 Options Database Keys: 1004 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 1005 . -mat_view ::ascii_info_detail - Prints more detailed info 1006 . -mat_view - Prints matrix in ASCII format 1007 . -mat_view ::ascii_matlab - Prints matrix in Matlab format 1008 . -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 1009 . -display <name> - Sets display name (default is host) 1010 . -draw_pause <sec> - Sets number of seconds to pause after display 1011 . -mat_view socket - Sends matrix to socket, can be accessed from Matlab (see Users-Manual: ch_matlab for details) 1012 . -viewer_socket_machine <machine> - 1013 . -viewer_socket_port <port> - 1014 . -mat_view binary - save matrix to file in binary format 1015 - -viewer_binary_filename <name> - 1016 1017 Level: beginner 1018 1019 Notes: 1020 The available visualization contexts include 1021 + `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices 1022 . `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD` 1023 . `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm 1024 - `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure 1025 1026 The user can open alternative visualization contexts with 1027 + `PetscViewerASCIIOpen()` - Outputs matrix to a specified file 1028 . `PetscViewerBinaryOpen()` - Outputs matrix in binary to a 1029 specified file; corresponding input uses `MatLoad()` 1030 . `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to 1031 an X window display 1032 - `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer. 1033 Currently only the `MATSEQDENSE` and `MATAIJ` 1034 matrix types support the Socket viewer. 1035 1036 The user can call `PetscViewerPushFormat()` to specify the output 1037 format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`, 1038 `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`). Available formats include 1039 + `PETSC_VIEWER_DEFAULT` - default, prints matrix contents 1040 . `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in Matlab format 1041 . `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros 1042 . `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse 1043 format common among all matrix types 1044 . `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific 1045 format (which is in many cases the same as the default) 1046 . `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix 1047 size and structure (not the matrix entries) 1048 - `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about 1049 the matrix structure 1050 1051 The ASCII viewers are only recommended for small matrices on at most a moderate number of processes, 1052 the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format. 1053 1054 In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer). 1055 1056 See the manual page for `MatLoad()` for the exact format of the binary file when the binary 1057 viewer is used. 1058 1059 See share/petsc/matlab/PetscBinaryRead.m for a Matlab code that can read in the binary file when the binary 1060 viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python. 1061 1062 One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure, 1063 and then use the following mouse functions. 1064 .vb 1065 left mouse: zoom in 1066 middle mouse: zoom out 1067 right mouse: continue with the simulation 1068 .ve 1069 1070 .seealso: [](ch_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`, 1071 `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()` 1072 @*/ 1073 PetscErrorCode MatView(Mat mat, PetscViewer viewer) 1074 { 1075 PetscInt rows, cols, rbs, cbs; 1076 PetscBool isascii, isstring, issaws; 1077 PetscViewerFormat format; 1078 PetscMPIInt size; 1079 1080 PetscFunctionBegin; 1081 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1082 PetscValidType(mat, 1); 1083 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer)); 1084 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1085 PetscCheckSameComm(mat, 1, viewer, 2); 1086 1087 PetscCall(PetscViewerGetFormat(viewer, &format)); 1088 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 1089 if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS); 1090 1091 #if !defined(PETSC_HAVE_THREADSAFETY) 1092 insidematview++; 1093 #endif 1094 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 1095 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 1096 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws)); 1097 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"); 1098 1099 PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0)); 1100 if (isascii) { 1101 if (!mat->preallocated) { 1102 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n")); 1103 #if !defined(PETSC_HAVE_THREADSAFETY) 1104 insidematview--; 1105 #endif 1106 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1107 PetscFunctionReturn(PETSC_SUCCESS); 1108 } 1109 if (!mat->assembled) { 1110 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n")); 1111 #if !defined(PETSC_HAVE_THREADSAFETY) 1112 insidematview--; 1113 #endif 1114 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1115 PetscFunctionReturn(PETSC_SUCCESS); 1116 } 1117 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer)); 1118 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1119 MatNullSpace nullsp, transnullsp; 1120 1121 PetscCall(PetscViewerASCIIPushTab(viewer)); 1122 PetscCall(MatGetSize(mat, &rows, &cols)); 1123 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1124 if (rbs != 1 || cbs != 1) { 1125 if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs)); 1126 else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs)); 1127 } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols)); 1128 if (mat->factortype) { 1129 MatSolverType solver; 1130 PetscCall(MatFactorGetSolverType(mat, &solver)); 1131 PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver)); 1132 } 1133 if (mat->ops->getinfo) { 1134 MatInfo info; 1135 PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info)); 1136 PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated)); 1137 if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs)); 1138 } 1139 PetscCall(MatGetNullSpace(mat, &nullsp)); 1140 PetscCall(MatGetTransposeNullSpace(mat, &transnullsp)); 1141 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached null space\n")); 1142 if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached transposed null space\n")); 1143 PetscCall(MatGetNearNullSpace(mat, &nullsp)); 1144 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached near null space\n")); 1145 PetscCall(PetscViewerASCIIPushTab(viewer)); 1146 PetscCall(MatProductView(mat, viewer)); 1147 PetscCall(PetscViewerASCIIPopTab(viewer)); 1148 } 1149 } else if (issaws) { 1150 #if defined(PETSC_HAVE_SAWS) 1151 PetscMPIInt rank; 1152 1153 PetscCall(PetscObjectName((PetscObject)mat)); 1154 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 1155 if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer)); 1156 #endif 1157 } else if (isstring) { 1158 const char *type; 1159 PetscCall(MatGetType(mat, &type)); 1160 PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type)); 1161 PetscTryTypeMethod(mat, view, viewer); 1162 } 1163 if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) { 1164 PetscCall(PetscViewerASCIIPushTab(viewer)); 1165 PetscUseTypeMethod(mat, viewnative, viewer); 1166 PetscCall(PetscViewerASCIIPopTab(viewer)); 1167 } else if (mat->ops->view) { 1168 PetscCall(PetscViewerASCIIPushTab(viewer)); 1169 PetscUseTypeMethod(mat, view, viewer); 1170 PetscCall(PetscViewerASCIIPopTab(viewer)); 1171 } 1172 if (isascii) { 1173 PetscCall(PetscViewerGetFormat(viewer, &format)); 1174 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer)); 1175 } 1176 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1177 #if !defined(PETSC_HAVE_THREADSAFETY) 1178 insidematview--; 1179 #endif 1180 PetscFunctionReturn(PETSC_SUCCESS); 1181 } 1182 1183 #if defined(PETSC_USE_DEBUG) 1184 #include <../src/sys/totalview/tv_data_display.h> 1185 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat) 1186 { 1187 TV_add_row("Local rows", "int", &mat->rmap->n); 1188 TV_add_row("Local columns", "int", &mat->cmap->n); 1189 TV_add_row("Global rows", "int", &mat->rmap->N); 1190 TV_add_row("Global columns", "int", &mat->cmap->N); 1191 TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name); 1192 return TV_format_OK; 1193 } 1194 #endif 1195 1196 /*@C 1197 MatLoad - Loads a matrix that has been stored in binary/HDF5 format 1198 with `MatView()`. The matrix format is determined from the options database. 1199 Generates a parallel MPI matrix if the communicator has more than one 1200 processor. The default matrix type is `MATAIJ`. 1201 1202 Collective 1203 1204 Input Parameters: 1205 + mat - the newly loaded matrix, this needs to have been created with `MatCreate()` 1206 or some related function before a call to `MatLoad()` 1207 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer 1208 1209 Options Database Keys: 1210 Used with block matrix formats (`MATSEQBAIJ`, ...) to specify 1211 block size 1212 . -matload_block_size <bs> - set block size 1213 1214 Level: beginner 1215 1216 Notes: 1217 If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the 1218 `Mat` before calling this routine if you wish to set it from the options database. 1219 1220 `MatLoad()` automatically loads into the options database any options 1221 given in the file filename.info where filename is the name of the file 1222 that was passed to the `PetscViewerBinaryOpen()`. The options in the info 1223 file will be ignored if you use the -viewer_binary_skip_info option. 1224 1225 If the type or size of mat is not set before a call to `MatLoad()`, PETSc 1226 sets the default matrix type AIJ and sets the local and global sizes. 1227 If type and/or size is already set, then the same are used. 1228 1229 In parallel, each processor can load a subset of rows (or the 1230 entire matrix). This routine is especially useful when a large 1231 matrix is stored on disk and only part of it is desired on each 1232 processor. For example, a parallel solver may access only some of 1233 the rows from each processor. The algorithm used here reads 1234 relatively small blocks of data rather than reading the entire 1235 matrix and then subsetting it. 1236 1237 Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`. 1238 Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`, 1239 or the sequence like 1240 .vb 1241 `PetscViewer` v; 1242 `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v); 1243 `PetscViewerSetType`(v,`PETSCVIEWERBINARY`); 1244 `PetscViewerSetFromOptions`(v); 1245 `PetscViewerFileSetMode`(v,`FILE_MODE_READ`); 1246 `PetscViewerFileSetName`(v,"datafile"); 1247 .ve 1248 The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option 1249 $ -viewer_type {binary, hdf5} 1250 1251 See the example src/ksp/ksp/tutorials/ex27.c with the first approach, 1252 and src/mat/tutorials/ex10.c with the second approach. 1253 1254 In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks 1255 is read onto MPI rank 0 and then shipped to its destination MPI rank, one after another. 1256 Multiple objects, both matrices and vectors, can be stored within the same file. 1257 Their `PetscObject` name is ignored; they are loaded in the order of their storage. 1258 1259 Most users should not need to know the details of the binary storage 1260 format, since `MatLoad()` and `MatView()` completely hide these details. 1261 But for anyone who is interested, the standard binary matrix storage 1262 format is 1263 1264 .vb 1265 PetscInt MAT_FILE_CLASSID 1266 PetscInt number of rows 1267 PetscInt number of columns 1268 PetscInt total number of nonzeros 1269 PetscInt *number nonzeros in each row 1270 PetscInt *column indices of all nonzeros (starting index is zero) 1271 PetscScalar *values of all nonzeros 1272 .ve 1273 If PETSc was not configured with `--with-64-bit-indices` then only `MATMPIAIJ` matrices with more than `PETSC_INT_MAX` non-zeros can be 1274 stored or loaded (each MPI process part of the matrix must have less than `PETSC_INT_MAX` nonzeros). Since the total nonzero count in this 1275 case will not fit in a (32-bit) `PetscInt` the value `PETSC_INT_MAX` is used for the header entry `total number of nonzeros`. 1276 1277 PETSc automatically does the byte swapping for 1278 machines that store the bytes reversed. Thus if you write your own binary 1279 read/write routines you have to swap the bytes; see `PetscBinaryRead()` 1280 and `PetscBinaryWrite()` to see how this may be done. 1281 1282 In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used. 1283 Each processor's chunk is loaded independently by its owning MPI process. 1284 Multiple objects, both matrices and vectors, can be stored within the same file. 1285 They are looked up by their PetscObject name. 1286 1287 As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use 1288 by default the same structure and naming of the AIJ arrays and column count 1289 within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g. 1290 $ save example.mat A b -v7.3 1291 can be directly read by this routine (see Reference 1 for details). 1292 1293 Depending on your MATLAB version, this format might be a default, 1294 otherwise you can set it as default in Preferences. 1295 1296 Unless -nocompression flag is used to save the file in MATLAB, 1297 PETSc must be configured with ZLIB package. 1298 1299 See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c 1300 1301 This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5` 1302 1303 Corresponding `MatView()` is not yet implemented. 1304 1305 The loaded matrix is actually a transpose of the original one in MATLAB, 1306 unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above). 1307 With this format, matrix is automatically transposed by PETSc, 1308 unless the matrix is marked as SPD or symmetric 1309 (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`). 1310 1311 References: 1312 . * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version 1313 1314 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()` 1315 @*/ 1316 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer) 1317 { 1318 PetscBool flg; 1319 1320 PetscFunctionBegin; 1321 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1322 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1323 1324 if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ)); 1325 1326 flg = PETSC_FALSE; 1327 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL)); 1328 if (flg) { 1329 PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE)); 1330 PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE)); 1331 } 1332 flg = PETSC_FALSE; 1333 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL)); 1334 if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE)); 1335 1336 PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0)); 1337 PetscUseTypeMethod(mat, load, viewer); 1338 PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0)); 1339 PetscFunctionReturn(PETSC_SUCCESS); 1340 } 1341 1342 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant) 1343 { 1344 Mat_Redundant *redund = *redundant; 1345 1346 PetscFunctionBegin; 1347 if (redund) { 1348 if (redund->matseq) { /* via MatCreateSubMatrices() */ 1349 PetscCall(ISDestroy(&redund->isrow)); 1350 PetscCall(ISDestroy(&redund->iscol)); 1351 PetscCall(MatDestroySubMatrices(1, &redund->matseq)); 1352 } else { 1353 PetscCall(PetscFree2(redund->send_rank, redund->recv_rank)); 1354 PetscCall(PetscFree(redund->sbuf_j)); 1355 PetscCall(PetscFree(redund->sbuf_a)); 1356 for (PetscInt i = 0; i < redund->nrecvs; i++) { 1357 PetscCall(PetscFree(redund->rbuf_j[i])); 1358 PetscCall(PetscFree(redund->rbuf_a[i])); 1359 } 1360 PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a)); 1361 } 1362 1363 if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm)); 1364 PetscCall(PetscFree(redund)); 1365 } 1366 PetscFunctionReturn(PETSC_SUCCESS); 1367 } 1368 1369 /*@C 1370 MatDestroy - Frees space taken by a matrix. 1371 1372 Collective 1373 1374 Input Parameter: 1375 . A - the matrix 1376 1377 Level: beginner 1378 1379 Developer Note: 1380 Some special arrays of matrices are not destroyed in this routine but instead by the routines called by 1381 `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines. 1382 `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes 1383 if changes are needed here. 1384 1385 .seealso: [](ch_matrices), `Mat`, `MatCreate()` 1386 @*/ 1387 PetscErrorCode MatDestroy(Mat *A) 1388 { 1389 PetscFunctionBegin; 1390 if (!*A) PetscFunctionReturn(PETSC_SUCCESS); 1391 PetscValidHeaderSpecific(*A, MAT_CLASSID, 1); 1392 if (--((PetscObject)(*A))->refct > 0) { 1393 *A = NULL; 1394 PetscFunctionReturn(PETSC_SUCCESS); 1395 } 1396 1397 /* if memory was published with SAWs then destroy it */ 1398 PetscCall(PetscObjectSAWsViewOff((PetscObject)*A)); 1399 PetscTryTypeMethod((*A), destroy); 1400 1401 PetscCall(PetscFree((*A)->factorprefix)); 1402 PetscCall(PetscFree((*A)->defaultvectype)); 1403 PetscCall(PetscFree((*A)->defaultrandtype)); 1404 PetscCall(PetscFree((*A)->bsizes)); 1405 PetscCall(PetscFree((*A)->solvertype)); 1406 for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i])); 1407 if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL; 1408 PetscCall(MatDestroy_Redundant(&(*A)->redundant)); 1409 PetscCall(MatProductClear(*A)); 1410 PetscCall(MatNullSpaceDestroy(&(*A)->nullsp)); 1411 PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp)); 1412 PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp)); 1413 PetscCall(MatDestroy(&(*A)->schur)); 1414 PetscCall(PetscLayoutDestroy(&(*A)->rmap)); 1415 PetscCall(PetscLayoutDestroy(&(*A)->cmap)); 1416 PetscCall(PetscHeaderDestroy(A)); 1417 PetscFunctionReturn(PETSC_SUCCESS); 1418 } 1419 1420 /*@C 1421 MatSetValues - Inserts or adds a block of values into a matrix. 1422 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1423 MUST be called after all calls to `MatSetValues()` have been completed. 1424 1425 Not Collective 1426 1427 Input Parameters: 1428 + mat - the matrix 1429 . v - a logically two-dimensional array of values 1430 . m - the number of rows 1431 . idxm - the global indices of the rows 1432 . n - the number of columns 1433 . idxn - the global indices of the columns 1434 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1435 1436 Level: beginner 1437 1438 Notes: 1439 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1440 1441 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1442 options cannot be mixed without intervening calls to the assembly 1443 routines. 1444 1445 `MatSetValues()` uses 0-based row and column numbers in Fortran 1446 as well as in C. 1447 1448 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1449 simply ignored. This allows easily inserting element stiffness matrices 1450 with homogeneous Dirchlet boundary conditions that you don't want represented 1451 in the matrix. 1452 1453 Efficiency Alert: 1454 The routine `MatSetValuesBlocked()` may offer much better efficiency 1455 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1456 1457 Developer Note: 1458 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1459 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1460 1461 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1462 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1463 @*/ 1464 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1465 { 1466 PetscFunctionBeginHot; 1467 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1468 PetscValidType(mat, 1); 1469 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1470 PetscValidIntPointer(idxm, 3); 1471 PetscValidIntPointer(idxn, 5); 1472 MatCheckPreallocated(mat, 1); 1473 1474 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1475 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1476 1477 if (PetscDefined(USE_DEBUG)) { 1478 PetscInt i, j; 1479 1480 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1481 for (i = 0; i < m; i++) { 1482 for (j = 0; j < n; j++) { 1483 if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j])) 1484 #if defined(PETSC_USE_COMPLEX) 1485 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]); 1486 #else 1487 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]); 1488 #endif 1489 } 1490 } 1491 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); 1492 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); 1493 } 1494 1495 if (mat->assembled) { 1496 mat->was_assembled = PETSC_TRUE; 1497 mat->assembled = PETSC_FALSE; 1498 } 1499 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1500 PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv); 1501 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1502 PetscFunctionReturn(PETSC_SUCCESS); 1503 } 1504 1505 /*@C 1506 MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns 1507 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1508 MUST be called after all calls to `MatSetValues()` have been completed. 1509 1510 Not Collective 1511 1512 Input Parameters: 1513 + mat - the matrix 1514 . v - a logically two-dimensional array of values 1515 . ism - the rows to provide 1516 . isn - the columns to provide 1517 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1518 1519 Level: beginner 1520 1521 Notes: 1522 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1523 1524 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1525 options cannot be mixed without intervening calls to the assembly 1526 routines. 1527 1528 `MatSetValues()` uses 0-based row and column numbers in Fortran 1529 as well as in C. 1530 1531 Negative indices may be passed in `ism` and `isn`, these rows and columns are 1532 simply ignored. This allows easily inserting element stiffness matrices 1533 with homogeneous Dirchlet boundary conditions that you don't want represented 1534 in the matrix. 1535 1536 Efficiency Alert: 1537 The routine `MatSetValuesBlocked()` may offer much better efficiency 1538 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1539 1540 This is currently not optimized for any particular `ISType` 1541 1542 Developer Notes: 1543 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1544 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1545 1546 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1547 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()` 1548 @*/ 1549 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv) 1550 { 1551 PetscInt m, n; 1552 const PetscInt *rows, *cols; 1553 1554 PetscFunctionBeginHot; 1555 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1556 PetscCall(ISGetIndices(ism, &rows)); 1557 PetscCall(ISGetIndices(isn, &cols)); 1558 PetscCall(ISGetLocalSize(ism, &m)); 1559 PetscCall(ISGetLocalSize(isn, &n)); 1560 PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv)); 1561 PetscCall(ISRestoreIndices(ism, &rows)); 1562 PetscCall(ISRestoreIndices(isn, &cols)); 1563 PetscFunctionReturn(PETSC_SUCCESS); 1564 } 1565 1566 /*@ 1567 MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1568 values into a matrix 1569 1570 Not Collective 1571 1572 Input Parameters: 1573 + mat - the matrix 1574 . row - the (block) row to set 1575 - v - a logically two-dimensional array of values 1576 1577 Level: intermediate 1578 1579 Notes: 1580 The values, `v`, are column-oriented (for the block version) and sorted 1581 1582 All the nonzeros in the row must be provided 1583 1584 The matrix must have previously had its column indices set, likely by having been assembled. 1585 1586 The row must belong to this process 1587 1588 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1589 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()` 1590 @*/ 1591 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[]) 1592 { 1593 PetscInt globalrow; 1594 1595 PetscFunctionBegin; 1596 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1597 PetscValidType(mat, 1); 1598 PetscValidScalarPointer(v, 3); 1599 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow)); 1600 PetscCall(MatSetValuesRow(mat, globalrow, v)); 1601 PetscFunctionReturn(PETSC_SUCCESS); 1602 } 1603 1604 /*@ 1605 MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1606 values into a matrix 1607 1608 Not Collective 1609 1610 Input Parameters: 1611 + mat - the matrix 1612 . row - the (block) row to set 1613 - 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 1614 1615 Level: advanced 1616 1617 Notes: 1618 The values, `v`, are column-oriented for the block version. 1619 1620 All the nonzeros in the row must be provided 1621 1622 THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used. 1623 1624 The row must belong to this process 1625 1626 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1627 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()` 1628 @*/ 1629 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[]) 1630 { 1631 PetscFunctionBeginHot; 1632 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1633 PetscValidType(mat, 1); 1634 MatCheckPreallocated(mat, 1); 1635 PetscValidScalarPointer(v, 3); 1636 PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values"); 1637 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1638 mat->insertmode = INSERT_VALUES; 1639 1640 if (mat->assembled) { 1641 mat->was_assembled = PETSC_TRUE; 1642 mat->assembled = PETSC_FALSE; 1643 } 1644 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1645 PetscUseTypeMethod(mat, setvaluesrow, row, v); 1646 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1647 PetscFunctionReturn(PETSC_SUCCESS); 1648 } 1649 1650 /*@ 1651 MatSetValuesStencil - Inserts or adds a block of values into a matrix. 1652 Using structured grid indexing 1653 1654 Not Collective 1655 1656 Input Parameters: 1657 + mat - the matrix 1658 . m - number of rows being entered 1659 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered 1660 . n - number of columns being entered 1661 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered 1662 . v - a logically two-dimensional array of values 1663 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values 1664 1665 Level: beginner 1666 1667 Notes: 1668 By default the values, `v`, are row-oriented. See `MatSetOption()` for other options. 1669 1670 Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1671 options cannot be mixed without intervening calls to the assembly 1672 routines. 1673 1674 The grid coordinates are across the entire grid, not just the local portion 1675 1676 `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran 1677 as well as in C. 1678 1679 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1680 1681 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1682 or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1683 1684 The columns and rows in the stencil passed in MUST be contained within the 1685 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1686 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1687 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1688 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1689 1690 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 1691 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 1692 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 1693 `DM_BOUNDARY_PERIODIC` boundary type. 1694 1695 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 1696 a single value per point) you can skip filling those indices. 1697 1698 Inspired by the structured grid interface to the HYPRE package 1699 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1700 1701 Efficiency Alert: 1702 The routine `MatSetValuesBlockedStencil()` may offer much better efficiency 1703 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1704 1705 Fortran Note: 1706 `idxm` and `idxn` should be declared as 1707 $ MatStencil idxm(4,m),idxn(4,n) 1708 and the values inserted using 1709 .vb 1710 idxm(MatStencil_i,1) = i 1711 idxm(MatStencil_j,1) = j 1712 idxm(MatStencil_k,1) = k 1713 idxm(MatStencil_c,1) = c 1714 etc 1715 .ve 1716 1717 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1718 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil` 1719 @*/ 1720 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1721 { 1722 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1723 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1724 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1725 1726 PetscFunctionBegin; 1727 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1728 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1729 PetscValidType(mat, 1); 1730 PetscValidPointer(idxm, 3); 1731 PetscValidPointer(idxn, 5); 1732 1733 if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 1734 jdxm = buf; 1735 jdxn = buf + m; 1736 } else { 1737 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1738 jdxm = bufm; 1739 jdxn = bufn; 1740 } 1741 for (i = 0; i < m; i++) { 1742 for (j = 0; j < 3 - sdim; j++) dxm++; 1743 tmp = *dxm++ - starts[0]; 1744 for (j = 0; j < dim - 1; j++) { 1745 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1746 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1747 } 1748 if (mat->stencil.noc) dxm++; 1749 jdxm[i] = tmp; 1750 } 1751 for (i = 0; i < n; i++) { 1752 for (j = 0; j < 3 - sdim; j++) dxn++; 1753 tmp = *dxn++ - starts[0]; 1754 for (j = 0; j < dim - 1; j++) { 1755 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1756 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1757 } 1758 if (mat->stencil.noc) dxn++; 1759 jdxn[i] = tmp; 1760 } 1761 PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv)); 1762 PetscCall(PetscFree2(bufm, bufn)); 1763 PetscFunctionReturn(PETSC_SUCCESS); 1764 } 1765 1766 /*@ 1767 MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix. 1768 Using structured grid indexing 1769 1770 Not Collective 1771 1772 Input Parameters: 1773 + mat - the matrix 1774 . m - number of rows being entered 1775 . idxm - grid coordinates for matrix rows being entered 1776 . n - number of columns being entered 1777 . idxn - grid coordinates for matrix columns being entered 1778 . v - a logically two-dimensional array of values 1779 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values 1780 1781 Level: beginner 1782 1783 Notes: 1784 By default the values, `v`, are row-oriented and unsorted. 1785 See `MatSetOption()` for other options. 1786 1787 Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1788 options cannot be mixed without intervening calls to the assembly 1789 routines. 1790 1791 The grid coordinates are across the entire grid, not just the local portion 1792 1793 `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran 1794 as well as in C. 1795 1796 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1797 1798 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1799 or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1800 1801 The columns and rows in the stencil passed in MUST be contained within the 1802 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1803 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1804 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1805 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1806 1807 Negative indices may be passed in idxm and idxn, these rows and columns are 1808 simply ignored. This allows easily inserting element stiffness matrices 1809 with homogeneous Dirchlet boundary conditions that you don't want represented 1810 in the matrix. 1811 1812 Inspired by the structured grid interface to the HYPRE package 1813 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1814 1815 Fortran Note: 1816 `idxm` and `idxn` should be declared as 1817 $ MatStencil idxm(4,m),idxn(4,n) 1818 and the values inserted using 1819 .vb 1820 idxm(MatStencil_i,1) = i 1821 idxm(MatStencil_j,1) = j 1822 idxm(MatStencil_k,1) = k 1823 etc 1824 .ve 1825 1826 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1827 `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`, 1828 `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` 1829 @*/ 1830 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1831 { 1832 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1833 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1834 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1835 1836 PetscFunctionBegin; 1837 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1838 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1839 PetscValidType(mat, 1); 1840 PetscValidPointer(idxm, 3); 1841 PetscValidPointer(idxn, 5); 1842 PetscValidScalarPointer(v, 6); 1843 1844 if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 1845 jdxm = buf; 1846 jdxn = buf + m; 1847 } else { 1848 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1849 jdxm = bufm; 1850 jdxn = bufn; 1851 } 1852 for (i = 0; i < m; i++) { 1853 for (j = 0; j < 3 - sdim; j++) dxm++; 1854 tmp = *dxm++ - starts[0]; 1855 for (j = 0; j < sdim - 1; j++) { 1856 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1857 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1858 } 1859 dxm++; 1860 jdxm[i] = tmp; 1861 } 1862 for (i = 0; i < n; i++) { 1863 for (j = 0; j < 3 - sdim; j++) dxn++; 1864 tmp = *dxn++ - starts[0]; 1865 for (j = 0; j < sdim - 1; j++) { 1866 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1867 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1868 } 1869 dxn++; 1870 jdxn[i] = tmp; 1871 } 1872 PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv)); 1873 PetscCall(PetscFree2(bufm, bufn)); 1874 PetscFunctionReturn(PETSC_SUCCESS); 1875 } 1876 1877 /*@ 1878 MatSetStencil - Sets the grid information for setting values into a matrix via 1879 `MatSetValuesStencil()` 1880 1881 Not Collective 1882 1883 Input Parameters: 1884 + mat - the matrix 1885 . dim - dimension of the grid 1, 2, or 3 1886 . dims - number of grid points in x, y, and z direction, including ghost points on your processor 1887 . starts - starting point of ghost nodes on your processor in x, y, and z direction 1888 - dof - number of degrees of freedom per node 1889 1890 Level: beginner 1891 1892 Notes: 1893 Inspired by the structured grid interface to the HYPRE package 1894 (www.llnl.gov/CASC/hyper) 1895 1896 For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the 1897 user. 1898 1899 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1900 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()` 1901 @*/ 1902 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof) 1903 { 1904 PetscFunctionBegin; 1905 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1906 PetscValidIntPointer(dims, 3); 1907 PetscValidIntPointer(starts, 4); 1908 1909 mat->stencil.dim = dim + (dof > 1); 1910 for (PetscInt i = 0; i < dim; i++) { 1911 mat->stencil.dims[i] = dims[dim - i - 1]; /* copy the values in backwards */ 1912 mat->stencil.starts[i] = starts[dim - i - 1]; 1913 } 1914 mat->stencil.dims[dim] = dof; 1915 mat->stencil.starts[dim] = 0; 1916 mat->stencil.noc = (PetscBool)(dof == 1); 1917 PetscFunctionReturn(PETSC_SUCCESS); 1918 } 1919 1920 /*@C 1921 MatSetValuesBlocked - Inserts or adds a block of values into a matrix. 1922 1923 Not Collective 1924 1925 Input Parameters: 1926 + mat - the matrix 1927 . v - a logically two-dimensional array of values 1928 . m - the number of block rows 1929 . idxm - the global block indices 1930 . n - the number of block columns 1931 . idxn - the global block indices 1932 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values 1933 1934 Level: intermediate 1935 1936 Notes: 1937 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call 1938 MatXXXXSetPreallocation() or `MatSetUp()` before using this routine. 1939 1940 The `m` and `n` count the NUMBER of blocks in the row direction and column direction, 1941 NOT the total number of rows/columns; for example, if the block size is 2 and 1942 you are passing in values for rows 2,3,4,5 then m would be 2 (not 4). 1943 The values in idxm would be 1 2; that is the first index for each block divided by 1944 the block size. 1945 1946 You must call `MatSetBlockSize()` when constructing this matrix (before 1947 preallocating it). 1948 1949 By default the values, `v`, are row-oriented, so the layout of 1950 `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options. 1951 1952 Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES` 1953 options cannot be mixed without intervening calls to the assembly 1954 routines. 1955 1956 `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran 1957 as well as in C. 1958 1959 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1960 simply ignored. This allows easily inserting element stiffness matrices 1961 with homogeneous Dirchlet boundary conditions that you don't want represented 1962 in the matrix. 1963 1964 Each time an entry is set within a sparse matrix via `MatSetValues()`, 1965 internal searching must be done to determine where to place the 1966 data in the matrix storage space. By instead inserting blocks of 1967 entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is 1968 reduced. 1969 1970 Example: 1971 .vb 1972 Suppose m=n=2 and block size(bs) = 2 The array is 1973 1974 1 2 | 3 4 1975 5 6 | 7 8 1976 - - - | - - - 1977 9 10 | 11 12 1978 13 14 | 15 16 1979 1980 v[] should be passed in like 1981 v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] 1982 1983 If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then 1984 v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16] 1985 .ve 1986 1987 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()` 1988 @*/ 1989 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1990 { 1991 PetscFunctionBeginHot; 1992 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1993 PetscValidType(mat, 1); 1994 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1995 PetscValidIntPointer(idxm, 3); 1996 PetscValidIntPointer(idxn, 5); 1997 MatCheckPreallocated(mat, 1); 1998 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1999 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2000 if (PetscDefined(USE_DEBUG)) { 2001 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2002 PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2003 } 2004 if (PetscDefined(USE_DEBUG)) { 2005 PetscInt rbs, cbs, M, N, i; 2006 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 2007 PetscCall(MatGetSize(mat, &M, &N)); 2008 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); 2009 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); 2010 } 2011 if (mat->assembled) { 2012 mat->was_assembled = PETSC_TRUE; 2013 mat->assembled = PETSC_FALSE; 2014 } 2015 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2016 if (mat->ops->setvaluesblocked) { 2017 PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv); 2018 } else { 2019 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn; 2020 PetscInt i, j, bs, cbs; 2021 2022 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 2023 if (m * bs + n * cbs <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2024 iidxm = buf; 2025 iidxn = buf + m * bs; 2026 } else { 2027 PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc)); 2028 iidxm = bufr; 2029 iidxn = bufc; 2030 } 2031 for (i = 0; i < m; i++) { 2032 for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j; 2033 } 2034 if (m != n || bs != cbs || idxm != idxn) { 2035 for (i = 0; i < n; i++) { 2036 for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j; 2037 } 2038 } else iidxn = iidxm; 2039 PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv)); 2040 PetscCall(PetscFree2(bufr, bufc)); 2041 } 2042 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2043 PetscFunctionReturn(PETSC_SUCCESS); 2044 } 2045 2046 /*@C 2047 MatGetValues - Gets a block of local values from a matrix. 2048 2049 Not Collective; can only return values that are owned by the give process 2050 2051 Input Parameters: 2052 + mat - the matrix 2053 . v - a logically two-dimensional array for storing the values 2054 . m - the number of rows 2055 . idxm - the global indices of the rows 2056 . n - the number of columns 2057 - idxn - the global indices of the columns 2058 2059 Level: advanced 2060 2061 Notes: 2062 The user must allocate space (m*n `PetscScalar`s) for the values, `v`. 2063 The values, `v`, are then returned in a row-oriented format, 2064 analogous to that used by default in `MatSetValues()`. 2065 2066 `MatGetValues()` uses 0-based row and column numbers in 2067 Fortran as well as in C. 2068 2069 `MatGetValues()` requires that the matrix has been assembled 2070 with `MatAssemblyBegin()`/`MatAssemblyEnd()`. Thus, calls to 2071 `MatSetValues()` and `MatGetValues()` CANNOT be made in succession 2072 without intermediate matrix assembly. 2073 2074 Negative row or column indices will be ignored and those locations in `v` will be 2075 left unchanged. 2076 2077 For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI process. 2078 That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable 2079 from `MatGetOwnershipRange`(mat,&rstart,&rend). 2080 2081 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()` 2082 @*/ 2083 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) 2084 { 2085 PetscFunctionBegin; 2086 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2087 PetscValidType(mat, 1); 2088 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); 2089 PetscValidIntPointer(idxm, 3); 2090 PetscValidIntPointer(idxn, 5); 2091 PetscValidScalarPointer(v, 6); 2092 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2093 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2094 MatCheckPreallocated(mat, 1); 2095 2096 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2097 PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v); 2098 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2099 PetscFunctionReturn(PETSC_SUCCESS); 2100 } 2101 2102 /*@C 2103 MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices 2104 defined previously by `MatSetLocalToGlobalMapping()` 2105 2106 Not Collective 2107 2108 Input Parameters: 2109 + mat - the matrix 2110 . nrow - number of rows 2111 . irow - the row local indices 2112 . ncol - number of columns 2113 - icol - the column local indices 2114 2115 Output Parameter: 2116 . y - a logically two-dimensional array of values 2117 2118 Level: advanced 2119 2120 Notes: 2121 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine. 2122 2123 This routine can only return values that are owned by the requesting MPI process. That is, for standard matrix formats, rows that, in the global numbering, 2124 are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can 2125 determine if the resulting global row associated with the local row r is owned by the requesting MPI process by applying the `ISLocalToGlobalMapping` set 2126 with `MatSetLocalToGlobalMapping()`. 2127 2128 Developer Note: 2129 This is labelled with C so does not automatically generate Fortran stubs and interfaces 2130 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2131 2132 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2133 `MatSetValuesLocal()`, `MatGetValues()` 2134 @*/ 2135 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[]) 2136 { 2137 PetscFunctionBeginHot; 2138 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2139 PetscValidType(mat, 1); 2140 MatCheckPreallocated(mat, 1); 2141 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */ 2142 PetscValidIntPointer(irow, 3); 2143 PetscValidIntPointer(icol, 5); 2144 if (PetscDefined(USE_DEBUG)) { 2145 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2146 PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2147 } 2148 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2149 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2150 if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y); 2151 else { 2152 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm; 2153 if ((nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2154 irowm = buf; 2155 icolm = buf + nrow; 2156 } else { 2157 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2158 irowm = bufr; 2159 icolm = bufc; 2160 } 2161 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping())."); 2162 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping())."); 2163 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm)); 2164 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm)); 2165 PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y)); 2166 PetscCall(PetscFree2(bufr, bufc)); 2167 } 2168 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2169 PetscFunctionReturn(PETSC_SUCCESS); 2170 } 2171 2172 /*@ 2173 MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and 2174 the same size. Currently, this can only be called once and creates the given matrix. 2175 2176 Not Collective 2177 2178 Input Parameters: 2179 + mat - the matrix 2180 . nb - the number of blocks 2181 . bs - the number of rows (and columns) in each block 2182 . rows - a concatenation of the rows for each block 2183 - v - a concatenation of logically two-dimensional arrays of values 2184 2185 Level: advanced 2186 2187 Note: 2188 `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values 2189 2190 In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix. 2191 2192 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 2193 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()` 2194 @*/ 2195 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[]) 2196 { 2197 PetscFunctionBegin; 2198 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2199 PetscValidType(mat, 1); 2200 PetscValidIntPointer(rows, 4); 2201 PetscValidScalarPointer(v, 5); 2202 PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2203 2204 PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0)); 2205 if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v); 2206 else { 2207 for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES)); 2208 } 2209 PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0)); 2210 PetscFunctionReturn(PETSC_SUCCESS); 2211 } 2212 2213 /*@ 2214 MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by 2215 the routine `MatSetValuesLocal()` to allow users to insert matrix entries 2216 using a local (per-processor) numbering. 2217 2218 Not Collective 2219 2220 Input Parameters: 2221 + x - the matrix 2222 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()` 2223 - cmapping - column mapping 2224 2225 Level: intermediate 2226 2227 Note: 2228 If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix 2229 2230 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()` 2231 @*/ 2232 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping) 2233 { 2234 PetscFunctionBegin; 2235 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 2236 PetscValidType(x, 1); 2237 if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2); 2238 if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3); 2239 if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping); 2240 else { 2241 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping)); 2242 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping)); 2243 } 2244 PetscFunctionReturn(PETSC_SUCCESS); 2245 } 2246 2247 /*@ 2248 MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()` 2249 2250 Not Collective 2251 2252 Input Parameter: 2253 . A - the matrix 2254 2255 Output Parameters: 2256 + rmapping - row mapping 2257 - cmapping - column mapping 2258 2259 Level: advanced 2260 2261 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()` 2262 @*/ 2263 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping) 2264 { 2265 PetscFunctionBegin; 2266 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2267 PetscValidType(A, 1); 2268 if (rmapping) { 2269 PetscValidPointer(rmapping, 2); 2270 *rmapping = A->rmap->mapping; 2271 } 2272 if (cmapping) { 2273 PetscValidPointer(cmapping, 3); 2274 *cmapping = A->cmap->mapping; 2275 } 2276 PetscFunctionReturn(PETSC_SUCCESS); 2277 } 2278 2279 /*@ 2280 MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix 2281 2282 Logically Collective 2283 2284 Input Parameters: 2285 + A - the matrix 2286 . rmap - row layout 2287 - cmap - column layout 2288 2289 Level: advanced 2290 2291 Note: 2292 The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called. 2293 2294 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()` 2295 @*/ 2296 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap) 2297 { 2298 PetscFunctionBegin; 2299 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2300 PetscCall(PetscLayoutReference(rmap, &A->rmap)); 2301 PetscCall(PetscLayoutReference(cmap, &A->cmap)); 2302 PetscFunctionReturn(PETSC_SUCCESS); 2303 } 2304 2305 /*@ 2306 MatGetLayouts - Gets the `PetscLayout` objects for rows and columns 2307 2308 Not Collective 2309 2310 Input Parameter: 2311 . A - the matrix 2312 2313 Output Parameters: 2314 + rmap - row layout 2315 - cmap - column layout 2316 2317 Level: advanced 2318 2319 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()` 2320 @*/ 2321 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap) 2322 { 2323 PetscFunctionBegin; 2324 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2325 PetscValidType(A, 1); 2326 if (rmap) { 2327 PetscValidPointer(rmap, 2); 2328 *rmap = A->rmap; 2329 } 2330 if (cmap) { 2331 PetscValidPointer(cmap, 3); 2332 *cmap = A->cmap; 2333 } 2334 PetscFunctionReturn(PETSC_SUCCESS); 2335 } 2336 2337 /*@C 2338 MatSetValuesLocal - Inserts or adds values into certain locations of a matrix, 2339 using a local numbering of the nodes. 2340 2341 Not Collective 2342 2343 Input Parameters: 2344 + mat - the matrix 2345 . nrow - number of rows 2346 . irow - the row local indices 2347 . ncol - number of columns 2348 . icol - the column local indices 2349 . y - a logically two-dimensional array of values 2350 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2351 2352 Level: intermediate 2353 2354 Notes: 2355 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 2356 `MatSetUp()` before using this routine 2357 2358 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine 2359 2360 Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2361 options cannot be mixed without intervening calls to the assembly 2362 routines. 2363 2364 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2365 MUST be called after all calls to `MatSetValuesLocal()` have been completed. 2366 2367 Developer Note: 2368 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2369 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2370 2371 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2372 `MatGetValuesLocal()` 2373 @*/ 2374 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2375 { 2376 PetscFunctionBeginHot; 2377 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2378 PetscValidType(mat, 1); 2379 MatCheckPreallocated(mat, 1); 2380 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2381 PetscValidIntPointer(irow, 3); 2382 PetscValidIntPointer(icol, 5); 2383 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2384 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2385 if (PetscDefined(USE_DEBUG)) { 2386 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2387 PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2388 } 2389 2390 if (mat->assembled) { 2391 mat->was_assembled = PETSC_TRUE; 2392 mat->assembled = PETSC_FALSE; 2393 } 2394 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2395 if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv); 2396 else { 2397 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2398 const PetscInt *irowm, *icolm; 2399 2400 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2401 bufr = buf; 2402 bufc = buf + nrow; 2403 irowm = bufr; 2404 icolm = bufc; 2405 } else { 2406 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2407 irowm = bufr; 2408 icolm = bufc; 2409 } 2410 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr)); 2411 else irowm = irow; 2412 if (mat->cmap->mapping) { 2413 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2414 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc)); 2415 } else icolm = irowm; 2416 } else icolm = icol; 2417 PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv)); 2418 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2419 } 2420 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2421 PetscFunctionReturn(PETSC_SUCCESS); 2422 } 2423 2424 /*@C 2425 MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix, 2426 using a local ordering of the nodes a block at a time. 2427 2428 Not Collective 2429 2430 Input Parameters: 2431 + x - the matrix 2432 . nrow - number of rows 2433 . irow - the row local indices 2434 . ncol - number of columns 2435 . icol - the column local indices 2436 . y - a logically two-dimensional array of values 2437 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2438 2439 Level: intermediate 2440 2441 Notes: 2442 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 2443 `MatSetUp()` before using this routine 2444 2445 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()` 2446 before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the 2447 2448 Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2449 options cannot be mixed without intervening calls to the assembly 2450 routines. 2451 2452 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2453 MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed. 2454 2455 Developer Note: 2456 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2457 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2458 2459 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, 2460 `MatSetValuesLocal()`, `MatSetValuesBlocked()` 2461 @*/ 2462 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2463 { 2464 PetscFunctionBeginHot; 2465 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2466 PetscValidType(mat, 1); 2467 MatCheckPreallocated(mat, 1); 2468 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2469 PetscValidIntPointer(irow, 3); 2470 PetscValidIntPointer(icol, 5); 2471 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2472 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2473 if (PetscDefined(USE_DEBUG)) { 2474 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2475 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); 2476 } 2477 2478 if (mat->assembled) { 2479 mat->was_assembled = PETSC_TRUE; 2480 mat->assembled = PETSC_FALSE; 2481 } 2482 if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */ 2483 PetscInt irbs, rbs; 2484 PetscCall(MatGetBlockSizes(mat, &rbs, NULL)); 2485 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs)); 2486 PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs); 2487 } 2488 if (PetscUnlikelyDebug(mat->cmap->mapping)) { 2489 PetscInt icbs, cbs; 2490 PetscCall(MatGetBlockSizes(mat, NULL, &cbs)); 2491 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs)); 2492 PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs); 2493 } 2494 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2495 if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv); 2496 else { 2497 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2498 const PetscInt *irowm, *icolm; 2499 2500 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2501 bufr = buf; 2502 bufc = buf + nrow; 2503 irowm = bufr; 2504 icolm = bufc; 2505 } else { 2506 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2507 irowm = bufr; 2508 icolm = bufc; 2509 } 2510 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr)); 2511 else irowm = irow; 2512 if (mat->cmap->mapping) { 2513 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2514 PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc)); 2515 } else icolm = irowm; 2516 } else icolm = icol; 2517 PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv)); 2518 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2519 } 2520 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2521 PetscFunctionReturn(PETSC_SUCCESS); 2522 } 2523 2524 /*@ 2525 MatMultDiagonalBlock - Computes the matrix-vector product, y = Dx. Where D is defined by the inode or block structure of the diagonal 2526 2527 Collective 2528 2529 Input Parameters: 2530 + mat - the matrix 2531 - x - the vector to be multiplied 2532 2533 Output Parameter: 2534 . y - the result 2535 2536 Level: developer 2537 2538 Note: 2539 The vectors `x` and `y` cannot be the same. I.e., one cannot 2540 call `MatMultDiagonalBlock`(A,y,y). 2541 2542 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2543 @*/ 2544 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y) 2545 { 2546 PetscFunctionBegin; 2547 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2548 PetscValidType(mat, 1); 2549 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2550 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2551 2552 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2553 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2554 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2555 MatCheckPreallocated(mat, 1); 2556 2557 PetscUseTypeMethod(mat, multdiagonalblock, x, y); 2558 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2559 PetscFunctionReturn(PETSC_SUCCESS); 2560 } 2561 2562 /*@ 2563 MatMult - Computes the matrix-vector product, y = Ax. 2564 2565 Neighbor-wise Collective 2566 2567 Input Parameters: 2568 + mat - the matrix 2569 - x - the vector to be multiplied 2570 2571 Output Parameter: 2572 . y - the result 2573 2574 Level: beginner 2575 2576 Note: 2577 The vectors `x` and `y` cannot be the same. I.e., one cannot 2578 call `MatMult`(A,y,y). 2579 2580 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2581 @*/ 2582 PetscErrorCode MatMult(Mat mat, Vec x, Vec y) 2583 { 2584 PetscFunctionBegin; 2585 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2586 PetscValidType(mat, 1); 2587 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2588 VecCheckAssembled(x); 2589 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2590 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2591 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2592 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2593 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); 2594 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); 2595 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); 2596 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); 2597 PetscCall(VecSetErrorIfLocked(y, 3)); 2598 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2599 MatCheckPreallocated(mat, 1); 2600 2601 PetscCall(VecLockReadPush(x)); 2602 PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0)); 2603 PetscUseTypeMethod(mat, mult, x, y); 2604 PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0)); 2605 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2606 PetscCall(VecLockReadPop(x)); 2607 PetscFunctionReturn(PETSC_SUCCESS); 2608 } 2609 2610 /*@ 2611 MatMultTranspose - Computes matrix transpose times a vector y = A^T * x. 2612 2613 Neighbor-wise Collective 2614 2615 Input Parameters: 2616 + mat - the matrix 2617 - x - the vector to be multiplied 2618 2619 Output Parameter: 2620 . y - the result 2621 2622 Level: beginner 2623 2624 Notes: 2625 The vectors `x` and `y` cannot be the same. I.e., one cannot 2626 call `MatMultTranspose`(A,y,y). 2627 2628 For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple, 2629 use `MatMultHermitianTranspose()` 2630 2631 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()` 2632 @*/ 2633 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y) 2634 { 2635 PetscErrorCode (*op)(Mat, Vec, Vec) = NULL; 2636 2637 PetscFunctionBegin; 2638 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2639 PetscValidType(mat, 1); 2640 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2641 VecCheckAssembled(x); 2642 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2643 2644 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2645 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2646 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2647 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); 2648 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); 2649 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); 2650 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); 2651 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2652 MatCheckPreallocated(mat, 1); 2653 2654 if (!mat->ops->multtranspose) { 2655 if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult; 2656 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); 2657 } else op = mat->ops->multtranspose; 2658 PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0)); 2659 PetscCall(VecLockReadPush(x)); 2660 PetscCall((*op)(mat, x, y)); 2661 PetscCall(VecLockReadPop(x)); 2662 PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0)); 2663 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2664 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2665 PetscFunctionReturn(PETSC_SUCCESS); 2666 } 2667 2668 /*@ 2669 MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector. 2670 2671 Neighbor-wise Collective 2672 2673 Input Parameters: 2674 + mat - the matrix 2675 - x - the vector to be multilplied 2676 2677 Output Parameter: 2678 . y - the result 2679 2680 Level: beginner 2681 2682 Notes: 2683 The vectors `x` and `y` cannot be the same. I.e., one cannot 2684 call `MatMultHermitianTranspose`(A,y,y). 2685 2686 Also called the conjugate transpose, complex conjugate transpose, or adjoint. 2687 2688 For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical. 2689 2690 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()` 2691 @*/ 2692 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y) 2693 { 2694 PetscFunctionBegin; 2695 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2696 PetscValidType(mat, 1); 2697 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2698 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2699 2700 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2701 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2702 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2703 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); 2704 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); 2705 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); 2706 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); 2707 MatCheckPreallocated(mat, 1); 2708 2709 PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0)); 2710 #if defined(PETSC_USE_COMPLEX) 2711 if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) { 2712 PetscCall(VecLockReadPush(x)); 2713 if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y); 2714 else PetscUseTypeMethod(mat, mult, x, y); 2715 PetscCall(VecLockReadPop(x)); 2716 } else { 2717 Vec w; 2718 PetscCall(VecDuplicate(x, &w)); 2719 PetscCall(VecCopy(x, w)); 2720 PetscCall(VecConjugate(w)); 2721 PetscCall(MatMultTranspose(mat, w, y)); 2722 PetscCall(VecDestroy(&w)); 2723 PetscCall(VecConjugate(y)); 2724 } 2725 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2726 #else 2727 PetscCall(MatMultTranspose(mat, x, y)); 2728 #endif 2729 PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0)); 2730 PetscFunctionReturn(PETSC_SUCCESS); 2731 } 2732 2733 /*@ 2734 MatMultAdd - Computes v3 = v2 + A * v1. 2735 2736 Neighbor-wise Collective 2737 2738 Input Parameters: 2739 + mat - the matrix 2740 . v1 - the vector to be multiplied by `mat` 2741 - v2 - the vector to be added to the result 2742 2743 Output Parameter: 2744 . v3 - the result 2745 2746 Level: beginner 2747 2748 Note: 2749 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2750 call `MatMultAdd`(A,v1,v2,v1). 2751 2752 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()` 2753 @*/ 2754 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2755 { 2756 PetscFunctionBegin; 2757 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2758 PetscValidType(mat, 1); 2759 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2760 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2761 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2762 2763 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2764 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2765 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); 2766 /* 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); 2767 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); */ 2768 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); 2769 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); 2770 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2771 MatCheckPreallocated(mat, 1); 2772 2773 PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3)); 2774 PetscCall(VecLockReadPush(v1)); 2775 PetscUseTypeMethod(mat, multadd, v1, v2, v3); 2776 PetscCall(VecLockReadPop(v1)); 2777 PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3)); 2778 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2779 PetscFunctionReturn(PETSC_SUCCESS); 2780 } 2781 2782 /*@ 2783 MatMultTransposeAdd - Computes v3 = v2 + A' * v1. 2784 2785 Neighbor-wise Collective 2786 2787 Input Parameters: 2788 + mat - the matrix 2789 . v1 - the vector to be multiplied by the transpose of the matrix 2790 - v2 - the vector to be added to the result 2791 2792 Output Parameter: 2793 . v3 - the result 2794 2795 Level: beginner 2796 2797 Note: 2798 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2799 call `MatMultTransposeAdd`(A,v1,v2,v1). 2800 2801 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2802 @*/ 2803 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2804 { 2805 PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd; 2806 2807 PetscFunctionBegin; 2808 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2809 PetscValidType(mat, 1); 2810 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2811 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2812 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2813 2814 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2815 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2816 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); 2817 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); 2818 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); 2819 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2820 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2821 MatCheckPreallocated(mat, 1); 2822 2823 PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2824 PetscCall(VecLockReadPush(v1)); 2825 PetscCall((*op)(mat, v1, v2, v3)); 2826 PetscCall(VecLockReadPop(v1)); 2827 PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2828 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2829 PetscFunctionReturn(PETSC_SUCCESS); 2830 } 2831 2832 /*@ 2833 MatMultHermitianTransposeAdd - Computes v3 = v2 + A^H * v1. 2834 2835 Neighbor-wise Collective 2836 2837 Input Parameters: 2838 + mat - the matrix 2839 . v1 - the vector to be multiplied by the Hermitian transpose 2840 - v2 - the vector to be added to the result 2841 2842 Output Parameter: 2843 . v3 - the result 2844 2845 Level: beginner 2846 2847 Note: 2848 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2849 call `MatMultHermitianTransposeAdd`(A,v1,v2,v1). 2850 2851 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2852 @*/ 2853 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2854 { 2855 PetscFunctionBegin; 2856 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2857 PetscValidType(mat, 1); 2858 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2859 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2860 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2861 2862 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2863 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2864 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2865 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); 2866 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); 2867 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); 2868 MatCheckPreallocated(mat, 1); 2869 2870 PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2871 PetscCall(VecLockReadPush(v1)); 2872 if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3); 2873 else { 2874 Vec w, z; 2875 PetscCall(VecDuplicate(v1, &w)); 2876 PetscCall(VecCopy(v1, w)); 2877 PetscCall(VecConjugate(w)); 2878 PetscCall(VecDuplicate(v3, &z)); 2879 PetscCall(MatMultTranspose(mat, w, z)); 2880 PetscCall(VecDestroy(&w)); 2881 PetscCall(VecConjugate(z)); 2882 if (v2 != v3) { 2883 PetscCall(VecWAXPY(v3, 1.0, v2, z)); 2884 } else { 2885 PetscCall(VecAXPY(v3, 1.0, z)); 2886 } 2887 PetscCall(VecDestroy(&z)); 2888 } 2889 PetscCall(VecLockReadPop(v1)); 2890 PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2891 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2892 PetscFunctionReturn(PETSC_SUCCESS); 2893 } 2894 2895 /*@C 2896 MatGetFactorType - gets the type of factorization it is 2897 2898 Not Collective 2899 2900 Input Parameter: 2901 . mat - the matrix 2902 2903 Output Parameter: 2904 . 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` 2905 2906 Level: intermediate 2907 2908 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2909 `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2910 @*/ 2911 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t) 2912 { 2913 PetscFunctionBegin; 2914 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2915 PetscValidType(mat, 1); 2916 PetscValidPointer(t, 2); 2917 *t = mat->factortype; 2918 PetscFunctionReturn(PETSC_SUCCESS); 2919 } 2920 2921 /*@C 2922 MatSetFactorType - sets the type of factorization it is 2923 2924 Logically Collective 2925 2926 Input Parameters: 2927 + mat - the matrix 2928 - 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` 2929 2930 Level: intermediate 2931 2932 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2933 `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2934 @*/ 2935 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t) 2936 { 2937 PetscFunctionBegin; 2938 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2939 PetscValidType(mat, 1); 2940 mat->factortype = t; 2941 PetscFunctionReturn(PETSC_SUCCESS); 2942 } 2943 2944 /*@C 2945 MatGetInfo - Returns information about matrix storage (number of 2946 nonzeros, memory, etc.). 2947 2948 Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag 2949 2950 Input Parameters: 2951 + mat - the matrix 2952 - 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) 2953 2954 Output Parameter: 2955 . info - matrix information context 2956 2957 Options Database Key: 2958 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT` 2959 2960 Notes: 2961 The `MatInfo` context contains a variety of matrix data, including 2962 number of nonzeros allocated and used, number of mallocs during 2963 matrix assembly, etc. Additional information for factored matrices 2964 is provided (such as the fill ratio, number of mallocs during 2965 factorization, etc.). 2966 2967 Example: 2968 See the file ${PETSC_DIR}/include/petscmat.h for a complete list of 2969 data within the MatInfo context. For example, 2970 .vb 2971 MatInfo info; 2972 Mat A; 2973 double mal, nz_a, nz_u; 2974 2975 MatGetInfo(A, MAT_LOCAL, &info); 2976 mal = info.mallocs; 2977 nz_a = info.nz_allocated; 2978 .ve 2979 2980 Fortran users should declare info as a double precision 2981 array of dimension `MAT_INFO_SIZE`, and then extract the parameters 2982 of interest. See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h 2983 a complete list of parameter names. 2984 .vb 2985 double precision info(MAT_INFO_SIZE) 2986 double precision mal, nz_a 2987 Mat A 2988 integer ierr 2989 2990 call MatGetInfo(A, MAT_LOCAL, info, ierr) 2991 mal = info(MAT_INFO_MALLOCS) 2992 nz_a = info(MAT_INFO_NZ_ALLOCATED) 2993 .ve 2994 2995 Level: intermediate 2996 2997 Developer Note: 2998 The Fortran interface is not autogenerated as the 2999 interface definition cannot be generated correctly [due to `MatInfo` argument] 3000 3001 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()` 3002 @*/ 3003 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info) 3004 { 3005 PetscFunctionBegin; 3006 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3007 PetscValidType(mat, 1); 3008 PetscValidPointer(info, 3); 3009 MatCheckPreallocated(mat, 1); 3010 PetscUseTypeMethod(mat, getinfo, flag, info); 3011 PetscFunctionReturn(PETSC_SUCCESS); 3012 } 3013 3014 /* 3015 This is used by external packages where it is not easy to get the info from the actual 3016 matrix factorization. 3017 */ 3018 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info) 3019 { 3020 PetscFunctionBegin; 3021 PetscCall(PetscMemzero(info, sizeof(MatInfo))); 3022 PetscFunctionReturn(PETSC_SUCCESS); 3023 } 3024 3025 /*@C 3026 MatLUFactor - Performs in-place LU factorization of matrix. 3027 3028 Collective 3029 3030 Input Parameters: 3031 + mat - the matrix 3032 . row - row permutation 3033 . col - column permutation 3034 - info - options for factorization, includes 3035 .vb 3036 fill - expected fill as ratio of original fill. 3037 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3038 Run with the option -info to determine an optimal value to use 3039 .ve 3040 Level: developer 3041 3042 Notes: 3043 Most users should employ the `KSP` interface for linear solvers 3044 instead of working directly with matrix algebra routines such as this. 3045 See, e.g., `KSPCreate()`. 3046 3047 This changes the state of the matrix to a factored matrix; it cannot be used 3048 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3049 3050 This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()` 3051 when not using `KSP`. 3052 3053 Developer Note: 3054 The Fortran interface is not autogenerated as the 3055 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3056 3057 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, 3058 `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3059 @*/ 3060 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3061 { 3062 MatFactorInfo tinfo; 3063 3064 PetscFunctionBegin; 3065 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3066 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3067 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3068 if (info) PetscValidPointer(info, 4); 3069 PetscValidType(mat, 1); 3070 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3071 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3072 MatCheckPreallocated(mat, 1); 3073 if (!info) { 3074 PetscCall(MatFactorInfoInitialize(&tinfo)); 3075 info = &tinfo; 3076 } 3077 3078 PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0)); 3079 PetscUseTypeMethod(mat, lufactor, row, col, info); 3080 PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0)); 3081 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3082 PetscFunctionReturn(PETSC_SUCCESS); 3083 } 3084 3085 /*@C 3086 MatILUFactor - Performs in-place ILU factorization of matrix. 3087 3088 Collective 3089 3090 Input Parameters: 3091 + mat - the matrix 3092 . row - row permutation 3093 . col - column permutation 3094 - info - structure containing 3095 .vb 3096 levels - number of levels of fill. 3097 expected fill - as ratio of original fill. 3098 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 3099 missing diagonal entries) 3100 .ve 3101 3102 Level: developer 3103 3104 Notes: 3105 Most users should employ the `KSP` interface for linear solvers 3106 instead of working directly with matrix algebra routines such as this. 3107 See, e.g., `KSPCreate()`. 3108 3109 Probably really in-place only when level of fill is zero, otherwise allocates 3110 new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()` 3111 when not using `KSP`. 3112 3113 Developer Note: 3114 The Fortran interface is not autogenerated as the 3115 interface definition cannot be generated correctly [due to MatFactorInfo] 3116 3117 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 3118 @*/ 3119 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3120 { 3121 PetscFunctionBegin; 3122 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3123 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3124 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3125 PetscValidPointer(info, 4); 3126 PetscValidType(mat, 1); 3127 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 3128 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3129 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3130 MatCheckPreallocated(mat, 1); 3131 3132 PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0)); 3133 PetscUseTypeMethod(mat, ilufactor, row, col, info); 3134 PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0)); 3135 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3136 PetscFunctionReturn(PETSC_SUCCESS); 3137 } 3138 3139 /*@C 3140 MatLUFactorSymbolic - Performs symbolic LU factorization of matrix. 3141 Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`. 3142 3143 Collective 3144 3145 Input Parameters: 3146 + fact - the factor matrix obtained with `MatGetFactor()` 3147 . mat - the matrix 3148 . row - the row permutation 3149 . col - the column permutation 3150 - info - options for factorization, includes 3151 .vb 3152 fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use 3153 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3154 .ve 3155 3156 Level: developer 3157 3158 Notes: 3159 See [Matrix Factorization](sec_matfactor) for additional information about factorizations 3160 3161 Most users should employ the simplified `KSP` interface for linear solvers 3162 instead of working directly with matrix algebra routines such as this. 3163 See, e.g., `KSPCreate()`. 3164 3165 Developer Note: 3166 The Fortran interface is not autogenerated as the 3167 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3168 3169 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3170 @*/ 3171 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 3172 { 3173 MatFactorInfo tinfo; 3174 3175 PetscFunctionBegin; 3176 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3177 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3178 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 3179 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 3180 if (info) PetscValidPointer(info, 5); 3181 PetscValidType(fact, 1); 3182 PetscValidType(mat, 2); 3183 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3184 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3185 MatCheckPreallocated(mat, 2); 3186 if (!info) { 3187 PetscCall(MatFactorInfoInitialize(&tinfo)); 3188 info = &tinfo; 3189 } 3190 3191 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0)); 3192 PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info); 3193 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0)); 3194 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3195 PetscFunctionReturn(PETSC_SUCCESS); 3196 } 3197 3198 /*@C 3199 MatLUFactorNumeric - Performs numeric LU factorization of a matrix. 3200 Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`. 3201 3202 Collective 3203 3204 Input Parameters: 3205 + fact - the factor matrix obtained with `MatGetFactor()` 3206 . mat - the matrix 3207 - info - options for factorization 3208 3209 Level: developer 3210 3211 Notes: 3212 See `MatLUFactor()` for in-place factorization. See 3213 `MatCholeskyFactorNumeric()` for the symmetric, positive definite case. 3214 3215 Most users should employ the `KSP` interface for linear solvers 3216 instead of working directly with matrix algebra routines such as this. 3217 See, e.g., `KSPCreate()`. 3218 3219 Developer Note: 3220 The Fortran interface is not autogenerated as the 3221 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3222 3223 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()` 3224 @*/ 3225 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3226 { 3227 MatFactorInfo tinfo; 3228 3229 PetscFunctionBegin; 3230 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3231 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3232 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3233 PetscValidType(fact, 1); 3234 PetscValidType(mat, 2); 3235 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3236 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, 3237 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3238 3239 MatCheckPreallocated(mat, 2); 3240 if (!info) { 3241 PetscCall(MatFactorInfoInitialize(&tinfo)); 3242 info = &tinfo; 3243 } 3244 3245 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3246 else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0)); 3247 PetscUseTypeMethod(fact, lufactornumeric, mat, info); 3248 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3249 else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0)); 3250 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3251 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3252 PetscFunctionReturn(PETSC_SUCCESS); 3253 } 3254 3255 /*@C 3256 MatCholeskyFactor - Performs in-place Cholesky factorization of a 3257 symmetric matrix. 3258 3259 Collective 3260 3261 Input Parameters: 3262 + mat - the matrix 3263 . perm - row and column permutations 3264 - f - expected fill as ratio of original fill 3265 3266 Level: developer 3267 3268 Notes: 3269 See `MatLUFactor()` for the nonsymmetric case. See also `MatGetFactor()`, 3270 `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`. 3271 3272 Most users should employ the `KSP` interface for linear solvers 3273 instead of working directly with matrix algebra routines such as this. 3274 See, e.g., `KSPCreate()`. 3275 3276 Developer Note: 3277 The Fortran interface is not autogenerated as the 3278 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3279 3280 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()` 3281 `MatGetOrdering()` 3282 @*/ 3283 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info) 3284 { 3285 MatFactorInfo tinfo; 3286 3287 PetscFunctionBegin; 3288 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3289 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2); 3290 if (info) PetscValidPointer(info, 3); 3291 PetscValidType(mat, 1); 3292 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3293 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3294 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3295 MatCheckPreallocated(mat, 1); 3296 if (!info) { 3297 PetscCall(MatFactorInfoInitialize(&tinfo)); 3298 info = &tinfo; 3299 } 3300 3301 PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0)); 3302 PetscUseTypeMethod(mat, choleskyfactor, perm, info); 3303 PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0)); 3304 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3305 PetscFunctionReturn(PETSC_SUCCESS); 3306 } 3307 3308 /*@C 3309 MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization 3310 of a symmetric matrix. 3311 3312 Collective 3313 3314 Input Parameters: 3315 + fact - the factor matrix obtained with `MatGetFactor()` 3316 . mat - the matrix 3317 . perm - row and column permutations 3318 - info - options for factorization, includes 3319 .vb 3320 fill - expected fill as ratio of original fill. 3321 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3322 Run with the option -info to determine an optimal value to use 3323 .ve 3324 3325 Level: developer 3326 3327 Notes: 3328 See `MatLUFactorSymbolic()` for the nonsymmetric case. See also 3329 `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`. 3330 3331 Most users should employ the `KSP` interface for linear solvers 3332 instead of working directly with matrix algebra routines such as this. 3333 See, e.g., `KSPCreate()`. 3334 3335 Developer Note: 3336 The Fortran interface is not autogenerated as the 3337 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3338 3339 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()` 3340 `MatGetOrdering()` 3341 @*/ 3342 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 3343 { 3344 MatFactorInfo tinfo; 3345 3346 PetscFunctionBegin; 3347 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3348 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3349 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 3350 if (info) PetscValidPointer(info, 4); 3351 PetscValidType(fact, 1); 3352 PetscValidType(mat, 2); 3353 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3354 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3355 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3356 MatCheckPreallocated(mat, 2); 3357 if (!info) { 3358 PetscCall(MatFactorInfoInitialize(&tinfo)); 3359 info = &tinfo; 3360 } 3361 3362 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3363 PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info); 3364 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3365 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3366 PetscFunctionReturn(PETSC_SUCCESS); 3367 } 3368 3369 /*@C 3370 MatCholeskyFactorNumeric - Performs numeric Cholesky factorization 3371 of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and 3372 `MatCholeskyFactorSymbolic()`. 3373 3374 Collective 3375 3376 Input Parameters: 3377 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored 3378 . mat - the initial matrix that is to be factored 3379 - info - options for factorization 3380 3381 Level: developer 3382 3383 Note: 3384 Most users should employ the `KSP` interface for linear solvers 3385 instead of working directly with matrix algebra routines such as this. 3386 See, e.g., `KSPCreate()`. 3387 3388 Developer Note: 3389 The Fortran interface is not autogenerated as the 3390 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3391 3392 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()` 3393 @*/ 3394 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3395 { 3396 MatFactorInfo tinfo; 3397 3398 PetscFunctionBegin; 3399 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3400 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3401 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3402 PetscValidType(fact, 1); 3403 PetscValidType(mat, 2); 3404 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3405 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, 3406 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3407 MatCheckPreallocated(mat, 2); 3408 if (!info) { 3409 PetscCall(MatFactorInfoInitialize(&tinfo)); 3410 info = &tinfo; 3411 } 3412 3413 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3414 else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0)); 3415 PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info); 3416 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3417 else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0)); 3418 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3419 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3420 PetscFunctionReturn(PETSC_SUCCESS); 3421 } 3422 3423 /*@ 3424 MatQRFactor - Performs in-place QR factorization of matrix. 3425 3426 Collective 3427 3428 Input Parameters: 3429 + mat - the matrix 3430 . col - column permutation 3431 - info - options for factorization, includes 3432 .vb 3433 fill - expected fill as ratio of original fill. 3434 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3435 Run with the option -info to determine an optimal value to use 3436 .ve 3437 3438 Level: developer 3439 3440 Notes: 3441 Most users should employ the `KSP` interface for linear solvers 3442 instead of working directly with matrix algebra routines such as this. 3443 See, e.g., `KSPCreate()`. 3444 3445 This changes the state of the matrix to a factored matrix; it cannot be used 3446 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3447 3448 Developer Note: 3449 The Fortran interface is not autogenerated as the 3450 interface definition cannot be generated correctly [due to MatFactorInfo] 3451 3452 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`, 3453 `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3454 @*/ 3455 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info) 3456 { 3457 PetscFunctionBegin; 3458 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3459 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2); 3460 if (info) PetscValidPointer(info, 3); 3461 PetscValidType(mat, 1); 3462 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3463 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3464 MatCheckPreallocated(mat, 1); 3465 PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0)); 3466 PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info)); 3467 PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0)); 3468 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3469 PetscFunctionReturn(PETSC_SUCCESS); 3470 } 3471 3472 /*@ 3473 MatQRFactorSymbolic - Performs symbolic QR factorization of matrix. 3474 Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`. 3475 3476 Collective 3477 3478 Input Parameters: 3479 + fact - the factor matrix obtained with `MatGetFactor()` 3480 . mat - the matrix 3481 . col - column permutation 3482 - info - options for factorization, includes 3483 .vb 3484 fill - expected fill as ratio of original fill. 3485 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3486 Run with the option -info to determine an optimal value to use 3487 .ve 3488 3489 Level: developer 3490 3491 Note: 3492 Most users should employ the `KSP` interface for linear solvers 3493 instead of working directly with matrix algebra routines such as this. 3494 See, e.g., `KSPCreate()`. 3495 3496 Developer Note: 3497 The Fortran interface is not autogenerated as the 3498 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3499 3500 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3501 @*/ 3502 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info) 3503 { 3504 MatFactorInfo tinfo; 3505 3506 PetscFunctionBegin; 3507 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3508 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3509 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3510 if (info) PetscValidPointer(info, 4); 3511 PetscValidType(fact, 1); 3512 PetscValidType(mat, 2); 3513 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3514 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3515 MatCheckPreallocated(mat, 2); 3516 if (!info) { 3517 PetscCall(MatFactorInfoInitialize(&tinfo)); 3518 info = &tinfo; 3519 } 3520 3521 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3522 PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info)); 3523 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3524 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3525 PetscFunctionReturn(PETSC_SUCCESS); 3526 } 3527 3528 /*@ 3529 MatQRFactorNumeric - Performs numeric QR factorization of a matrix. 3530 Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`. 3531 3532 Collective 3533 3534 Input Parameters: 3535 + fact - the factor matrix obtained with `MatGetFactor()` 3536 . mat - the matrix 3537 - info - options for factorization 3538 3539 Level: developer 3540 3541 Notes: 3542 See `MatQRFactor()` for in-place factorization. 3543 3544 Most users should employ the `KSP` interface for linear solvers 3545 instead of working directly with matrix algebra routines such as this. 3546 See, e.g., `KSPCreate()`. 3547 3548 Developer Note: 3549 The Fortran interface is not autogenerated as the 3550 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3551 3552 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()` 3553 @*/ 3554 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3555 { 3556 MatFactorInfo tinfo; 3557 3558 PetscFunctionBegin; 3559 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3560 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3561 PetscValidType(fact, 1); 3562 PetscValidType(mat, 2); 3563 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3564 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, 3565 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3566 3567 MatCheckPreallocated(mat, 2); 3568 if (!info) { 3569 PetscCall(MatFactorInfoInitialize(&tinfo)); 3570 info = &tinfo; 3571 } 3572 3573 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3574 else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0)); 3575 PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info)); 3576 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3577 else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0)); 3578 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3579 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3580 PetscFunctionReturn(PETSC_SUCCESS); 3581 } 3582 3583 /*@ 3584 MatSolve - Solves A x = b, given a factored matrix. 3585 3586 Neighbor-wise Collective 3587 3588 Input Parameters: 3589 + mat - the factored matrix 3590 - b - the right-hand-side vector 3591 3592 Output Parameter: 3593 . x - the result vector 3594 3595 Level: developer 3596 3597 Notes: 3598 The vectors `b` and `x` cannot be the same. I.e., one cannot 3599 call `MatSolve`(A,x,x). 3600 3601 Most users should employ the `KSP` interface for linear solvers 3602 instead of working directly with matrix algebra routines such as this. 3603 See, e.g., `KSPCreate()`. 3604 3605 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3606 @*/ 3607 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x) 3608 { 3609 PetscFunctionBegin; 3610 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3611 PetscValidType(mat, 1); 3612 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3613 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3614 PetscCheckSameComm(mat, 1, b, 2); 3615 PetscCheckSameComm(mat, 1, x, 3); 3616 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3617 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); 3618 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); 3619 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); 3620 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3621 MatCheckPreallocated(mat, 1); 3622 3623 PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0)); 3624 if (mat->factorerrortype) { 3625 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3626 PetscCall(VecSetInf(x)); 3627 } else PetscUseTypeMethod(mat, solve, b, x); 3628 PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0)); 3629 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3630 PetscFunctionReturn(PETSC_SUCCESS); 3631 } 3632 3633 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans) 3634 { 3635 Vec b, x; 3636 PetscInt N, i; 3637 PetscErrorCode (*f)(Mat, Vec, Vec); 3638 PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE; 3639 3640 PetscFunctionBegin; 3641 if (A->factorerrortype) { 3642 PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype)); 3643 PetscCall(MatSetInf(X)); 3644 PetscFunctionReturn(PETSC_SUCCESS); 3645 } 3646 f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose; 3647 PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 3648 PetscCall(MatBoundToCPU(A, &Abound)); 3649 if (!Abound) { 3650 PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3651 PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3652 } 3653 #if PetscDefined(HAVE_CUDA) 3654 if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B)); 3655 if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X)); 3656 #elif PetscDefined(HAVE_HIP) 3657 if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B)); 3658 if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X)); 3659 #endif 3660 PetscCall(MatGetSize(B, NULL, &N)); 3661 for (i = 0; i < N; i++) { 3662 PetscCall(MatDenseGetColumnVecRead(B, i, &b)); 3663 PetscCall(MatDenseGetColumnVecWrite(X, i, &x)); 3664 PetscCall((*f)(A, b, x)); 3665 PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x)); 3666 PetscCall(MatDenseRestoreColumnVecRead(B, i, &b)); 3667 } 3668 if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B)); 3669 if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X)); 3670 PetscFunctionReturn(PETSC_SUCCESS); 3671 } 3672 3673 /*@ 3674 MatMatSolve - Solves A X = B, given a factored matrix. 3675 3676 Neighbor-wise Collective 3677 3678 Input Parameters: 3679 + A - the factored matrix 3680 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS) 3681 3682 Output Parameter: 3683 . X - the result matrix (dense matrix) 3684 3685 Level: developer 3686 3687 Note: 3688 If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`; 3689 otherwise, `B` and `X` cannot be the same. 3690 3691 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3692 @*/ 3693 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X) 3694 { 3695 PetscFunctionBegin; 3696 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3697 PetscValidType(A, 1); 3698 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3699 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3700 PetscCheckSameComm(A, 1, B, 2); 3701 PetscCheckSameComm(A, 1, X, 3); 3702 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); 3703 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); 3704 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"); 3705 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3706 MatCheckPreallocated(A, 1); 3707 3708 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3709 if (!A->ops->matsolve) { 3710 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name)); 3711 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE)); 3712 } else PetscUseTypeMethod(A, matsolve, B, X); 3713 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3714 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3715 PetscFunctionReturn(PETSC_SUCCESS); 3716 } 3717 3718 /*@ 3719 MatMatSolveTranspose - Solves A^T X = B, given a factored matrix. 3720 3721 Neighbor-wise Collective 3722 3723 Input Parameters: 3724 + A - the factored matrix 3725 - B - the right-hand-side matrix (`MATDENSE` matrix) 3726 3727 Output Parameter: 3728 . X - the result matrix (dense matrix) 3729 3730 Level: developer 3731 3732 Note: 3733 The matrices `B` and `X` cannot be the same. I.e., one cannot 3734 call `MatMatSolveTranspose`(A,X,X). 3735 3736 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()` 3737 @*/ 3738 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X) 3739 { 3740 PetscFunctionBegin; 3741 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3742 PetscValidType(A, 1); 3743 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3744 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3745 PetscCheckSameComm(A, 1, B, 2); 3746 PetscCheckSameComm(A, 1, X, 3); 3747 PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3748 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); 3749 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); 3750 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); 3751 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"); 3752 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3753 MatCheckPreallocated(A, 1); 3754 3755 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3756 if (!A->ops->matsolvetranspose) { 3757 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name)); 3758 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE)); 3759 } else PetscUseTypeMethod(A, matsolvetranspose, B, X); 3760 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3761 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3762 PetscFunctionReturn(PETSC_SUCCESS); 3763 } 3764 3765 /*@ 3766 MatMatTransposeSolve - Solves A X = B^T, given a factored matrix. 3767 3768 Neighbor-wise Collective 3769 3770 Input Parameters: 3771 + A - the factored matrix 3772 - Bt - the transpose of right-hand-side matrix as a `MATDENSE` 3773 3774 Output Parameter: 3775 . X - the result matrix (dense matrix) 3776 3777 Level: developer 3778 3779 Note: 3780 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 3781 format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`. 3782 3783 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3784 @*/ 3785 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X) 3786 { 3787 PetscFunctionBegin; 3788 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3789 PetscValidType(A, 1); 3790 PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2); 3791 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3792 PetscCheckSameComm(A, 1, Bt, 2); 3793 PetscCheckSameComm(A, 1, X, 3); 3794 3795 PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3796 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); 3797 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); 3798 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"); 3799 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3800 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3801 MatCheckPreallocated(A, 1); 3802 3803 PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0)); 3804 PetscUseTypeMethod(A, mattransposesolve, Bt, X); 3805 PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0)); 3806 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3807 PetscFunctionReturn(PETSC_SUCCESS); 3808 } 3809 3810 /*@ 3811 MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or 3812 U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U, 3813 3814 Neighbor-wise Collective 3815 3816 Input Parameters: 3817 + mat - the factored matrix 3818 - b - the right-hand-side vector 3819 3820 Output Parameter: 3821 . x - the result vector 3822 3823 Level: developer 3824 3825 Notes: 3826 `MatSolve()` should be used for most applications, as it performs 3827 a forward solve followed by a backward solve. 3828 3829 The vectors `b` and `x` cannot be the same, i.e., one cannot 3830 call `MatForwardSolve`(A,x,x). 3831 3832 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3833 the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet. 3834 `MatForwardSolve()` solves U^T*D y = b, and 3835 `MatBackwardSolve()` solves U x = y. 3836 Thus they do not provide a symmetric preconditioner. 3837 3838 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatBackwardSolve()` 3839 @*/ 3840 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x) 3841 { 3842 PetscFunctionBegin; 3843 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3844 PetscValidType(mat, 1); 3845 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3846 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3847 PetscCheckSameComm(mat, 1, b, 2); 3848 PetscCheckSameComm(mat, 1, x, 3); 3849 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3850 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); 3851 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); 3852 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); 3853 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3854 MatCheckPreallocated(mat, 1); 3855 3856 PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0)); 3857 PetscUseTypeMethod(mat, forwardsolve, b, x); 3858 PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0)); 3859 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3860 PetscFunctionReturn(PETSC_SUCCESS); 3861 } 3862 3863 /*@ 3864 MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU. 3865 D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U, 3866 3867 Neighbor-wise Collective 3868 3869 Input Parameters: 3870 + mat - the factored matrix 3871 - b - the right-hand-side vector 3872 3873 Output Parameter: 3874 . x - the result vector 3875 3876 Level: developer 3877 3878 Notes: 3879 `MatSolve()` should be used for most applications, as it performs 3880 a forward solve followed by a backward solve. 3881 3882 The vectors `b` and `x` cannot be the same. I.e., one cannot 3883 call `MatBackwardSolve`(A,x,x). 3884 3885 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3886 the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet. 3887 `MatForwardSolve()` solves U^T*D y = b, and 3888 `MatBackwardSolve()` solves U x = y. 3889 Thus they do not provide a symmetric preconditioner. 3890 3891 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatForwardSolve()` 3892 @*/ 3893 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x) 3894 { 3895 PetscFunctionBegin; 3896 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3897 PetscValidType(mat, 1); 3898 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3899 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3900 PetscCheckSameComm(mat, 1, b, 2); 3901 PetscCheckSameComm(mat, 1, x, 3); 3902 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3903 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); 3904 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); 3905 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); 3906 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3907 MatCheckPreallocated(mat, 1); 3908 3909 PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0)); 3910 PetscUseTypeMethod(mat, backwardsolve, b, x); 3911 PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0)); 3912 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3913 PetscFunctionReturn(PETSC_SUCCESS); 3914 } 3915 3916 /*@ 3917 MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix. 3918 3919 Neighbor-wise Collective 3920 3921 Input Parameters: 3922 + mat - the factored matrix 3923 . b - the right-hand-side vector 3924 - y - the vector to be added to 3925 3926 Output Parameter: 3927 . x - the result vector 3928 3929 Level: developer 3930 3931 Note: 3932 The vectors `b` and `x` cannot be the same. I.e., one cannot 3933 call `MatSolveAdd`(A,x,y,x). 3934 3935 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3936 @*/ 3937 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x) 3938 { 3939 PetscScalar one = 1.0; 3940 Vec tmp; 3941 3942 PetscFunctionBegin; 3943 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3944 PetscValidType(mat, 1); 3945 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 3946 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3947 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 3948 PetscCheckSameComm(mat, 1, b, 2); 3949 PetscCheckSameComm(mat, 1, y, 3); 3950 PetscCheckSameComm(mat, 1, x, 4); 3951 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3952 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); 3953 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); 3954 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); 3955 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); 3956 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); 3957 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3958 MatCheckPreallocated(mat, 1); 3959 3960 PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y)); 3961 if (mat->factorerrortype) { 3962 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3963 PetscCall(VecSetInf(x)); 3964 } else if (mat->ops->solveadd) { 3965 PetscUseTypeMethod(mat, solveadd, b, y, x); 3966 } else { 3967 /* do the solve then the add manually */ 3968 if (x != y) { 3969 PetscCall(MatSolve(mat, b, x)); 3970 PetscCall(VecAXPY(x, one, y)); 3971 } else { 3972 PetscCall(VecDuplicate(x, &tmp)); 3973 PetscCall(VecCopy(x, tmp)); 3974 PetscCall(MatSolve(mat, b, x)); 3975 PetscCall(VecAXPY(x, one, tmp)); 3976 PetscCall(VecDestroy(&tmp)); 3977 } 3978 } 3979 PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y)); 3980 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3981 PetscFunctionReturn(PETSC_SUCCESS); 3982 } 3983 3984 /*@ 3985 MatSolveTranspose - Solves A' x = b, given a factored matrix. 3986 3987 Neighbor-wise Collective 3988 3989 Input Parameters: 3990 + mat - the factored matrix 3991 - b - the right-hand-side vector 3992 3993 Output Parameter: 3994 . x - the result vector 3995 3996 Level: developer 3997 3998 Notes: 3999 The vectors `b` and `x` cannot be the same. I.e., one cannot 4000 call `MatSolveTranspose`(A,x,x). 4001 4002 Most users should employ the `KSP` interface for linear solvers 4003 instead of working directly with matrix algebra routines such as this. 4004 See, e.g., `KSPCreate()`. 4005 4006 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()` 4007 @*/ 4008 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x) 4009 { 4010 PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose; 4011 4012 PetscFunctionBegin; 4013 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4014 PetscValidType(mat, 1); 4015 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4016 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 4017 PetscCheckSameComm(mat, 1, b, 2); 4018 PetscCheckSameComm(mat, 1, x, 3); 4019 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4020 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); 4021 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); 4022 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4023 MatCheckPreallocated(mat, 1); 4024 PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0)); 4025 if (mat->factorerrortype) { 4026 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4027 PetscCall(VecSetInf(x)); 4028 } else { 4029 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name); 4030 PetscCall((*f)(mat, b, x)); 4031 } 4032 PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0)); 4033 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4034 PetscFunctionReturn(PETSC_SUCCESS); 4035 } 4036 4037 /*@ 4038 MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a 4039 factored matrix. 4040 4041 Neighbor-wise Collective 4042 4043 Input Parameters: 4044 + mat - the factored matrix 4045 . b - the right-hand-side vector 4046 - y - the vector to be added to 4047 4048 Output Parameter: 4049 . x - the result vector 4050 4051 Level: developer 4052 4053 Note: 4054 The vectors `b` and `x` cannot be the same. I.e., one cannot 4055 call `MatSolveTransposeAdd`(A,x,y,x). 4056 4057 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()` 4058 @*/ 4059 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x) 4060 { 4061 PetscScalar one = 1.0; 4062 Vec tmp; 4063 PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd; 4064 4065 PetscFunctionBegin; 4066 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4067 PetscValidType(mat, 1); 4068 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4069 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4070 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4071 PetscCheckSameComm(mat, 1, b, 2); 4072 PetscCheckSameComm(mat, 1, y, 3); 4073 PetscCheckSameComm(mat, 1, x, 4); 4074 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4075 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); 4076 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); 4077 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); 4078 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); 4079 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4080 MatCheckPreallocated(mat, 1); 4081 4082 PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y)); 4083 if (mat->factorerrortype) { 4084 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4085 PetscCall(VecSetInf(x)); 4086 } else if (f) { 4087 PetscCall((*f)(mat, b, y, x)); 4088 } else { 4089 /* do the solve then the add manually */ 4090 if (x != y) { 4091 PetscCall(MatSolveTranspose(mat, b, x)); 4092 PetscCall(VecAXPY(x, one, y)); 4093 } else { 4094 PetscCall(VecDuplicate(x, &tmp)); 4095 PetscCall(VecCopy(x, tmp)); 4096 PetscCall(MatSolveTranspose(mat, b, x)); 4097 PetscCall(VecAXPY(x, one, tmp)); 4098 PetscCall(VecDestroy(&tmp)); 4099 } 4100 } 4101 PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y)); 4102 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4103 PetscFunctionReturn(PETSC_SUCCESS); 4104 } 4105 4106 /*@ 4107 MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps. 4108 4109 Neighbor-wise Collective 4110 4111 Input Parameters: 4112 + mat - the matrix 4113 . b - the right hand side 4114 . omega - the relaxation factor 4115 . flag - flag indicating the type of SOR (see below) 4116 . shift - diagonal shift 4117 . its - the number of iterations 4118 - lits - the number of local iterations 4119 4120 Output Parameter: 4121 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess) 4122 4123 SOR Flags: 4124 + `SOR_FORWARD_SWEEP` - forward SOR 4125 . `SOR_BACKWARD_SWEEP` - backward SOR 4126 . `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR) 4127 . `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR 4128 . `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR 4129 . `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR 4130 . `SOR_EISENSTAT` - SOR with Eisenstat trick 4131 . `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies 4132 upper/lower triangular part of matrix to 4133 vector (with omega) 4134 - `SOR_ZERO_INITIAL_GUESS` - zero initial guess 4135 4136 Level: developer 4137 4138 Notes: 4139 `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and 4140 `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings 4141 on each processor. 4142 4143 Application programmers will not generally use `MatSOR()` directly, 4144 but instead will employ the `KSP`/`PC` interface. 4145 4146 For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing 4147 4148 Most users should employ the `KSP` interface for linear solvers 4149 instead of working directly with matrix algebra routines such as this. 4150 See, e.g., `KSPCreate()`. 4151 4152 Vectors `x` and `b` CANNOT be the same 4153 4154 The flags are implemented as bitwise inclusive or operations. 4155 For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`) 4156 to specify a zero initial guess for SSOR. 4157 4158 Developer Note: 4159 We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes 4160 4161 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()` 4162 @*/ 4163 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x) 4164 { 4165 PetscFunctionBegin; 4166 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4167 PetscValidType(mat, 1); 4168 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4169 PetscValidHeaderSpecific(x, VEC_CLASSID, 8); 4170 PetscCheckSameComm(mat, 1, b, 2); 4171 PetscCheckSameComm(mat, 1, x, 8); 4172 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4173 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4174 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); 4175 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); 4176 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); 4177 PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its); 4178 PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits); 4179 PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same"); 4180 4181 MatCheckPreallocated(mat, 1); 4182 PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0)); 4183 PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x); 4184 PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0)); 4185 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4186 PetscFunctionReturn(PETSC_SUCCESS); 4187 } 4188 4189 /* 4190 Default matrix copy routine. 4191 */ 4192 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str) 4193 { 4194 PetscInt i, rstart = 0, rend = 0, nz; 4195 const PetscInt *cwork; 4196 const PetscScalar *vwork; 4197 4198 PetscFunctionBegin; 4199 if (B->assembled) PetscCall(MatZeroEntries(B)); 4200 if (str == SAME_NONZERO_PATTERN) { 4201 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 4202 for (i = rstart; i < rend; i++) { 4203 PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork)); 4204 PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES)); 4205 PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork)); 4206 } 4207 } else { 4208 PetscCall(MatAYPX(B, 0.0, A, str)); 4209 } 4210 PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 4211 PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 4212 PetscFunctionReturn(PETSC_SUCCESS); 4213 } 4214 4215 /*@ 4216 MatCopy - Copies a matrix to another matrix. 4217 4218 Collective 4219 4220 Input Parameters: 4221 + A - the matrix 4222 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN` 4223 4224 Output Parameter: 4225 . B - where the copy is put 4226 4227 Level: intermediate 4228 4229 Notes: 4230 If you use `SAME_NONZERO_PATTERN` then the two matrices must have the same nonzero pattern or the routine will crash. 4231 4232 `MatCopy()` copies the matrix entries of a matrix to another existing 4233 matrix (after first zeroing the second matrix). A related routine is 4234 `MatConvert()`, which first creates a new matrix and then copies the data. 4235 4236 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()` 4237 @*/ 4238 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str) 4239 { 4240 PetscInt i; 4241 4242 PetscFunctionBegin; 4243 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 4244 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 4245 PetscValidType(A, 1); 4246 PetscValidType(B, 2); 4247 PetscCheckSameComm(A, 1, B, 2); 4248 MatCheckPreallocated(B, 2); 4249 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4250 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4251 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, 4252 A->cmap->N, B->cmap->N); 4253 MatCheckPreallocated(A, 1); 4254 if (A == B) PetscFunctionReturn(PETSC_SUCCESS); 4255 4256 PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0)); 4257 if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str); 4258 else PetscCall(MatCopy_Basic(A, B, str)); 4259 4260 B->stencil.dim = A->stencil.dim; 4261 B->stencil.noc = A->stencil.noc; 4262 for (i = 0; i <= A->stencil.dim; i++) { 4263 B->stencil.dims[i] = A->stencil.dims[i]; 4264 B->stencil.starts[i] = A->stencil.starts[i]; 4265 } 4266 4267 PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0)); 4268 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4269 PetscFunctionReturn(PETSC_SUCCESS); 4270 } 4271 4272 /*@C 4273 MatConvert - Converts a matrix to another matrix, either of the same 4274 or different type. 4275 4276 Collective 4277 4278 Input Parameters: 4279 + mat - the matrix 4280 . newtype - new matrix type. Use `MATSAME` to create a new matrix of the 4281 same type as the original matrix. 4282 - reuse - denotes if the destination matrix is to be created or reused. 4283 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 4284 `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). 4285 4286 Output Parameter: 4287 . M - pointer to place new matrix 4288 4289 Level: intermediate 4290 4291 Notes: 4292 `MatConvert()` first creates a new matrix and then copies the data from 4293 the first matrix. A related routine is `MatCopy()`, which copies the matrix 4294 entries of one matrix to another already existing matrix context. 4295 4296 Cannot be used to convert a sequential matrix to parallel or parallel to sequential, 4297 the MPI communicator of the generated matrix is always the same as the communicator 4298 of the input matrix. 4299 4300 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 4301 @*/ 4302 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M) 4303 { 4304 PetscBool sametype, issame, flg; 4305 PetscBool3 issymmetric, ishermitian; 4306 char convname[256], mtype[256]; 4307 Mat B; 4308 4309 PetscFunctionBegin; 4310 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4311 PetscValidType(mat, 1); 4312 PetscValidPointer(M, 4); 4313 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4314 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4315 MatCheckPreallocated(mat, 1); 4316 4317 PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg)); 4318 if (flg) newtype = mtype; 4319 4320 PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype)); 4321 PetscCall(PetscStrcmp(newtype, "same", &issame)); 4322 PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix"); 4323 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"); 4324 4325 if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) { 4326 PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4327 PetscFunctionReturn(PETSC_SUCCESS); 4328 } 4329 4330 /* Cache Mat options because some converters use MatHeaderReplace */ 4331 issymmetric = mat->symmetric; 4332 ishermitian = mat->hermitian; 4333 4334 if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) { 4335 PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4336 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4337 } else { 4338 PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL; 4339 const char *prefix[3] = {"seq", "mpi", ""}; 4340 PetscInt i; 4341 /* 4342 Order of precedence: 4343 0) See if newtype is a superclass of the current matrix. 4344 1) See if a specialized converter is known to the current matrix. 4345 2) See if a specialized converter is known to the desired matrix class. 4346 3) See if a good general converter is registered for the desired class 4347 (as of 6/27/03 only MATMPIADJ falls into this category). 4348 4) See if a good general converter is known for the current matrix. 4349 5) Use a really basic converter. 4350 */ 4351 4352 /* 0) See if newtype is a superclass of the current matrix. 4353 i.e mat is mpiaij and newtype is aij */ 4354 for (i = 0; i < 2; i++) { 4355 PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname))); 4356 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4357 PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg)); 4358 PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg)); 4359 if (flg) { 4360 if (reuse == MAT_INPLACE_MATRIX) { 4361 PetscCall(PetscInfo(mat, "Early return\n")); 4362 PetscFunctionReturn(PETSC_SUCCESS); 4363 } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) { 4364 PetscCall(PetscInfo(mat, "Calling MatDuplicate\n")); 4365 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4366 PetscFunctionReturn(PETSC_SUCCESS); 4367 } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) { 4368 PetscCall(PetscInfo(mat, "Calling MatCopy\n")); 4369 PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN)); 4370 PetscFunctionReturn(PETSC_SUCCESS); 4371 } 4372 } 4373 } 4374 /* 1) See if a specialized converter is known to the current matrix and the desired class */ 4375 for (i = 0; i < 3; i++) { 4376 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4377 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4378 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4379 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4380 PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname))); 4381 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4382 PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv)); 4383 PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv)); 4384 if (conv) goto foundconv; 4385 } 4386 4387 /* 2) See if a specialized converter is known to the desired matrix class. */ 4388 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B)); 4389 PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 4390 PetscCall(MatSetType(B, newtype)); 4391 for (i = 0; i < 3; i++) { 4392 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4393 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4394 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4395 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4396 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4397 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4398 PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv)); 4399 PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv)); 4400 if (conv) { 4401 PetscCall(MatDestroy(&B)); 4402 goto foundconv; 4403 } 4404 } 4405 4406 /* 3) See if a good general converter is registered for the desired class */ 4407 conv = B->ops->convertfrom; 4408 PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv)); 4409 PetscCall(MatDestroy(&B)); 4410 if (conv) goto foundconv; 4411 4412 /* 4) See if a good general converter is known for the current matrix */ 4413 if (mat->ops->convert) conv = mat->ops->convert; 4414 PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv)); 4415 if (conv) goto foundconv; 4416 4417 /* 5) Use a really basic converter. */ 4418 PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n")); 4419 conv = MatConvert_Basic; 4420 4421 foundconv: 4422 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4423 PetscCall((*conv)(mat, newtype, reuse, M)); 4424 if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) { 4425 /* the block sizes must be same if the mappings are copied over */ 4426 (*M)->rmap->bs = mat->rmap->bs; 4427 (*M)->cmap->bs = mat->cmap->bs; 4428 PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping)); 4429 PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping)); 4430 (*M)->rmap->mapping = mat->rmap->mapping; 4431 (*M)->cmap->mapping = mat->cmap->mapping; 4432 } 4433 (*M)->stencil.dim = mat->stencil.dim; 4434 (*M)->stencil.noc = mat->stencil.noc; 4435 for (i = 0; i <= mat->stencil.dim; i++) { 4436 (*M)->stencil.dims[i] = mat->stencil.dims[i]; 4437 (*M)->stencil.starts[i] = mat->stencil.starts[i]; 4438 } 4439 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4440 } 4441 PetscCall(PetscObjectStateIncrease((PetscObject)*M)); 4442 4443 /* Copy Mat options */ 4444 if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE)); 4445 else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE)); 4446 if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE)); 4447 else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE)); 4448 PetscFunctionReturn(PETSC_SUCCESS); 4449 } 4450 4451 /*@C 4452 MatFactorGetSolverType - Returns name of the package providing the factorization routines 4453 4454 Not Collective 4455 4456 Input Parameter: 4457 . mat - the matrix, must be a factored matrix 4458 4459 Output Parameter: 4460 . type - the string name of the package (do not free this string) 4461 4462 Level: intermediate 4463 4464 Fortran Note: 4465 Pass in an empty string and the package name will be copied into it. Make sure the string is long enough. 4466 4467 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()` 4468 @*/ 4469 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type) 4470 { 4471 PetscErrorCode (*conv)(Mat, MatSolverType *); 4472 4473 PetscFunctionBegin; 4474 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4475 PetscValidType(mat, 1); 4476 PetscValidPointer(type, 2); 4477 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 4478 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv)); 4479 if (conv) PetscCall((*conv)(mat, type)); 4480 else *type = MATSOLVERPETSC; 4481 PetscFunctionReturn(PETSC_SUCCESS); 4482 } 4483 4484 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType; 4485 struct _MatSolverTypeForSpecifcType { 4486 MatType mtype; 4487 /* no entry for MAT_FACTOR_NONE */ 4488 PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *); 4489 MatSolverTypeForSpecifcType next; 4490 }; 4491 4492 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder; 4493 struct _MatSolverTypeHolder { 4494 char *name; 4495 MatSolverTypeForSpecifcType handlers; 4496 MatSolverTypeHolder next; 4497 }; 4498 4499 static MatSolverTypeHolder MatSolverTypeHolders = NULL; 4500 4501 /*@C 4502 MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type 4503 4504 Input Parameters: 4505 + package - name of the package, for example petsc or superlu 4506 . mtype - the matrix type that works with this package 4507 . ftype - the type of factorization supported by the package 4508 - createfactor - routine that will create the factored matrix ready to be used 4509 4510 Level: developer 4511 4512 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()` 4513 @*/ 4514 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *)) 4515 { 4516 MatSolverTypeHolder next = MatSolverTypeHolders, prev = NULL; 4517 PetscBool flg; 4518 MatSolverTypeForSpecifcType inext, iprev = NULL; 4519 4520 PetscFunctionBegin; 4521 PetscCall(MatInitializePackage()); 4522 if (!next) { 4523 PetscCall(PetscNew(&MatSolverTypeHolders)); 4524 PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name)); 4525 PetscCall(PetscNew(&MatSolverTypeHolders->handlers)); 4526 PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype)); 4527 MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor; 4528 PetscFunctionReturn(PETSC_SUCCESS); 4529 } 4530 while (next) { 4531 PetscCall(PetscStrcasecmp(package, next->name, &flg)); 4532 if (flg) { 4533 PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers"); 4534 inext = next->handlers; 4535 while (inext) { 4536 PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg)); 4537 if (flg) { 4538 inext->createfactor[(int)ftype - 1] = createfactor; 4539 PetscFunctionReturn(PETSC_SUCCESS); 4540 } 4541 iprev = inext; 4542 inext = inext->next; 4543 } 4544 PetscCall(PetscNew(&iprev->next)); 4545 PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype)); 4546 iprev->next->createfactor[(int)ftype - 1] = createfactor; 4547 PetscFunctionReturn(PETSC_SUCCESS); 4548 } 4549 prev = next; 4550 next = next->next; 4551 } 4552 PetscCall(PetscNew(&prev->next)); 4553 PetscCall(PetscStrallocpy(package, &prev->next->name)); 4554 PetscCall(PetscNew(&prev->next->handlers)); 4555 PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype)); 4556 prev->next->handlers->createfactor[(int)ftype - 1] = createfactor; 4557 PetscFunctionReturn(PETSC_SUCCESS); 4558 } 4559 4560 /*@C 4561 MatSolverTypeGet - Gets the function that creates the factor matrix if it exist 4562 4563 Input Parameters: 4564 + type - name of the package, for example petsc or superlu 4565 . ftype - the type of factorization supported by the type 4566 - mtype - the matrix type that works with this type 4567 4568 Output Parameters: 4569 + foundtype - `PETSC_TRUE` if the type was registered 4570 . foundmtype - `PETSC_TRUE` if the type supports the requested mtype 4571 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found 4572 4573 Level: developer 4574 4575 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()` 4576 @*/ 4577 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *)) 4578 { 4579 MatSolverTypeHolder next = MatSolverTypeHolders; 4580 PetscBool flg; 4581 MatSolverTypeForSpecifcType inext; 4582 4583 PetscFunctionBegin; 4584 if (foundtype) *foundtype = PETSC_FALSE; 4585 if (foundmtype) *foundmtype = PETSC_FALSE; 4586 if (createfactor) *createfactor = NULL; 4587 4588 if (type) { 4589 while (next) { 4590 PetscCall(PetscStrcasecmp(type, next->name, &flg)); 4591 if (flg) { 4592 if (foundtype) *foundtype = PETSC_TRUE; 4593 inext = next->handlers; 4594 while (inext) { 4595 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4596 if (flg) { 4597 if (foundmtype) *foundmtype = PETSC_TRUE; 4598 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4599 PetscFunctionReturn(PETSC_SUCCESS); 4600 } 4601 inext = inext->next; 4602 } 4603 } 4604 next = next->next; 4605 } 4606 } else { 4607 while (next) { 4608 inext = next->handlers; 4609 while (inext) { 4610 PetscCall(PetscStrcmp(mtype, inext->mtype, &flg)); 4611 if (flg && inext->createfactor[(int)ftype - 1]) { 4612 if (foundtype) *foundtype = PETSC_TRUE; 4613 if (foundmtype) *foundmtype = PETSC_TRUE; 4614 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4615 PetscFunctionReturn(PETSC_SUCCESS); 4616 } 4617 inext = inext->next; 4618 } 4619 next = next->next; 4620 } 4621 /* try with base classes inext->mtype */ 4622 next = MatSolverTypeHolders; 4623 while (next) { 4624 inext = next->handlers; 4625 while (inext) { 4626 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4627 if (flg && inext->createfactor[(int)ftype - 1]) { 4628 if (foundtype) *foundtype = PETSC_TRUE; 4629 if (foundmtype) *foundmtype = PETSC_TRUE; 4630 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4631 PetscFunctionReturn(PETSC_SUCCESS); 4632 } 4633 inext = inext->next; 4634 } 4635 next = next->next; 4636 } 4637 } 4638 PetscFunctionReturn(PETSC_SUCCESS); 4639 } 4640 4641 PetscErrorCode MatSolverTypeDestroy(void) 4642 { 4643 MatSolverTypeHolder next = MatSolverTypeHolders, prev; 4644 MatSolverTypeForSpecifcType inext, iprev; 4645 4646 PetscFunctionBegin; 4647 while (next) { 4648 PetscCall(PetscFree(next->name)); 4649 inext = next->handlers; 4650 while (inext) { 4651 PetscCall(PetscFree(inext->mtype)); 4652 iprev = inext; 4653 inext = inext->next; 4654 PetscCall(PetscFree(iprev)); 4655 } 4656 prev = next; 4657 next = next->next; 4658 PetscCall(PetscFree(prev)); 4659 } 4660 MatSolverTypeHolders = NULL; 4661 PetscFunctionReturn(PETSC_SUCCESS); 4662 } 4663 4664 /*@C 4665 MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4666 4667 Logically Collective 4668 4669 Input Parameter: 4670 . mat - the matrix 4671 4672 Output Parameter: 4673 . flg - `PETSC_TRUE` if uses the ordering 4674 4675 Level: developer 4676 4677 Note: 4678 Most internal PETSc factorizations use the ordering passed to the factorization routine but external 4679 packages do not, thus we want to skip generating the ordering when it is not needed or used. 4680 4681 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4682 @*/ 4683 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg) 4684 { 4685 PetscFunctionBegin; 4686 *flg = mat->canuseordering; 4687 PetscFunctionReturn(PETSC_SUCCESS); 4688 } 4689 4690 /*@C 4691 MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object 4692 4693 Logically Collective 4694 4695 Input Parameters: 4696 + mat - the matrix obtained with `MatGetFactor()` 4697 - ftype - the factorization type to be used 4698 4699 Output Parameter: 4700 . otype - the preferred ordering type 4701 4702 Level: developer 4703 4704 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4705 @*/ 4706 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype) 4707 { 4708 PetscFunctionBegin; 4709 *otype = mat->preferredordering[ftype]; 4710 PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering"); 4711 PetscFunctionReturn(PETSC_SUCCESS); 4712 } 4713 4714 /*@C 4715 MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic() 4716 4717 Collective 4718 4719 Input Parameters: 4720 + mat - the matrix 4721 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4722 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4723 4724 Output Parameter: 4725 . f - the factor matrix used with MatXXFactorSymbolic() calls. Can be `NULL` in some cases, see notes below. 4726 4727 Options Database Key: 4728 . -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory. 4729 One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices. 4730 4731 Level: intermediate 4732 4733 Notes: 4734 The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization 4735 types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime. 4736 4737 Users usually access the factorization solvers via `KSP` 4738 4739 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4740 such as pastix, superlu, mumps etc. 4741 4742 PETSc must have been ./configure to use the external solver, using the option --download-package 4743 4744 Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption 4745 where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set 4746 call `MatSetOptionsPrefixFactor()` on the originating matrix or `MatSetOptionsPrefix()` on the resulting factor matrix. 4747 4748 Developer Note: 4749 This should actually be called `MatCreateFactor()` since it creates a new factor object 4750 4751 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, 4752 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4753 @*/ 4754 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f) 4755 { 4756 PetscBool foundtype, foundmtype; 4757 PetscErrorCode (*conv)(Mat, MatFactorType, Mat *); 4758 4759 PetscFunctionBegin; 4760 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4761 PetscValidType(mat, 1); 4762 4763 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4764 MatCheckPreallocated(mat, 1); 4765 4766 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv)); 4767 if (!foundtype) { 4768 if (type) { 4769 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], 4770 ((PetscObject)mat)->type_name, type); 4771 } else { 4772 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); 4773 } 4774 } 4775 PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name); 4776 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); 4777 4778 PetscCall((*conv)(mat, ftype, f)); 4779 if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix)); 4780 PetscFunctionReturn(PETSC_SUCCESS); 4781 } 4782 4783 /*@C 4784 MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type 4785 4786 Not Collective 4787 4788 Input Parameters: 4789 + mat - the matrix 4790 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4791 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4792 4793 Output Parameter: 4794 . flg - PETSC_TRUE if the factorization is available 4795 4796 Level: intermediate 4797 4798 Notes: 4799 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4800 such as pastix, superlu, mumps etc. 4801 4802 PETSc must have been ./configure to use the external solver, using the option --download-package 4803 4804 Developer Note: 4805 This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object 4806 4807 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactor()`, `MatSolverTypeRegister()`, 4808 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4809 @*/ 4810 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg) 4811 { 4812 PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *); 4813 4814 PetscFunctionBegin; 4815 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4816 PetscValidType(mat, 1); 4817 PetscValidBoolPointer(flg, 4); 4818 4819 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4820 MatCheckPreallocated(mat, 1); 4821 4822 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv)); 4823 *flg = gconv ? PETSC_TRUE : PETSC_FALSE; 4824 PetscFunctionReturn(PETSC_SUCCESS); 4825 } 4826 4827 /*@ 4828 MatDuplicate - Duplicates a matrix including the non-zero structure. 4829 4830 Collective 4831 4832 Input Parameters: 4833 + mat - the matrix 4834 - op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`. 4835 See the manual page for `MatDuplicateOption()` for an explanation of these options. 4836 4837 Output Parameter: 4838 . M - pointer to place new matrix 4839 4840 Level: intermediate 4841 4842 Notes: 4843 You cannot change the nonzero pattern for the parent or child matrix if you use `MAT_SHARE_NONZERO_PATTERN`. 4844 4845 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. 4846 4847 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 4848 is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated. 4849 User should not use `MatDuplicate()` to create new matrix M if M is intended to be reused as the product of matrix operation. 4850 4851 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption` 4852 @*/ 4853 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M) 4854 { 4855 Mat B; 4856 VecType vtype; 4857 PetscInt i; 4858 PetscObject dm, container_h, container_d; 4859 void (*viewf)(void); 4860 4861 PetscFunctionBegin; 4862 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4863 PetscValidType(mat, 1); 4864 PetscValidPointer(M, 3); 4865 PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix"); 4866 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4867 MatCheckPreallocated(mat, 1); 4868 4869 *M = NULL; 4870 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4871 PetscUseTypeMethod(mat, duplicate, op, M); 4872 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4873 B = *M; 4874 4875 PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf)); 4876 if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf)); 4877 PetscCall(MatGetVecType(mat, &vtype)); 4878 PetscCall(MatSetVecType(B, vtype)); 4879 4880 B->stencil.dim = mat->stencil.dim; 4881 B->stencil.noc = mat->stencil.noc; 4882 for (i = 0; i <= mat->stencil.dim; i++) { 4883 B->stencil.dims[i] = mat->stencil.dims[i]; 4884 B->stencil.starts[i] = mat->stencil.starts[i]; 4885 } 4886 4887 B->nooffproczerorows = mat->nooffproczerorows; 4888 B->nooffprocentries = mat->nooffprocentries; 4889 4890 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm)); 4891 if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm)); 4892 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h)); 4893 if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h)); 4894 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d)); 4895 if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d)); 4896 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4897 PetscFunctionReturn(PETSC_SUCCESS); 4898 } 4899 4900 /*@ 4901 MatGetDiagonal - Gets the diagonal of a matrix as a `Vec` 4902 4903 Logically Collective 4904 4905 Input Parameter: 4906 . mat - the matrix 4907 4908 Output Parameter: 4909 . v - the diagonal of the matrix 4910 4911 Level: intermediate 4912 4913 Note: 4914 If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries 4915 of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v` 4916 is larger than `ndiag`, the values of the remaining entries are unspecified. 4917 4918 Currently only correct in parallel for square matrices. 4919 4920 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()` 4921 @*/ 4922 PetscErrorCode MatGetDiagonal(Mat mat, Vec v) 4923 { 4924 PetscFunctionBegin; 4925 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4926 PetscValidType(mat, 1); 4927 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4928 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4929 MatCheckPreallocated(mat, 1); 4930 if (PetscDefined(USE_DEBUG)) { 4931 PetscInt nv, row, col, ndiag; 4932 4933 PetscCall(VecGetLocalSize(v, &nv)); 4934 PetscCall(MatGetLocalSize(mat, &row, &col)); 4935 ndiag = PetscMin(row, col); 4936 PetscCheck(nv >= ndiag, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming Mat and Vec. Vec local size %" PetscInt_FMT " < Mat local diagonal length %" PetscInt_FMT, nv, ndiag); 4937 } 4938 4939 PetscUseTypeMethod(mat, getdiagonal, v); 4940 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4941 PetscFunctionReturn(PETSC_SUCCESS); 4942 } 4943 4944 /*@C 4945 MatGetRowMin - Gets the minimum value (of the real part) of each 4946 row of the matrix 4947 4948 Logically Collective 4949 4950 Input Parameter: 4951 . mat - the matrix 4952 4953 Output Parameters: 4954 + v - the vector for storing the maximums 4955 - idx - the indices of the column found for each row (optional) 4956 4957 Level: intermediate 4958 4959 Note: 4960 The result of this call are the same as if one converted the matrix to dense format 4961 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 4962 4963 This code is only implemented for a couple of matrix formats. 4964 4965 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, 4966 `MatGetRowMax()` 4967 @*/ 4968 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[]) 4969 { 4970 PetscFunctionBegin; 4971 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4972 PetscValidType(mat, 1); 4973 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4974 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4975 4976 if (!mat->cmap->N) { 4977 PetscCall(VecSet(v, PETSC_MAX_REAL)); 4978 if (idx) { 4979 PetscInt i, m = mat->rmap->n; 4980 for (i = 0; i < m; i++) idx[i] = -1; 4981 } 4982 } else { 4983 MatCheckPreallocated(mat, 1); 4984 } 4985 PetscUseTypeMethod(mat, getrowmin, v, idx); 4986 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4987 PetscFunctionReturn(PETSC_SUCCESS); 4988 } 4989 4990 /*@C 4991 MatGetRowMinAbs - Gets the minimum value (in absolute value) of each 4992 row of the matrix 4993 4994 Logically Collective 4995 4996 Input Parameter: 4997 . mat - the matrix 4998 4999 Output Parameters: 5000 + v - the vector for storing the minimums 5001 - idx - the indices of the column found for each row (or `NULL` if not needed) 5002 5003 Level: intermediate 5004 5005 Notes: 5006 if a row is completely empty or has only 0.0 values then the idx[] value for that 5007 row is 0 (the first column). 5008 5009 This code is only implemented for a couple of matrix formats. 5010 5011 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()` 5012 @*/ 5013 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[]) 5014 { 5015 PetscFunctionBegin; 5016 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5017 PetscValidType(mat, 1); 5018 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5019 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5020 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5021 5022 if (!mat->cmap->N) { 5023 PetscCall(VecSet(v, 0.0)); 5024 if (idx) { 5025 PetscInt i, m = mat->rmap->n; 5026 for (i = 0; i < m; i++) idx[i] = -1; 5027 } 5028 } else { 5029 MatCheckPreallocated(mat, 1); 5030 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5031 PetscUseTypeMethod(mat, getrowminabs, v, idx); 5032 } 5033 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5034 PetscFunctionReturn(PETSC_SUCCESS); 5035 } 5036 5037 /*@C 5038 MatGetRowMax - Gets the maximum value (of the real part) of each 5039 row of the matrix 5040 5041 Logically Collective 5042 5043 Input Parameter: 5044 . mat - the matrix 5045 5046 Output Parameters: 5047 + v - the vector for storing the maximums 5048 - idx - the indices of the column found for each row (optional) 5049 5050 Level: intermediate 5051 5052 Notes: 5053 The result of this call are the same as if one converted the matrix to dense format 5054 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5055 5056 This code is only implemented for a couple of matrix formats. 5057 5058 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5059 @*/ 5060 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[]) 5061 { 5062 PetscFunctionBegin; 5063 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5064 PetscValidType(mat, 1); 5065 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5066 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5067 5068 if (!mat->cmap->N) { 5069 PetscCall(VecSet(v, PETSC_MIN_REAL)); 5070 if (idx) { 5071 PetscInt i, m = mat->rmap->n; 5072 for (i = 0; i < m; i++) idx[i] = -1; 5073 } 5074 } else { 5075 MatCheckPreallocated(mat, 1); 5076 PetscUseTypeMethod(mat, getrowmax, v, idx); 5077 } 5078 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5079 PetscFunctionReturn(PETSC_SUCCESS); 5080 } 5081 5082 /*@C 5083 MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each 5084 row of the matrix 5085 5086 Logically Collective 5087 5088 Input Parameter: 5089 . mat - the matrix 5090 5091 Output Parameters: 5092 + v - the vector for storing the maximums 5093 - idx - the indices of the column found for each row (or `NULL` if not needed) 5094 5095 Level: intermediate 5096 5097 Notes: 5098 if a row is completely empty or has only 0.0 values then the idx[] value for that 5099 row is 0 (the first column). 5100 5101 This code is only implemented for a couple of matrix formats. 5102 5103 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5104 @*/ 5105 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[]) 5106 { 5107 PetscFunctionBegin; 5108 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5109 PetscValidType(mat, 1); 5110 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5111 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5112 5113 if (!mat->cmap->N) { 5114 PetscCall(VecSet(v, 0.0)); 5115 if (idx) { 5116 PetscInt i, m = mat->rmap->n; 5117 for (i = 0; i < m; i++) idx[i] = -1; 5118 } 5119 } else { 5120 MatCheckPreallocated(mat, 1); 5121 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5122 PetscUseTypeMethod(mat, getrowmaxabs, v, idx); 5123 } 5124 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5125 PetscFunctionReturn(PETSC_SUCCESS); 5126 } 5127 5128 /*@ 5129 MatGetRowSum - Gets the sum of each row of the matrix 5130 5131 Logically or Neighborhood Collective 5132 5133 Input Parameter: 5134 . mat - the matrix 5135 5136 Output Parameter: 5137 . v - the vector for storing the sum of rows 5138 5139 Level: intermediate 5140 5141 Notes: 5142 This code is slow since it is not currently specialized for different formats 5143 5144 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()` 5145 @*/ 5146 PetscErrorCode MatGetRowSum(Mat mat, Vec v) 5147 { 5148 Vec ones; 5149 5150 PetscFunctionBegin; 5151 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5152 PetscValidType(mat, 1); 5153 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5154 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5155 MatCheckPreallocated(mat, 1); 5156 PetscCall(MatCreateVecs(mat, &ones, NULL)); 5157 PetscCall(VecSet(ones, 1.)); 5158 PetscCall(MatMult(mat, ones, v)); 5159 PetscCall(VecDestroy(&ones)); 5160 PetscFunctionReturn(PETSC_SUCCESS); 5161 } 5162 5163 /*@ 5164 MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) 5165 when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B) 5166 5167 Collective 5168 5169 Input Parameter: 5170 . mat - the matrix to provide the transpose 5171 5172 Output Parameter: 5173 . 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 5174 5175 Level: advanced 5176 5177 Note: 5178 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 5179 routine allows bypassing that call. 5180 5181 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5182 @*/ 5183 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B) 5184 { 5185 PetscContainer rB = NULL; 5186 MatParentState *rb = NULL; 5187 5188 PetscFunctionBegin; 5189 PetscCall(PetscNew(&rb)); 5190 rb->id = ((PetscObject)mat)->id; 5191 rb->state = 0; 5192 PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate)); 5193 PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB)); 5194 PetscCall(PetscContainerSetPointer(rB, rb)); 5195 PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault)); 5196 PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB)); 5197 PetscCall(PetscObjectDereference((PetscObject)rB)); 5198 PetscFunctionReturn(PETSC_SUCCESS); 5199 } 5200 5201 /*@ 5202 MatTranspose - Computes an in-place or out-of-place transpose of a matrix. 5203 5204 Collective 5205 5206 Input Parameters: 5207 + mat - the matrix to transpose 5208 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5209 5210 Output Parameter: 5211 . B - the transpose 5212 5213 Level: intermediate 5214 5215 Notes: 5216 If you use `MAT_INPLACE_MATRIX` then you must pass in &mat for B 5217 5218 `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 5219 transpose, call `MatTransposeSetPrecursor`(mat,B) before calling this routine. 5220 5221 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. 5222 5223 Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed. 5224 5225 If mat is unchanged from the last call this function returns immediately without recomputing the result 5226 5227 If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()` 5228 5229 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`, 5230 `MatTransposeSymbolic()`, `MatCreateTranspose()` 5231 @*/ 5232 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B) 5233 { 5234 PetscContainer rB = NULL; 5235 MatParentState *rb = NULL; 5236 5237 PetscFunctionBegin; 5238 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5239 PetscValidType(mat, 1); 5240 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5241 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5242 PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first"); 5243 PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX"); 5244 MatCheckPreallocated(mat, 1); 5245 if (reuse == MAT_REUSE_MATRIX) { 5246 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5247 PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor()."); 5248 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5249 PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5250 if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS); 5251 } 5252 5253 PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0)); 5254 if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) { 5255 PetscUseTypeMethod(mat, transpose, reuse, B); 5256 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5257 } 5258 PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0)); 5259 5260 if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B)); 5261 if (reuse != MAT_INPLACE_MATRIX) { 5262 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5263 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5264 rb->state = ((PetscObject)mat)->state; 5265 rb->nonzerostate = mat->nonzerostate; 5266 } 5267 PetscFunctionReturn(PETSC_SUCCESS); 5268 } 5269 5270 /*@ 5271 MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix. 5272 5273 Collective 5274 5275 Input Parameter: 5276 . A - the matrix to transpose 5277 5278 Output Parameter: 5279 . 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 5280 numerical portion. 5281 5282 Level: intermediate 5283 5284 Note: 5285 This is not supported for many matrix types, use `MatTranspose()` in those cases 5286 5287 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5288 @*/ 5289 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B) 5290 { 5291 PetscFunctionBegin; 5292 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5293 PetscValidType(A, 1); 5294 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5295 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5296 PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0)); 5297 PetscUseTypeMethod(A, transposesymbolic, B); 5298 PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0)); 5299 5300 PetscCall(MatTransposeSetPrecursor(A, *B)); 5301 PetscFunctionReturn(PETSC_SUCCESS); 5302 } 5303 5304 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B) 5305 { 5306 PetscContainer rB; 5307 MatParentState *rb; 5308 5309 PetscFunctionBegin; 5310 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5311 PetscValidType(A, 1); 5312 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5313 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5314 PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB)); 5315 PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()"); 5316 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5317 PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5318 PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure"); 5319 PetscFunctionReturn(PETSC_SUCCESS); 5320 } 5321 5322 /*@ 5323 MatIsTranspose - Test whether a matrix is another one's transpose, 5324 or its own, in which case it tests symmetry. 5325 5326 Collective 5327 5328 Input Parameters: 5329 + A - the matrix to test 5330 . B - the matrix to test against, this can equal the first parameter 5331 - tol - tolerance, differences between entries smaller than this are counted as zero 5332 5333 Output Parameter: 5334 . flg - the result 5335 5336 Level: intermediate 5337 5338 Notes: 5339 Only available for `MATAIJ` matrices. 5340 5341 The sequential algorithm has a running time of the order of the number of nonzeros; the parallel 5342 test involves parallel copies of the block-offdiagonal parts of the matrix. 5343 5344 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()` 5345 @*/ 5346 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5347 { 5348 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5349 5350 PetscFunctionBegin; 5351 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5352 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5353 PetscValidBoolPointer(flg, 4); 5354 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f)); 5355 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g)); 5356 *flg = PETSC_FALSE; 5357 if (f && g) { 5358 PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test"); 5359 PetscCall((*f)(A, B, tol, flg)); 5360 } else { 5361 MatType mattype; 5362 5363 PetscCall(MatGetType(f ? B : A, &mattype)); 5364 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype); 5365 } 5366 PetscFunctionReturn(PETSC_SUCCESS); 5367 } 5368 5369 /*@ 5370 MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate. 5371 5372 Collective 5373 5374 Input Parameters: 5375 + mat - the matrix to transpose and complex conjugate 5376 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5377 5378 Output Parameter: 5379 . B - the Hermitian transpose 5380 5381 Level: intermediate 5382 5383 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse` 5384 @*/ 5385 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B) 5386 { 5387 PetscFunctionBegin; 5388 PetscCall(MatTranspose(mat, reuse, B)); 5389 #if defined(PETSC_USE_COMPLEX) 5390 PetscCall(MatConjugate(*B)); 5391 #endif 5392 PetscFunctionReturn(PETSC_SUCCESS); 5393 } 5394 5395 /*@ 5396 MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose, 5397 5398 Collective 5399 5400 Input Parameters: 5401 + A - the matrix to test 5402 . B - the matrix to test against, this can equal the first parameter 5403 - tol - tolerance, differences between entries smaller than this are counted as zero 5404 5405 Output Parameter: 5406 . flg - the result 5407 5408 Level: intermediate 5409 5410 Notes: 5411 Only available for `MATAIJ` matrices. 5412 5413 The sequential algorithm 5414 has a running time of the order of the number of nonzeros; the parallel 5415 test involves parallel copies of the block-offdiagonal parts of the matrix. 5416 5417 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()` 5418 @*/ 5419 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5420 { 5421 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5422 5423 PetscFunctionBegin; 5424 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5425 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5426 PetscValidBoolPointer(flg, 4); 5427 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f)); 5428 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g)); 5429 if (f && g) { 5430 PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test"); 5431 PetscCall((*f)(A, B, tol, flg)); 5432 } 5433 PetscFunctionReturn(PETSC_SUCCESS); 5434 } 5435 5436 /*@ 5437 MatPermute - Creates a new matrix with rows and columns permuted from the 5438 original. 5439 5440 Collective 5441 5442 Input Parameters: 5443 + mat - the matrix to permute 5444 . row - row permutation, each processor supplies only the permutation for its rows 5445 - col - column permutation, each processor supplies only the permutation for its columns 5446 5447 Output Parameter: 5448 . B - the permuted matrix 5449 5450 Level: advanced 5451 5452 Note: 5453 The index sets map from row/col of permuted matrix to row/col of original matrix. 5454 The index sets should be on the same communicator as mat and have the same local sizes. 5455 5456 Developer Note: 5457 If you want to implement `MatPermute()` for a matrix type, and your approach doesn't 5458 exploit the fact that row and col are permutations, consider implementing the 5459 more general `MatCreateSubMatrix()` instead. 5460 5461 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()` 5462 @*/ 5463 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B) 5464 { 5465 PetscFunctionBegin; 5466 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5467 PetscValidType(mat, 1); 5468 PetscValidHeaderSpecific(row, IS_CLASSID, 2); 5469 PetscValidHeaderSpecific(col, IS_CLASSID, 3); 5470 PetscValidPointer(B, 4); 5471 PetscCheckSameComm(mat, 1, row, 2); 5472 if (row != col) PetscCheckSameComm(row, 2, col, 3); 5473 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5474 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5475 PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name); 5476 MatCheckPreallocated(mat, 1); 5477 5478 if (mat->ops->permute) { 5479 PetscUseTypeMethod(mat, permute, row, col, B); 5480 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5481 } else { 5482 PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B)); 5483 } 5484 PetscFunctionReturn(PETSC_SUCCESS); 5485 } 5486 5487 /*@ 5488 MatEqual - Compares two matrices. 5489 5490 Collective 5491 5492 Input Parameters: 5493 + A - the first matrix 5494 - B - the second matrix 5495 5496 Output Parameter: 5497 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise. 5498 5499 Level: intermediate 5500 5501 .seealso: [](ch_matrices), `Mat` 5502 @*/ 5503 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg) 5504 { 5505 PetscFunctionBegin; 5506 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5507 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5508 PetscValidType(A, 1); 5509 PetscValidType(B, 2); 5510 PetscValidBoolPointer(flg, 3); 5511 PetscCheckSameComm(A, 1, B, 2); 5512 MatCheckPreallocated(A, 1); 5513 MatCheckPreallocated(B, 2); 5514 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5515 PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5516 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, 5517 B->cmap->N); 5518 if (A->ops->equal && A->ops->equal == B->ops->equal) { 5519 PetscUseTypeMethod(A, equal, B, flg); 5520 } else { 5521 PetscCall(MatMultEqual(A, B, 10, flg)); 5522 } 5523 PetscFunctionReturn(PETSC_SUCCESS); 5524 } 5525 5526 /*@ 5527 MatDiagonalScale - Scales a matrix on the left and right by diagonal 5528 matrices that are stored as vectors. Either of the two scaling 5529 matrices can be `NULL`. 5530 5531 Collective 5532 5533 Input Parameters: 5534 + mat - the matrix to be scaled 5535 . l - the left scaling vector (or `NULL`) 5536 - r - the right scaling vector (or `NULL`) 5537 5538 Level: intermediate 5539 5540 Note: 5541 `MatDiagonalScale()` computes A = LAR, where 5542 L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector) 5543 The L scales the rows of the matrix, the R scales the columns of the matrix. 5544 5545 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()` 5546 @*/ 5547 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r) 5548 { 5549 PetscFunctionBegin; 5550 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5551 PetscValidType(mat, 1); 5552 if (l) { 5553 PetscValidHeaderSpecific(l, VEC_CLASSID, 2); 5554 PetscCheckSameComm(mat, 1, l, 2); 5555 } 5556 if (r) { 5557 PetscValidHeaderSpecific(r, VEC_CLASSID, 3); 5558 PetscCheckSameComm(mat, 1, r, 3); 5559 } 5560 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5561 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5562 MatCheckPreallocated(mat, 1); 5563 if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS); 5564 5565 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5566 PetscUseTypeMethod(mat, diagonalscale, l, r); 5567 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5568 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5569 if (l != r) mat->symmetric = PETSC_BOOL3_FALSE; 5570 PetscFunctionReturn(PETSC_SUCCESS); 5571 } 5572 5573 /*@ 5574 MatScale - Scales all elements of a matrix by a given number. 5575 5576 Logically Collective 5577 5578 Input Parameters: 5579 + mat - the matrix to be scaled 5580 - a - the scaling value 5581 5582 Level: intermediate 5583 5584 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 5585 @*/ 5586 PetscErrorCode MatScale(Mat mat, PetscScalar a) 5587 { 5588 PetscFunctionBegin; 5589 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5590 PetscValidType(mat, 1); 5591 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5592 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5593 PetscValidLogicalCollectiveScalar(mat, a, 2); 5594 MatCheckPreallocated(mat, 1); 5595 5596 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5597 if (a != (PetscScalar)1.0) { 5598 PetscUseTypeMethod(mat, scale, a); 5599 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5600 } 5601 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5602 PetscFunctionReturn(PETSC_SUCCESS); 5603 } 5604 5605 /*@ 5606 MatNorm - Calculates various norms of a matrix. 5607 5608 Collective 5609 5610 Input Parameters: 5611 + mat - the matrix 5612 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY` 5613 5614 Output Parameter: 5615 . nrm - the resulting norm 5616 5617 Level: intermediate 5618 5619 .seealso: [](ch_matrices), `Mat` 5620 @*/ 5621 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm) 5622 { 5623 PetscFunctionBegin; 5624 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5625 PetscValidType(mat, 1); 5626 PetscValidRealPointer(nrm, 3); 5627 5628 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5629 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5630 MatCheckPreallocated(mat, 1); 5631 5632 PetscUseTypeMethod(mat, norm, type, nrm); 5633 PetscFunctionReturn(PETSC_SUCCESS); 5634 } 5635 5636 /* 5637 This variable is used to prevent counting of MatAssemblyBegin() that 5638 are called from within a MatAssemblyEnd(). 5639 */ 5640 static PetscInt MatAssemblyEnd_InUse = 0; 5641 /*@ 5642 MatAssemblyBegin - Begins assembling the matrix. This routine should 5643 be called after completing all calls to `MatSetValues()`. 5644 5645 Collective 5646 5647 Input Parameters: 5648 + mat - the matrix 5649 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5650 5651 Level: beginner 5652 5653 Notes: 5654 `MatSetValues()` generally caches the values that belong to other MPI processes. The matrix is ready to 5655 use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called. 5656 5657 Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES` 5658 in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before 5659 using the matrix. 5660 5661 ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the 5662 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 5663 a global collective operation requiring all processes that share the matrix. 5664 5665 Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed 5666 out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros 5667 before `MAT_FINAL_ASSEMBLY` so the space is not compressed out. 5668 5669 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()` 5670 @*/ 5671 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type) 5672 { 5673 PetscFunctionBegin; 5674 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5675 PetscValidType(mat, 1); 5676 MatCheckPreallocated(mat, 1); 5677 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?"); 5678 if (mat->assembled) { 5679 mat->was_assembled = PETSC_TRUE; 5680 mat->assembled = PETSC_FALSE; 5681 } 5682 5683 if (!MatAssemblyEnd_InUse) { 5684 PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0)); 5685 PetscTryTypeMethod(mat, assemblybegin, type); 5686 PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0)); 5687 } else PetscTryTypeMethod(mat, assemblybegin, type); 5688 PetscFunctionReturn(PETSC_SUCCESS); 5689 } 5690 5691 /*@ 5692 MatAssembled - Indicates if a matrix has been assembled and is ready for 5693 use; for example, in matrix-vector product. 5694 5695 Not Collective 5696 5697 Input Parameter: 5698 . mat - the matrix 5699 5700 Output Parameter: 5701 . assembled - `PETSC_TRUE` or `PETSC_FALSE` 5702 5703 Level: advanced 5704 5705 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()` 5706 @*/ 5707 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled) 5708 { 5709 PetscFunctionBegin; 5710 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5711 PetscValidBoolPointer(assembled, 2); 5712 *assembled = mat->assembled; 5713 PetscFunctionReturn(PETSC_SUCCESS); 5714 } 5715 5716 /*@ 5717 MatAssemblyEnd - Completes assembling the matrix. This routine should 5718 be called after `MatAssemblyBegin()`. 5719 5720 Collective 5721 5722 Input Parameters: 5723 + mat - the matrix 5724 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5725 5726 Options Database Keys: 5727 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 5728 . -mat_view ::ascii_info_detail - Prints more detailed info 5729 . -mat_view - Prints matrix in ASCII format 5730 . -mat_view ::ascii_matlab - Prints matrix in Matlab format 5731 . -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 5732 . -display <name> - Sets display name (default is host) 5733 . -draw_pause <sec> - Sets number of seconds to pause after display 5734 . -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See [Using MATLAB with PETSc](ch_matlab)) 5735 . -viewer_socket_machine <machine> - Machine to use for socket 5736 . -viewer_socket_port <port> - Port number to use for socket 5737 - -mat_view binary:filename[:append] - Save matrix to file in binary format 5738 5739 Level: beginner 5740 5741 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()` 5742 @*/ 5743 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type) 5744 { 5745 static PetscInt inassm = 0; 5746 PetscBool flg = PETSC_FALSE; 5747 5748 PetscFunctionBegin; 5749 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5750 PetscValidType(mat, 1); 5751 5752 inassm++; 5753 MatAssemblyEnd_InUse++; 5754 if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */ 5755 PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0)); 5756 PetscTryTypeMethod(mat, assemblyend, type); 5757 PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0)); 5758 } else PetscTryTypeMethod(mat, assemblyend, type); 5759 5760 /* Flush assembly is not a true assembly */ 5761 if (type != MAT_FLUSH_ASSEMBLY) { 5762 if (mat->num_ass) { 5763 if (!mat->symmetry_eternal) { 5764 mat->symmetric = PETSC_BOOL3_UNKNOWN; 5765 mat->hermitian = PETSC_BOOL3_UNKNOWN; 5766 } 5767 if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN; 5768 if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN; 5769 } 5770 mat->num_ass++; 5771 mat->assembled = PETSC_TRUE; 5772 mat->ass_nonzerostate = mat->nonzerostate; 5773 } 5774 5775 mat->insertmode = NOT_SET_VALUES; 5776 MatAssemblyEnd_InUse--; 5777 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5778 if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) { 5779 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 5780 5781 if (mat->checksymmetryonassembly) { 5782 PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg)); 5783 if (flg) { 5784 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5785 } else { 5786 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5787 } 5788 } 5789 if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL)); 5790 } 5791 inassm--; 5792 PetscFunctionReturn(PETSC_SUCCESS); 5793 } 5794 5795 /*@ 5796 MatSetOption - Sets a parameter option for a matrix. Some options 5797 may be specific to certain storage formats. Some options 5798 determine how values will be inserted (or added). Sorted, 5799 row-oriented input will generally assemble the fastest. The default 5800 is row-oriented. 5801 5802 Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption` 5803 5804 Input Parameters: 5805 + mat - the matrix 5806 . option - the option, one of those listed below (and possibly others), 5807 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5808 5809 Options Describing Matrix Structure: 5810 + `MAT_SPD` - symmetric positive definite 5811 . `MAT_SYMMETRIC` - symmetric in terms of both structure and value 5812 . `MAT_HERMITIAN` - transpose is the complex conjugation 5813 . `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure 5814 . `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix 5815 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix 5816 - `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix 5817 5818 These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they 5819 do not need to be computed (usually at a high cost) 5820 5821 Options For Use with `MatSetValues()`: 5822 Insert a logically dense subblock, which can be 5823 . `MAT_ROW_ORIENTED` - row-oriented (default) 5824 5825 These options reflect the data you pass in with `MatSetValues()`; it has 5826 nothing to do with how the data is stored internally in the matrix 5827 data structure. 5828 5829 When (re)assembling a matrix, we can restrict the input for 5830 efficiency/debugging purposes. These options include 5831 + `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow) 5832 . `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated 5833 . `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries 5834 . `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry 5835 . `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly 5836 . `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if 5837 any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves 5838 performance for very large process counts. 5839 - `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset 5840 of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly 5841 functions, instead sending only neighbor messages. 5842 5843 Level: intermediate 5844 5845 Notes: 5846 Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg! 5847 5848 Some options are relevant only for particular matrix types and 5849 are thus ignored by others. Other options are not supported by 5850 certain matrix types and will generate an error message if set. 5851 5852 If using Fortran to compute a matrix, one may need to 5853 use the column-oriented option (or convert to the row-oriented 5854 format). 5855 5856 `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion 5857 that would generate a new entry in the nonzero structure is instead 5858 ignored. Thus, if memory has not already been allocated for this particular 5859 data, then the insertion is ignored. For dense matrices, in which 5860 the entire array is allocated, no entries are ever ignored. 5861 Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction 5862 5863 `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion 5864 that would generate a new entry in the nonzero structure instead produces 5865 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 5866 5867 `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion 5868 that would generate a new entry that has not been preallocated will 5869 instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats 5870 only.) This is a useful flag when debugging matrix memory preallocation. 5871 If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 5872 5873 `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for 5874 other processors should be dropped, rather than stashed. 5875 This is useful if you know that the "owning" processor is also 5876 always generating the correct matrix entries, so that PETSc need 5877 not transfer duplicate entries generated on another processor. 5878 5879 `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the 5880 searches during matrix assembly. When this flag is set, the hash table 5881 is created during the first matrix assembly. This hash table is 5882 used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()` 5883 to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag 5884 should be used with `MAT_USE_HASH_TABLE` flag. This option is currently 5885 supported by `MATMPIBAIJ` format only. 5886 5887 `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries 5888 are kept in the nonzero structure 5889 5890 `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating 5891 a zero location in the matrix 5892 5893 `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types 5894 5895 `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the 5896 zero row routines and thus improves performance for very large process counts. 5897 5898 `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular 5899 part of the matrix (since they should match the upper triangular part). 5900 5901 `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a 5902 single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common 5903 with finite difference schemes with non-periodic boundary conditions. 5904 5905 Developer Note: 5906 `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other 5907 places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRIC` or `MAT_SPD` would need to be changed back 5908 to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had 5909 not changed. 5910 5911 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()` 5912 @*/ 5913 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg) 5914 { 5915 PetscFunctionBegin; 5916 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5917 if (op > 0) { 5918 PetscValidLogicalCollectiveEnum(mat, op, 2); 5919 PetscValidLogicalCollectiveBool(mat, flg, 3); 5920 } 5921 5922 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); 5923 5924 switch (op) { 5925 case MAT_FORCE_DIAGONAL_ENTRIES: 5926 mat->force_diagonals = flg; 5927 PetscFunctionReturn(PETSC_SUCCESS); 5928 case MAT_NO_OFF_PROC_ENTRIES: 5929 mat->nooffprocentries = flg; 5930 PetscFunctionReturn(PETSC_SUCCESS); 5931 case MAT_SUBSET_OFF_PROC_ENTRIES: 5932 mat->assembly_subset = flg; 5933 if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */ 5934 #if !defined(PETSC_HAVE_MPIUNI) 5935 PetscCall(MatStashScatterDestroy_BTS(&mat->stash)); 5936 #endif 5937 mat->stash.first_assembly_done = PETSC_FALSE; 5938 } 5939 PetscFunctionReturn(PETSC_SUCCESS); 5940 case MAT_NO_OFF_PROC_ZERO_ROWS: 5941 mat->nooffproczerorows = flg; 5942 PetscFunctionReturn(PETSC_SUCCESS); 5943 case MAT_SPD: 5944 if (flg) { 5945 mat->spd = PETSC_BOOL3_TRUE; 5946 mat->symmetric = PETSC_BOOL3_TRUE; 5947 mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5948 } else { 5949 mat->spd = PETSC_BOOL3_FALSE; 5950 } 5951 break; 5952 case MAT_SYMMETRIC: 5953 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5954 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5955 #if !defined(PETSC_USE_COMPLEX) 5956 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5957 #endif 5958 break; 5959 case MAT_HERMITIAN: 5960 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5961 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5962 #if !defined(PETSC_USE_COMPLEX) 5963 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5964 #endif 5965 break; 5966 case MAT_STRUCTURALLY_SYMMETRIC: 5967 mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5968 break; 5969 case MAT_SYMMETRY_ETERNAL: 5970 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"); 5971 mat->symmetry_eternal = flg; 5972 if (flg) mat->structural_symmetry_eternal = PETSC_TRUE; 5973 break; 5974 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 5975 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"); 5976 mat->structural_symmetry_eternal = flg; 5977 break; 5978 case MAT_SPD_ETERNAL: 5979 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"); 5980 mat->spd_eternal = flg; 5981 if (flg) { 5982 mat->structural_symmetry_eternal = PETSC_TRUE; 5983 mat->symmetry_eternal = PETSC_TRUE; 5984 } 5985 break; 5986 case MAT_STRUCTURE_ONLY: 5987 mat->structure_only = flg; 5988 break; 5989 case MAT_SORTED_FULL: 5990 mat->sortedfull = flg; 5991 break; 5992 default: 5993 break; 5994 } 5995 PetscTryTypeMethod(mat, setoption, op, flg); 5996 PetscFunctionReturn(PETSC_SUCCESS); 5997 } 5998 5999 /*@ 6000 MatGetOption - Gets a parameter option that has been set for a matrix. 6001 6002 Logically Collective 6003 6004 Input Parameters: 6005 + mat - the matrix 6006 - option - the option, this only responds to certain options, check the code for which ones 6007 6008 Output Parameter: 6009 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 6010 6011 Level: intermediate 6012 6013 Notes: 6014 Can only be called after `MatSetSizes()` and `MatSetType()` have been set. 6015 6016 Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or 6017 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6018 6019 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, 6020 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6021 @*/ 6022 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg) 6023 { 6024 PetscFunctionBegin; 6025 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6026 PetscValidType(mat, 1); 6027 6028 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); 6029 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()"); 6030 6031 switch (op) { 6032 case MAT_NO_OFF_PROC_ENTRIES: 6033 *flg = mat->nooffprocentries; 6034 break; 6035 case MAT_NO_OFF_PROC_ZERO_ROWS: 6036 *flg = mat->nooffproczerorows; 6037 break; 6038 case MAT_SYMMETRIC: 6039 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()"); 6040 break; 6041 case MAT_HERMITIAN: 6042 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()"); 6043 break; 6044 case MAT_STRUCTURALLY_SYMMETRIC: 6045 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()"); 6046 break; 6047 case MAT_SPD: 6048 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()"); 6049 break; 6050 case MAT_SYMMETRY_ETERNAL: 6051 *flg = mat->symmetry_eternal; 6052 break; 6053 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6054 *flg = mat->symmetry_eternal; 6055 break; 6056 default: 6057 break; 6058 } 6059 PetscFunctionReturn(PETSC_SUCCESS); 6060 } 6061 6062 /*@ 6063 MatZeroEntries - Zeros all entries of a matrix. For sparse matrices 6064 this routine retains the old nonzero structure. 6065 6066 Logically Collective 6067 6068 Input Parameter: 6069 . mat - the matrix 6070 6071 Level: intermediate 6072 6073 Note: 6074 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. 6075 See the Performance chapter of the users manual for information on preallocating matrices. 6076 6077 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()` 6078 @*/ 6079 PetscErrorCode MatZeroEntries(Mat mat) 6080 { 6081 PetscFunctionBegin; 6082 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6083 PetscValidType(mat, 1); 6084 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6085 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"); 6086 MatCheckPreallocated(mat, 1); 6087 6088 PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0)); 6089 PetscUseTypeMethod(mat, zeroentries); 6090 PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0)); 6091 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6092 PetscFunctionReturn(PETSC_SUCCESS); 6093 } 6094 6095 /*@ 6096 MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal) 6097 of a set of rows and columns of a matrix. 6098 6099 Collective 6100 6101 Input Parameters: 6102 + mat - the matrix 6103 . numRows - the number of rows/columns to zero 6104 . rows - the global row indices 6105 . diag - value put in the diagonal of the eliminated rows 6106 . x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call 6107 - b - optional vector of the right hand side, that will be adjusted by provided solution entries 6108 6109 Level: intermediate 6110 6111 Notes: 6112 This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6113 6114 For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`. 6115 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 6116 6117 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6118 Krylov method to take advantage of the known solution on the zeroed rows. 6119 6120 For the parallel case, all processes that share the matrix (i.e., 6121 those in the communicator used for matrix creation) MUST call this 6122 routine, regardless of whether any rows being zeroed are owned by 6123 them. 6124 6125 Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix. 6126 6127 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6128 list only rows local to itself). 6129 6130 The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine. 6131 6132 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6133 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6134 @*/ 6135 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6136 { 6137 PetscFunctionBegin; 6138 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6139 PetscValidType(mat, 1); 6140 if (numRows) PetscValidIntPointer(rows, 3); 6141 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6142 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6143 MatCheckPreallocated(mat, 1); 6144 6145 PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b); 6146 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6147 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6148 PetscFunctionReturn(PETSC_SUCCESS); 6149 } 6150 6151 /*@ 6152 MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal) 6153 of a set of rows and columns of a matrix. 6154 6155 Collective 6156 6157 Input Parameters: 6158 + mat - the matrix 6159 . is - the rows to zero 6160 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6161 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6162 - b - optional vector of right hand side, that will be adjusted by provided solution 6163 6164 Level: intermediate 6165 6166 Note: 6167 See `MatZeroRowsColumns()` for details on how this routine operates. 6168 6169 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6170 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()` 6171 @*/ 6172 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6173 { 6174 PetscInt numRows; 6175 const PetscInt *rows; 6176 6177 PetscFunctionBegin; 6178 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6179 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6180 PetscValidType(mat, 1); 6181 PetscValidType(is, 2); 6182 PetscCall(ISGetLocalSize(is, &numRows)); 6183 PetscCall(ISGetIndices(is, &rows)); 6184 PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b)); 6185 PetscCall(ISRestoreIndices(is, &rows)); 6186 PetscFunctionReturn(PETSC_SUCCESS); 6187 } 6188 6189 /*@ 6190 MatZeroRows - Zeros all entries (except possibly the main diagonal) 6191 of a set of rows of a matrix. 6192 6193 Collective 6194 6195 Input Parameters: 6196 + mat - the matrix 6197 . numRows - the number of rows to zero 6198 . rows - the global row indices 6199 . diag - value put in the diagonal of the zeroed rows 6200 . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call 6201 - b - optional vector of right hand side, that will be adjusted by provided solution entries 6202 6203 Level: intermediate 6204 6205 Notes: 6206 This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6207 6208 For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`. 6209 6210 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6211 Krylov method to take advantage of the known solution on the zeroed rows. 6212 6213 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) 6214 from the matrix. 6215 6216 Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix 6217 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 6218 formats this does not alter the nonzero structure. 6219 6220 If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure 6221 of the matrix is not changed the values are 6222 merely zeroed. 6223 6224 The user can set a value in the diagonal entry (or for the `MATAIJ` format 6225 formats can optionally remove the main diagonal entry from the 6226 nonzero structure as well, by passing 0.0 as the final argument). 6227 6228 For the parallel case, all processes that share the matrix (i.e., 6229 those in the communicator used for matrix creation) MUST call this 6230 routine, regardless of whether any rows being zeroed are owned by 6231 them. 6232 6233 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6234 list only rows local to itself). 6235 6236 You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it 6237 owns that are to be zeroed. This saves a global synchronization in the implementation. 6238 6239 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6240 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE` 6241 @*/ 6242 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6243 { 6244 PetscFunctionBegin; 6245 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6246 PetscValidType(mat, 1); 6247 if (numRows) PetscValidIntPointer(rows, 3); 6248 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6249 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6250 MatCheckPreallocated(mat, 1); 6251 6252 PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b); 6253 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6254 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6255 PetscFunctionReturn(PETSC_SUCCESS); 6256 } 6257 6258 /*@ 6259 MatZeroRowsIS - Zeros all entries (except possibly the main diagonal) 6260 of a set of rows of a matrix. 6261 6262 Collective 6263 6264 Input Parameters: 6265 + mat - the matrix 6266 . is - index set of rows to remove (if `NULL` then no row is removed) 6267 . diag - value put in all diagonals of eliminated rows 6268 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6269 - b - optional vector of right hand side, that will be adjusted by provided solution 6270 6271 Level: intermediate 6272 6273 Note: 6274 See `MatZeroRows()` for details on how this routine operates. 6275 6276 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6277 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6278 @*/ 6279 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6280 { 6281 PetscInt numRows = 0; 6282 const PetscInt *rows = NULL; 6283 6284 PetscFunctionBegin; 6285 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6286 PetscValidType(mat, 1); 6287 if (is) { 6288 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6289 PetscCall(ISGetLocalSize(is, &numRows)); 6290 PetscCall(ISGetIndices(is, &rows)); 6291 } 6292 PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b)); 6293 if (is) PetscCall(ISRestoreIndices(is, &rows)); 6294 PetscFunctionReturn(PETSC_SUCCESS); 6295 } 6296 6297 /*@ 6298 MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal) 6299 of a set of rows of a matrix. These rows must be local to the process. 6300 6301 Collective 6302 6303 Input Parameters: 6304 + mat - the matrix 6305 . numRows - the number of rows to remove 6306 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6307 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6308 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6309 - b - optional vector of right hand side, that will be adjusted by provided solution 6310 6311 Level: intermediate 6312 6313 Notes: 6314 See `MatZeroRows()` for details on how this routine operates. 6315 6316 The grid coordinates are across the entire grid, not just the local portion 6317 6318 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6319 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6320 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6321 `DM_BOUNDARY_PERIODIC` boundary type. 6322 6323 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 6324 a single value per point) you can skip filling those indices. 6325 6326 Fortran Note: 6327 `idxm` and `idxn` should be declared as 6328 $ MatStencil idxm(4, m) 6329 and the values inserted using 6330 .vb 6331 idxm(MatStencil_i, 1) = i 6332 idxm(MatStencil_j, 1) = j 6333 idxm(MatStencil_k, 1) = k 6334 idxm(MatStencil_c, 1) = c 6335 etc 6336 .ve 6337 6338 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6339 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6340 @*/ 6341 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6342 { 6343 PetscInt dim = mat->stencil.dim; 6344 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6345 PetscInt *dims = mat->stencil.dims + 1; 6346 PetscInt *starts = mat->stencil.starts; 6347 PetscInt *dxm = (PetscInt *)rows; 6348 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6349 6350 PetscFunctionBegin; 6351 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6352 PetscValidType(mat, 1); 6353 if (numRows) PetscValidPointer(rows, 3); 6354 6355 PetscCall(PetscMalloc1(numRows, &jdxm)); 6356 for (i = 0; i < numRows; ++i) { 6357 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6358 for (j = 0; j < 3 - sdim; ++j) dxm++; 6359 /* Local index in X dir */ 6360 tmp = *dxm++ - starts[0]; 6361 /* Loop over remaining dimensions */ 6362 for (j = 0; j < dim - 1; ++j) { 6363 /* If nonlocal, set index to be negative */ 6364 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6365 /* Update local index */ 6366 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6367 } 6368 /* Skip component slot if necessary */ 6369 if (mat->stencil.noc) dxm++; 6370 /* Local row number */ 6371 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6372 } 6373 PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b)); 6374 PetscCall(PetscFree(jdxm)); 6375 PetscFunctionReturn(PETSC_SUCCESS); 6376 } 6377 6378 /*@ 6379 MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal) 6380 of a set of rows and columns of a matrix. 6381 6382 Collective 6383 6384 Input Parameters: 6385 + mat - the matrix 6386 . numRows - the number of rows/columns to remove 6387 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6388 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6389 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6390 - b - optional vector of right hand side, that will be adjusted by provided solution 6391 6392 Level: intermediate 6393 6394 Notes: 6395 See `MatZeroRowsColumns()` for details on how this routine operates. 6396 6397 The grid coordinates are across the entire grid, not just the local portion 6398 6399 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6400 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6401 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6402 `DM_BOUNDARY_PERIODIC` boundary type. 6403 6404 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 6405 a single value per point) you can skip filling those indices. 6406 6407 Fortran Note: 6408 `idxm` and `idxn` should be declared as 6409 $ MatStencil idxm(4, m) 6410 and the values inserted using 6411 .vb 6412 idxm(MatStencil_i, 1) = i 6413 idxm(MatStencil_j, 1) = j 6414 idxm(MatStencil_k, 1) = k 6415 idxm(MatStencil_c, 1) = c 6416 etc 6417 .ve 6418 6419 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6420 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()` 6421 @*/ 6422 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6423 { 6424 PetscInt dim = mat->stencil.dim; 6425 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6426 PetscInt *dims = mat->stencil.dims + 1; 6427 PetscInt *starts = mat->stencil.starts; 6428 PetscInt *dxm = (PetscInt *)rows; 6429 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6430 6431 PetscFunctionBegin; 6432 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6433 PetscValidType(mat, 1); 6434 if (numRows) PetscValidPointer(rows, 3); 6435 6436 PetscCall(PetscMalloc1(numRows, &jdxm)); 6437 for (i = 0; i < numRows; ++i) { 6438 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6439 for (j = 0; j < 3 - sdim; ++j) dxm++; 6440 /* Local index in X dir */ 6441 tmp = *dxm++ - starts[0]; 6442 /* Loop over remaining dimensions */ 6443 for (j = 0; j < dim - 1; ++j) { 6444 /* If nonlocal, set index to be negative */ 6445 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6446 /* Update local index */ 6447 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6448 } 6449 /* Skip component slot if necessary */ 6450 if (mat->stencil.noc) dxm++; 6451 /* Local row number */ 6452 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6453 } 6454 PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b)); 6455 PetscCall(PetscFree(jdxm)); 6456 PetscFunctionReturn(PETSC_SUCCESS); 6457 } 6458 6459 /*@C 6460 MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal) 6461 of a set of rows of a matrix; using local numbering of rows. 6462 6463 Collective 6464 6465 Input Parameters: 6466 + mat - the matrix 6467 . numRows - the number of rows to remove 6468 . rows - the local row indices 6469 . diag - value put in all diagonals of eliminated rows 6470 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6471 - b - optional vector of right hand side, that will be adjusted by provided solution 6472 6473 Level: intermediate 6474 6475 Notes: 6476 Before calling `MatZeroRowsLocal()`, the user must first set the 6477 local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`. 6478 6479 See `MatZeroRows()` for details on how this routine operates. 6480 6481 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`, 6482 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6483 @*/ 6484 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6485 { 6486 PetscFunctionBegin; 6487 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6488 PetscValidType(mat, 1); 6489 if (numRows) PetscValidIntPointer(rows, 3); 6490 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6491 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6492 MatCheckPreallocated(mat, 1); 6493 6494 if (mat->ops->zerorowslocal) { 6495 PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b); 6496 } else { 6497 IS is, newis; 6498 const PetscInt *newRows; 6499 6500 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6501 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6502 PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis)); 6503 PetscCall(ISGetIndices(newis, &newRows)); 6504 PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b); 6505 PetscCall(ISRestoreIndices(newis, &newRows)); 6506 PetscCall(ISDestroy(&newis)); 6507 PetscCall(ISDestroy(&is)); 6508 } 6509 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6510 PetscFunctionReturn(PETSC_SUCCESS); 6511 } 6512 6513 /*@ 6514 MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal) 6515 of a set of rows of a matrix; using local numbering of rows. 6516 6517 Collective 6518 6519 Input Parameters: 6520 + mat - the matrix 6521 . is - index set of rows to remove 6522 . diag - value put in all diagonals of eliminated rows 6523 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6524 - b - optional vector of right hand side, that will be adjusted by provided solution 6525 6526 Level: intermediate 6527 6528 Notes: 6529 Before calling `MatZeroRowsLocalIS()`, the user must first set the 6530 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6531 6532 See `MatZeroRows()` for details on how this routine operates. 6533 6534 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6535 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6536 @*/ 6537 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6538 { 6539 PetscInt numRows; 6540 const PetscInt *rows; 6541 6542 PetscFunctionBegin; 6543 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6544 PetscValidType(mat, 1); 6545 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6546 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6547 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6548 MatCheckPreallocated(mat, 1); 6549 6550 PetscCall(ISGetLocalSize(is, &numRows)); 6551 PetscCall(ISGetIndices(is, &rows)); 6552 PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b)); 6553 PetscCall(ISRestoreIndices(is, &rows)); 6554 PetscFunctionReturn(PETSC_SUCCESS); 6555 } 6556 6557 /*@ 6558 MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal) 6559 of a set of rows and columns of a matrix; using local numbering of rows. 6560 6561 Collective 6562 6563 Input Parameters: 6564 + mat - the matrix 6565 . numRows - the number of rows to remove 6566 . rows - the global row indices 6567 . diag - value put in all diagonals of eliminated rows 6568 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6569 - b - optional vector of right hand side, that will be adjusted by provided solution 6570 6571 Level: intermediate 6572 6573 Notes: 6574 Before calling `MatZeroRowsColumnsLocal()`, the user must first set the 6575 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6576 6577 See `MatZeroRowsColumns()` for details on how this routine operates. 6578 6579 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6580 `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6581 @*/ 6582 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6583 { 6584 IS is, newis; 6585 const PetscInt *newRows; 6586 6587 PetscFunctionBegin; 6588 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6589 PetscValidType(mat, 1); 6590 if (numRows) PetscValidIntPointer(rows, 3); 6591 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6592 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6593 MatCheckPreallocated(mat, 1); 6594 6595 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6596 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6597 PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis)); 6598 PetscCall(ISGetIndices(newis, &newRows)); 6599 PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b); 6600 PetscCall(ISRestoreIndices(newis, &newRows)); 6601 PetscCall(ISDestroy(&newis)); 6602 PetscCall(ISDestroy(&is)); 6603 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6604 PetscFunctionReturn(PETSC_SUCCESS); 6605 } 6606 6607 /*@ 6608 MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal) 6609 of a set of rows and columns of a matrix; using local numbering of rows. 6610 6611 Collective 6612 6613 Input Parameters: 6614 + mat - the matrix 6615 . is - index set of rows to remove 6616 . diag - value put in all diagonals of eliminated rows 6617 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6618 - b - optional vector of right hand side, that will be adjusted by provided solution 6619 6620 Level: intermediate 6621 6622 Notes: 6623 Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the 6624 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6625 6626 See `MatZeroRowsColumns()` for details on how this routine operates. 6627 6628 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6629 `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6630 @*/ 6631 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6632 { 6633 PetscInt numRows; 6634 const PetscInt *rows; 6635 6636 PetscFunctionBegin; 6637 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6638 PetscValidType(mat, 1); 6639 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6640 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6641 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6642 MatCheckPreallocated(mat, 1); 6643 6644 PetscCall(ISGetLocalSize(is, &numRows)); 6645 PetscCall(ISGetIndices(is, &rows)); 6646 PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b)); 6647 PetscCall(ISRestoreIndices(is, &rows)); 6648 PetscFunctionReturn(PETSC_SUCCESS); 6649 } 6650 6651 /*@C 6652 MatGetSize - Returns the numbers of rows and columns in a matrix. 6653 6654 Not Collective 6655 6656 Input Parameter: 6657 . mat - the matrix 6658 6659 Output Parameters: 6660 + m - the number of global rows 6661 - n - the number of global columns 6662 6663 Level: beginner 6664 6665 Note: 6666 Both output parameters can be `NULL` on input. 6667 6668 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()` 6669 @*/ 6670 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n) 6671 { 6672 PetscFunctionBegin; 6673 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6674 if (m) *m = mat->rmap->N; 6675 if (n) *n = mat->cmap->N; 6676 PetscFunctionReturn(PETSC_SUCCESS); 6677 } 6678 6679 /*@C 6680 MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns 6681 of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`. 6682 6683 Not Collective 6684 6685 Input Parameter: 6686 . mat - the matrix 6687 6688 Output Parameters: 6689 + m - the number of local rows, use `NULL` to not obtain this value 6690 - n - the number of local columns, use `NULL` to not obtain this value 6691 6692 Level: beginner 6693 6694 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()` 6695 @*/ 6696 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n) 6697 { 6698 PetscFunctionBegin; 6699 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6700 if (m) PetscValidIntPointer(m, 2); 6701 if (n) PetscValidIntPointer(n, 3); 6702 if (m) *m = mat->rmap->n; 6703 if (n) *n = mat->cmap->n; 6704 PetscFunctionReturn(PETSC_SUCCESS); 6705 } 6706 6707 /*@C 6708 MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by 6709 this processor. (The columns of the "diagonal block" for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts. 6710 6711 Not Collective, unless matrix has not been allocated, then collective 6712 6713 Input Parameter: 6714 . mat - the matrix 6715 6716 Output Parameters: 6717 + m - the global index of the first local column, use `NULL` to not obtain this value 6718 - n - one more than the global index of the last local column, use `NULL` to not obtain this value 6719 6720 Level: developer 6721 6722 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout` 6723 @*/ 6724 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n) 6725 { 6726 PetscFunctionBegin; 6727 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6728 PetscValidType(mat, 1); 6729 if (m) PetscValidIntPointer(m, 2); 6730 if (n) PetscValidIntPointer(n, 3); 6731 MatCheckPreallocated(mat, 1); 6732 if (m) *m = mat->cmap->rstart; 6733 if (n) *n = mat->cmap->rend; 6734 PetscFunctionReturn(PETSC_SUCCESS); 6735 } 6736 6737 /*@C 6738 MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6739 this MPI process. For all matrices it returns the range of matrix rows associated with rows of a vector that would contain the result of a matrix 6740 vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts 6741 6742 Not Collective 6743 6744 Input Parameter: 6745 . mat - the matrix 6746 6747 Output Parameters: 6748 + m - the global index of the first local row, use `NULL` to not obtain this value 6749 - n - one more than the global index of the last local row, use `NULL` to not obtain this value 6750 6751 Level: beginner 6752 6753 Note: 6754 This function requires that the matrix be preallocated. If you have not preallocated, consider using 6755 `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N) 6756 and then `MPI_Scan()` to calculate prefix sums of the local sizes. 6757 6758 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, 6759 `PetscLayout` 6760 @*/ 6761 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n) 6762 { 6763 PetscFunctionBegin; 6764 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6765 PetscValidType(mat, 1); 6766 if (m) PetscValidIntPointer(m, 2); 6767 if (n) PetscValidIntPointer(n, 3); 6768 MatCheckPreallocated(mat, 1); 6769 if (m) *m = mat->rmap->rstart; 6770 if (n) *n = mat->rmap->rend; 6771 PetscFunctionReturn(PETSC_SUCCESS); 6772 } 6773 6774 /*@C 6775 MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6776 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 6777 vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts 6778 6779 Not Collective, unless matrix has not been allocated 6780 6781 Input Parameter: 6782 . mat - the matrix 6783 6784 Output Parameter: 6785 . ranges - start of each processors portion plus one more than the total length at the end 6786 6787 Level: beginner 6788 6789 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout` 6790 @*/ 6791 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges) 6792 { 6793 PetscFunctionBegin; 6794 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6795 PetscValidType(mat, 1); 6796 MatCheckPreallocated(mat, 1); 6797 PetscCall(PetscLayoutGetRanges(mat->rmap, ranges)); 6798 PetscFunctionReturn(PETSC_SUCCESS); 6799 } 6800 6801 /*@C 6802 MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by 6803 each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts. 6804 6805 Not Collective, unless matrix has not been allocated 6806 6807 Input Parameter: 6808 . mat - the matrix 6809 6810 Output Parameter: 6811 . ranges - start of each processors portion plus one more then the total length at the end 6812 6813 Level: beginner 6814 6815 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()` 6816 @*/ 6817 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges) 6818 { 6819 PetscFunctionBegin; 6820 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6821 PetscValidType(mat, 1); 6822 MatCheckPreallocated(mat, 1); 6823 PetscCall(PetscLayoutGetRanges(mat->cmap, ranges)); 6824 PetscFunctionReturn(PETSC_SUCCESS); 6825 } 6826 6827 /*@C 6828 MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this 6829 corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership 6830 is more complicated. See :any:`<sec_matlayout>` for details on matrix layouts. 6831 6832 Not Collective 6833 6834 Input Parameter: 6835 . A - matrix 6836 6837 Output Parameters: 6838 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value 6839 - cols - columns in which this process owns elements, use `NULL` to not obtain this value 6840 6841 Level: intermediate 6842 6843 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK`` 6844 @*/ 6845 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols) 6846 { 6847 PetscErrorCode (*f)(Mat, IS *, IS *); 6848 6849 PetscFunctionBegin; 6850 MatCheckPreallocated(A, 1); 6851 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f)); 6852 if (f) { 6853 PetscCall((*f)(A, rows, cols)); 6854 } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */ 6855 if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows)); 6856 if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols)); 6857 } 6858 PetscFunctionReturn(PETSC_SUCCESS); 6859 } 6860 6861 /*@C 6862 MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()` 6863 Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()` 6864 to complete the factorization. 6865 6866 Collective 6867 6868 Input Parameters: 6869 + fact - the factorized matrix obtained with `MatGetFactor()` 6870 . mat - the matrix 6871 . row - row permutation 6872 . col - column permutation 6873 - info - structure containing 6874 .vb 6875 levels - number of levels of fill. 6876 expected fill - as ratio of original fill. 6877 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 6878 missing diagonal entries) 6879 .ve 6880 6881 Level: developer 6882 6883 Notes: 6884 See [Matrix Factorization](sec_matfactor) for additional information. 6885 6886 Most users should employ the `KSP` interface for linear solvers 6887 instead of working directly with matrix algebra routines such as this. 6888 See, e.g., `KSPCreate()`. 6889 6890 Uses the definition of level of fill as in Y. Saad, 2003 6891 6892 Developer Note: 6893 The Fortran interface is not autogenerated as the 6894 interface definition cannot be generated correctly [due to `MatFactorInfo`] 6895 6896 References: 6897 . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003 6898 6899 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 6900 `MatGetOrdering()`, `MatFactorInfo` 6901 @*/ 6902 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 6903 { 6904 PetscFunctionBegin; 6905 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 6906 PetscValidType(mat, 2); 6907 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 6908 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 6909 PetscValidPointer(info, 5); 6910 PetscValidPointer(fact, 1); 6911 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels); 6912 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 6913 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6914 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6915 MatCheckPreallocated(mat, 2); 6916 6917 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0)); 6918 PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info); 6919 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0)); 6920 PetscFunctionReturn(PETSC_SUCCESS); 6921 } 6922 6923 /*@C 6924 MatICCFactorSymbolic - Performs symbolic incomplete 6925 Cholesky factorization for a symmetric matrix. Use 6926 `MatCholeskyFactorNumeric()` to complete the factorization. 6927 6928 Collective 6929 6930 Input Parameters: 6931 + fact - the factorized matrix obtained with `MatGetFactor()` 6932 . mat - the matrix to be factored 6933 . perm - row and column permutation 6934 - info - structure containing 6935 .vb 6936 levels - number of levels of fill. 6937 expected fill - as ratio of original fill. 6938 .ve 6939 6940 Level: developer 6941 6942 Notes: 6943 Most users should employ the `KSP` interface for linear solvers 6944 instead of working directly with matrix algebra routines such as this. 6945 See, e.g., `KSPCreate()`. 6946 6947 This uses the definition of level of fill as in Y. Saad, 2003 6948 6949 Developer Note: 6950 The Fortran interface is not autogenerated as the 6951 interface definition cannot be generated correctly [due to `MatFactorInfo`] 6952 6953 References: 6954 . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003 6955 6956 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 6957 @*/ 6958 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 6959 { 6960 PetscFunctionBegin; 6961 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 6962 PetscValidType(mat, 2); 6963 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 6964 PetscValidPointer(info, 4); 6965 PetscValidPointer(fact, 1); 6966 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6967 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels); 6968 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 6969 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6970 MatCheckPreallocated(mat, 2); 6971 6972 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 6973 PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info); 6974 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 6975 PetscFunctionReturn(PETSC_SUCCESS); 6976 } 6977 6978 /*@C 6979 MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat 6980 points to an array of valid matrices, they may be reused to store the new 6981 submatrices. 6982 6983 Collective 6984 6985 Input Parameters: 6986 + mat - the matrix 6987 . n - the number of submatrixes to be extracted (on this processor, may be zero) 6988 . irow - index set of rows to extract 6989 . icol - index set of columns to extract 6990 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 6991 6992 Output Parameter: 6993 . submat - the array of submatrices 6994 6995 Level: advanced 6996 6997 Notes: 6998 `MatCreateSubMatrices()` can extract ONLY sequential submatrices 6999 (from both sequential and parallel matrices). Use `MatCreateSubMatrix()` 7000 to extract a parallel submatrix. 7001 7002 Some matrix types place restrictions on the row and column 7003 indices, such as that they be sorted or that they be equal to each other. 7004 7005 The index sets may not have duplicate entries. 7006 7007 When extracting submatrices from a parallel matrix, each processor can 7008 form a different submatrix by setting the rows and columns of its 7009 individual index sets according to the local submatrix desired. 7010 7011 When finished using the submatrices, the user should destroy 7012 them with `MatDestroySubMatrices()`. 7013 7014 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 7015 original matrix has not changed from that last call to `MatCreateSubMatrices()`. 7016 7017 This routine creates the matrices in submat; you should NOT create them before 7018 calling it. It also allocates the array of matrix pointers submat. 7019 7020 For `MATBAIJ` matrices the index sets must respect the block structure, that is if they 7021 request one row/column in a block, they must request all rows/columns that are in 7022 that block. For example, if the block size is 2 you cannot request just row 0 and 7023 column 0. 7024 7025 Fortran Note: 7026 The Fortran interface is slightly different from that given below; it 7027 requires one to pass in as `submat` a `Mat` (integer) array of size at least n+1. 7028 7029 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7030 @*/ 7031 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7032 { 7033 PetscInt i; 7034 PetscBool eq; 7035 7036 PetscFunctionBegin; 7037 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7038 PetscValidType(mat, 1); 7039 if (n) { 7040 PetscValidPointer(irow, 3); 7041 for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3); 7042 PetscValidPointer(icol, 4); 7043 for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4); 7044 } 7045 PetscValidPointer(submat, 6); 7046 if (n && scall == MAT_REUSE_MATRIX) { 7047 PetscValidPointer(*submat, 6); 7048 for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6); 7049 } 7050 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7051 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7052 MatCheckPreallocated(mat, 1); 7053 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7054 PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat); 7055 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7056 for (i = 0; i < n; i++) { 7057 (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */ 7058 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7059 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7060 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 7061 if (mat->boundtocpu && mat->bindingpropagates) { 7062 PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE)); 7063 PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE)); 7064 } 7065 #endif 7066 } 7067 PetscFunctionReturn(PETSC_SUCCESS); 7068 } 7069 7070 /*@C 7071 MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms). 7072 7073 Collective 7074 7075 Input Parameters: 7076 + mat - the matrix 7077 . n - the number of submatrixes to be extracted 7078 . irow - index set of rows to extract 7079 . icol - index set of columns to extract 7080 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7081 7082 Output Parameter: 7083 . submat - the array of submatrices 7084 7085 Level: advanced 7086 7087 Note: 7088 This is used by `PCGASM` 7089 7090 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7091 @*/ 7092 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7093 { 7094 PetscInt i; 7095 PetscBool eq; 7096 7097 PetscFunctionBegin; 7098 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7099 PetscValidType(mat, 1); 7100 if (n) { 7101 PetscValidPointer(irow, 3); 7102 PetscValidHeaderSpecific(*irow, IS_CLASSID, 3); 7103 PetscValidPointer(icol, 4); 7104 PetscValidHeaderSpecific(*icol, IS_CLASSID, 4); 7105 } 7106 PetscValidPointer(submat, 6); 7107 if (n && scall == MAT_REUSE_MATRIX) { 7108 PetscValidPointer(*submat, 6); 7109 PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6); 7110 } 7111 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7112 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7113 MatCheckPreallocated(mat, 1); 7114 7115 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7116 PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat); 7117 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7118 for (i = 0; i < n; i++) { 7119 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7120 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7121 } 7122 PetscFunctionReturn(PETSC_SUCCESS); 7123 } 7124 7125 /*@C 7126 MatDestroyMatrices - Destroys an array of matrices. 7127 7128 Collective 7129 7130 Input Parameters: 7131 + n - the number of local matrices 7132 - mat - the matrices (this is a pointer to the array of matrices) 7133 7134 Level: advanced 7135 7136 Note: 7137 Frees not only the matrices, but also the array that contains the matrices 7138 7139 Fortran Note: 7140 This does not free the array. 7141 7142 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()` 7143 @*/ 7144 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[]) 7145 { 7146 PetscInt i; 7147 7148 PetscFunctionBegin; 7149 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7150 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7151 PetscValidPointer(mat, 2); 7152 7153 for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i])); 7154 7155 /* memory is allocated even if n = 0 */ 7156 PetscCall(PetscFree(*mat)); 7157 PetscFunctionReturn(PETSC_SUCCESS); 7158 } 7159 7160 /*@C 7161 MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`. 7162 7163 Collective 7164 7165 Input Parameters: 7166 + n - the number of local matrices 7167 - mat - the matrices (this is a pointer to the array of matrices, just to match the calling 7168 sequence of `MatCreateSubMatrices()`) 7169 7170 Level: advanced 7171 7172 Note: 7173 Frees not only the matrices, but also the array that contains the matrices 7174 7175 Fortran Note: 7176 This does not free the array. 7177 7178 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7179 @*/ 7180 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[]) 7181 { 7182 Mat mat0; 7183 7184 PetscFunctionBegin; 7185 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7186 /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */ 7187 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7188 PetscValidPointer(mat, 2); 7189 7190 mat0 = (*mat)[0]; 7191 if (mat0 && mat0->ops->destroysubmatrices) { 7192 PetscCall((*mat0->ops->destroysubmatrices)(n, mat)); 7193 } else { 7194 PetscCall(MatDestroyMatrices(n, mat)); 7195 } 7196 PetscFunctionReturn(PETSC_SUCCESS); 7197 } 7198 7199 /*@C 7200 MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process 7201 7202 Collective 7203 7204 Input Parameter: 7205 . mat - the matrix 7206 7207 Output Parameter: 7208 . matstruct - the sequential matrix with the nonzero structure of mat 7209 7210 Level: developer 7211 7212 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7213 @*/ 7214 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct) 7215 { 7216 PetscFunctionBegin; 7217 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7218 PetscValidPointer(matstruct, 2); 7219 7220 PetscValidType(mat, 1); 7221 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7222 MatCheckPreallocated(mat, 1); 7223 7224 PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7225 PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct); 7226 PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7227 PetscFunctionReturn(PETSC_SUCCESS); 7228 } 7229 7230 /*@C 7231 MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`. 7232 7233 Collective 7234 7235 Input Parameter: 7236 . mat - the matrix (this is a pointer to the array of matrices, just to match the calling 7237 sequence of `MatGetSeqNonzeroStructure()`) 7238 7239 Level: advanced 7240 7241 Note: 7242 Frees not only the matrices, but also the array that contains the matrices 7243 7244 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()` 7245 @*/ 7246 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat) 7247 { 7248 PetscFunctionBegin; 7249 PetscValidPointer(mat, 1); 7250 PetscCall(MatDestroy(mat)); 7251 PetscFunctionReturn(PETSC_SUCCESS); 7252 } 7253 7254 /*@ 7255 MatIncreaseOverlap - Given a set of submatrices indicated by index sets, 7256 replaces the index sets by larger ones that represent submatrices with 7257 additional overlap. 7258 7259 Collective 7260 7261 Input Parameters: 7262 + mat - the matrix 7263 . n - the number of index sets 7264 . is - the array of index sets (these index sets will changed during the call) 7265 - ov - the additional overlap requested 7266 7267 Options Database Key: 7268 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7269 7270 Level: developer 7271 7272 Note: 7273 The computed overlap preserves the matrix block sizes when the blocks are square. 7274 That is: if a matrix nonzero for a given block would increase the overlap all columns associated with 7275 that block are included in the overlap regardless of whether each specific column would increase the overlap. 7276 7277 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()` 7278 @*/ 7279 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov) 7280 { 7281 PetscInt i, bs, cbs; 7282 7283 PetscFunctionBegin; 7284 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7285 PetscValidType(mat, 1); 7286 PetscValidLogicalCollectiveInt(mat, n, 2); 7287 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7288 if (n) { 7289 PetscValidPointer(is, 3); 7290 for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3); 7291 } 7292 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7293 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7294 MatCheckPreallocated(mat, 1); 7295 7296 if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS); 7297 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7298 PetscUseTypeMethod(mat, increaseoverlap, n, is, ov); 7299 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7300 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 7301 if (bs == cbs) { 7302 for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs)); 7303 } 7304 PetscFunctionReturn(PETSC_SUCCESS); 7305 } 7306 7307 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt); 7308 7309 /*@ 7310 MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across 7311 a sub communicator, replaces the index sets by larger ones that represent submatrices with 7312 additional overlap. 7313 7314 Collective 7315 7316 Input Parameters: 7317 + mat - the matrix 7318 . n - the number of index sets 7319 . is - the array of index sets (these index sets will changed during the call) 7320 - ov - the additional overlap requested 7321 7322 ` Options Database Key: 7323 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7324 7325 Level: developer 7326 7327 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()` 7328 @*/ 7329 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov) 7330 { 7331 PetscInt i; 7332 7333 PetscFunctionBegin; 7334 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7335 PetscValidType(mat, 1); 7336 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7337 if (n) { 7338 PetscValidPointer(is, 3); 7339 PetscValidHeaderSpecific(*is, IS_CLASSID, 3); 7340 } 7341 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7342 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7343 MatCheckPreallocated(mat, 1); 7344 if (!ov) PetscFunctionReturn(PETSC_SUCCESS); 7345 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7346 for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov)); 7347 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7348 PetscFunctionReturn(PETSC_SUCCESS); 7349 } 7350 7351 /*@ 7352 MatGetBlockSize - Returns the matrix block size. 7353 7354 Not Collective 7355 7356 Input Parameter: 7357 . mat - the matrix 7358 7359 Output Parameter: 7360 . bs - block size 7361 7362 Level: intermediate 7363 7364 Notes: 7365 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7366 7367 If the block size has not been set yet this routine returns 1. 7368 7369 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()` 7370 @*/ 7371 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs) 7372 { 7373 PetscFunctionBegin; 7374 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7375 PetscValidIntPointer(bs, 2); 7376 *bs = PetscAbs(mat->rmap->bs); 7377 PetscFunctionReturn(PETSC_SUCCESS); 7378 } 7379 7380 /*@ 7381 MatGetBlockSizes - Returns the matrix block row and column sizes. 7382 7383 Not Collective 7384 7385 Input Parameter: 7386 . mat - the matrix 7387 7388 Output Parameters: 7389 + rbs - row block size 7390 - cbs - column block size 7391 7392 Level: intermediate 7393 7394 Notes: 7395 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7396 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7397 7398 If a block size has not been set yet this routine returns 1. 7399 7400 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()` 7401 @*/ 7402 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs) 7403 { 7404 PetscFunctionBegin; 7405 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7406 if (rbs) PetscValidIntPointer(rbs, 2); 7407 if (cbs) PetscValidIntPointer(cbs, 3); 7408 if (rbs) *rbs = PetscAbs(mat->rmap->bs); 7409 if (cbs) *cbs = PetscAbs(mat->cmap->bs); 7410 PetscFunctionReturn(PETSC_SUCCESS); 7411 } 7412 7413 /*@ 7414 MatSetBlockSize - Sets the matrix block size. 7415 7416 Logically Collective 7417 7418 Input Parameters: 7419 + mat - the matrix 7420 - bs - block size 7421 7422 Level: intermediate 7423 7424 Notes: 7425 Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix. 7426 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7427 7428 For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size 7429 is compatible with the matrix local sizes. 7430 7431 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()` 7432 @*/ 7433 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs) 7434 { 7435 PetscFunctionBegin; 7436 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7437 PetscValidLogicalCollectiveInt(mat, bs, 2); 7438 PetscCall(MatSetBlockSizes(mat, bs, bs)); 7439 PetscFunctionReturn(PETSC_SUCCESS); 7440 } 7441 7442 typedef struct { 7443 PetscInt n; 7444 IS *is; 7445 Mat *mat; 7446 PetscObjectState nonzerostate; 7447 Mat C; 7448 } EnvelopeData; 7449 7450 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata) 7451 { 7452 for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i])); 7453 PetscCall(PetscFree(edata->is)); 7454 PetscCall(PetscFree(edata)); 7455 return PETSC_SUCCESS; 7456 } 7457 7458 /* 7459 MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores 7460 the sizes of these blocks in the matrix. An individual block may lie over several processes. 7461 7462 Collective 7463 7464 Input Parameter: 7465 . mat - the matrix 7466 7467 Notes: 7468 There can be zeros within the blocks 7469 7470 The blocks can overlap between processes, including laying on more than two processes 7471 7472 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()` 7473 */ 7474 static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat) 7475 { 7476 PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend; 7477 PetscInt *diag, *odiag, sc; 7478 VecScatter scatter; 7479 PetscScalar *seqv; 7480 const PetscScalar *parv; 7481 const PetscInt *ia, *ja; 7482 PetscBool set, flag, done; 7483 Mat AA = mat, A; 7484 MPI_Comm comm; 7485 PetscMPIInt rank, size, tag; 7486 MPI_Status status; 7487 PetscContainer container; 7488 EnvelopeData *edata; 7489 Vec seq, par; 7490 IS isglobal; 7491 7492 PetscFunctionBegin; 7493 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7494 PetscCall(MatIsSymmetricKnown(mat, &set, &flag)); 7495 if (!set || !flag) { 7496 /* TOO: only needs nonzero structure of transpose */ 7497 PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA)); 7498 PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN)); 7499 } 7500 PetscCall(MatAIJGetLocalMat(AA, &A)); 7501 PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7502 PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix"); 7503 7504 PetscCall(MatGetLocalSize(mat, &n, NULL)); 7505 PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag)); 7506 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 7507 PetscCallMPI(MPI_Comm_size(comm, &size)); 7508 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7509 7510 PetscCall(PetscMalloc2(n, &sizes, n, &starts)); 7511 7512 if (rank > 0) { 7513 PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7514 PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7515 } 7516 PetscCall(MatGetOwnershipRange(mat, &rstart, NULL)); 7517 for (i = 0; i < n; i++) { 7518 env = PetscMax(env, ja[ia[i + 1] - 1]); 7519 II = rstart + i; 7520 if (env == II) { 7521 starts[lblocks] = tbs; 7522 sizes[lblocks++] = 1 + II - tbs; 7523 tbs = 1 + II; 7524 } 7525 } 7526 if (rank < size - 1) { 7527 PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm)); 7528 PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm)); 7529 } 7530 7531 PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7532 if (!set || !flag) PetscCall(MatDestroy(&AA)); 7533 PetscCall(MatDestroy(&A)); 7534 7535 PetscCall(PetscNew(&edata)); 7536 PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate)); 7537 edata->n = lblocks; 7538 /* create IS needed for extracting blocks from the original matrix */ 7539 PetscCall(PetscMalloc1(lblocks, &edata->is)); 7540 for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i])); 7541 7542 /* Create the resulting inverse matrix structure with preallocation information */ 7543 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C)); 7544 PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 7545 PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat)); 7546 PetscCall(MatSetType(edata->C, MATAIJ)); 7547 7548 /* Communicate the start and end of each row, from each block to the correct rank */ 7549 /* TODO: Use PetscSF instead of VecScatter */ 7550 for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i]; 7551 PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq)); 7552 PetscCall(VecGetArrayWrite(seq, &seqv)); 7553 for (PetscInt i = 0; i < lblocks; i++) { 7554 for (PetscInt j = 0; j < sizes[i]; j++) { 7555 seqv[cnt] = starts[i]; 7556 seqv[cnt + 1] = starts[i] + sizes[i]; 7557 cnt += 2; 7558 } 7559 } 7560 PetscCall(VecRestoreArrayWrite(seq, &seqv)); 7561 PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 7562 sc -= cnt; 7563 PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par)); 7564 PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal)); 7565 PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter)); 7566 PetscCall(ISDestroy(&isglobal)); 7567 PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7568 PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7569 PetscCall(VecScatterDestroy(&scatter)); 7570 PetscCall(VecDestroy(&seq)); 7571 PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend)); 7572 PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag)); 7573 PetscCall(VecGetArrayRead(par, &parv)); 7574 cnt = 0; 7575 PetscCall(MatGetSize(mat, NULL, &n)); 7576 for (PetscInt i = 0; i < mat->rmap->n; i++) { 7577 PetscInt start, end, d = 0, od = 0; 7578 7579 start = (PetscInt)PetscRealPart(parv[cnt]); 7580 end = (PetscInt)PetscRealPart(parv[cnt + 1]); 7581 cnt += 2; 7582 7583 if (start < cstart) { 7584 od += cstart - start + n - cend; 7585 d += cend - cstart; 7586 } else if (start < cend) { 7587 od += n - cend; 7588 d += cend - start; 7589 } else od += n - start; 7590 if (end <= cstart) { 7591 od -= cstart - end + n - cend; 7592 d -= cend - cstart; 7593 } else if (end < cend) { 7594 od -= n - cend; 7595 d -= cend - end; 7596 } else od -= n - end; 7597 7598 odiag[i] = od; 7599 diag[i] = d; 7600 } 7601 PetscCall(VecRestoreArrayRead(par, &parv)); 7602 PetscCall(VecDestroy(&par)); 7603 PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL)); 7604 PetscCall(PetscFree2(diag, odiag)); 7605 PetscCall(PetscFree2(sizes, starts)); 7606 7607 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container)); 7608 PetscCall(PetscContainerSetPointer(container, edata)); 7609 PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy)); 7610 PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container)); 7611 PetscCall(PetscObjectDereference((PetscObject)container)); 7612 PetscFunctionReturn(PETSC_SUCCESS); 7613 } 7614 7615 /*@ 7616 MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A 7617 7618 Collective 7619 7620 Input Parameters: 7621 + A - the matrix 7622 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine 7623 7624 Output Parameter: 7625 . C - matrix with inverted block diagonal of `A` 7626 7627 Level: advanced 7628 7629 Note: 7630 For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal. 7631 7632 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()` 7633 @*/ 7634 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C) 7635 { 7636 PetscContainer container; 7637 EnvelopeData *edata; 7638 PetscObjectState nonzerostate; 7639 7640 PetscFunctionBegin; 7641 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7642 if (!container) { 7643 PetscCall(MatComputeVariableBlockEnvelope(A)); 7644 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7645 } 7646 PetscCall(PetscContainerGetPointer(container, (void **)&edata)); 7647 PetscCall(MatGetNonzeroState(A, &nonzerostate)); 7648 PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure"); 7649 PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output"); 7650 7651 PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat)); 7652 *C = edata->C; 7653 7654 for (PetscInt i = 0; i < edata->n; i++) { 7655 Mat D; 7656 PetscScalar *dvalues; 7657 7658 PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D)); 7659 PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE)); 7660 PetscCall(MatSeqDenseInvert(D)); 7661 PetscCall(MatDenseGetArray(D, &dvalues)); 7662 PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES)); 7663 PetscCall(MatDestroy(&D)); 7664 } 7665 PetscCall(MatDestroySubMatrices(edata->n, &edata->mat)); 7666 PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY)); 7667 PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY)); 7668 PetscFunctionReturn(PETSC_SUCCESS); 7669 } 7670 7671 /*@ 7672 MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size 7673 7674 Logically Collective 7675 7676 Input Parameters: 7677 + mat - the matrix 7678 . nblocks - the number of blocks on this process, each block can only exist on a single process 7679 - bsizes - the block sizes 7680 7681 Level: intermediate 7682 7683 Notes: 7684 Currently used by `PCVPBJACOBI` for `MATAIJ` matrices 7685 7686 Each variable point-block set of degrees of freedom must live on a single MPI process. That is a point block cannot straddle two MPI processes. 7687 7688 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, 7689 `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI` 7690 @*/ 7691 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes) 7692 { 7693 PetscInt i, ncnt = 0, nlocal; 7694 7695 PetscFunctionBegin; 7696 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7697 PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero"); 7698 PetscCall(MatGetLocalSize(mat, &nlocal, NULL)); 7699 for (i = 0; i < nblocks; i++) ncnt += bsizes[i]; 7700 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); 7701 PetscCall(PetscFree(mat->bsizes)); 7702 mat->nblocks = nblocks; 7703 PetscCall(PetscMalloc1(nblocks, &mat->bsizes)); 7704 PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks)); 7705 PetscFunctionReturn(PETSC_SUCCESS); 7706 } 7707 7708 /*@C 7709 MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size 7710 7711 Logically Collective; No Fortran Support 7712 7713 Input Parameter: 7714 . mat - the matrix 7715 7716 Output Parameters: 7717 + nblocks - the number of blocks on this process 7718 - bsizes - the block sizes 7719 7720 Level: intermediate 7721 7722 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()` 7723 @*/ 7724 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes) 7725 { 7726 PetscFunctionBegin; 7727 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7728 *nblocks = mat->nblocks; 7729 *bsizes = mat->bsizes; 7730 PetscFunctionReturn(PETSC_SUCCESS); 7731 } 7732 7733 /*@ 7734 MatSetBlockSizes - Sets the matrix block row and column sizes. 7735 7736 Logically Collective 7737 7738 Input Parameters: 7739 + mat - the matrix 7740 . rbs - row block size 7741 - cbs - column block size 7742 7743 Level: intermediate 7744 7745 Notes: 7746 Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix. 7747 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7748 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7749 7750 For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes 7751 are compatible with the matrix local sizes. 7752 7753 The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`. 7754 7755 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()` 7756 @*/ 7757 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs) 7758 { 7759 PetscFunctionBegin; 7760 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7761 PetscValidLogicalCollectiveInt(mat, rbs, 2); 7762 PetscValidLogicalCollectiveInt(mat, cbs, 3); 7763 PetscTryTypeMethod(mat, setblocksizes, rbs, cbs); 7764 if (mat->rmap->refcnt) { 7765 ISLocalToGlobalMapping l2g = NULL; 7766 PetscLayout nmap = NULL; 7767 7768 PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap)); 7769 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g)); 7770 PetscCall(PetscLayoutDestroy(&mat->rmap)); 7771 mat->rmap = nmap; 7772 mat->rmap->mapping = l2g; 7773 } 7774 if (mat->cmap->refcnt) { 7775 ISLocalToGlobalMapping l2g = NULL; 7776 PetscLayout nmap = NULL; 7777 7778 PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap)); 7779 if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g)); 7780 PetscCall(PetscLayoutDestroy(&mat->cmap)); 7781 mat->cmap = nmap; 7782 mat->cmap->mapping = l2g; 7783 } 7784 PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs)); 7785 PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs)); 7786 PetscFunctionReturn(PETSC_SUCCESS); 7787 } 7788 7789 /*@ 7790 MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices 7791 7792 Logically Collective 7793 7794 Input Parameters: 7795 + mat - the matrix 7796 . fromRow - matrix from which to copy row block size 7797 - fromCol - matrix from which to copy column block size (can be same as fromRow) 7798 7799 Level: developer 7800 7801 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()` 7802 @*/ 7803 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol) 7804 { 7805 PetscFunctionBegin; 7806 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7807 PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2); 7808 PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3); 7809 if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs)); 7810 if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs)); 7811 PetscFunctionReturn(PETSC_SUCCESS); 7812 } 7813 7814 /*@ 7815 MatResidual - Default routine to calculate the residual r = b - Ax 7816 7817 Collective 7818 7819 Input Parameters: 7820 + mat - the matrix 7821 . b - the right-hand-side 7822 - x - the approximate solution 7823 7824 Output Parameter: 7825 . r - location to store the residual 7826 7827 Level: developer 7828 7829 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()` 7830 @*/ 7831 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r) 7832 { 7833 PetscFunctionBegin; 7834 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7835 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 7836 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 7837 PetscValidHeaderSpecific(r, VEC_CLASSID, 4); 7838 PetscValidType(mat, 1); 7839 MatCheckPreallocated(mat, 1); 7840 PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0)); 7841 if (!mat->ops->residual) { 7842 PetscCall(MatMult(mat, x, r)); 7843 PetscCall(VecAYPX(r, -1.0, b)); 7844 } else { 7845 PetscUseTypeMethod(mat, residual, b, x, r); 7846 } 7847 PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0)); 7848 PetscFunctionReturn(PETSC_SUCCESS); 7849 } 7850 7851 /*MC 7852 MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix 7853 7854 Synopsis: 7855 MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 7856 7857 Not Collective 7858 7859 Input Parameters: 7860 + A - the matrix 7861 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7862 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7863 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7864 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7865 always used. 7866 7867 Output Parameters: 7868 + n - number of local rows in the (possibly compressed) matrix 7869 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 7870 . ja - the column indices 7871 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7872 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7873 7874 Level: developer 7875 7876 Note: 7877 Use `MatRestoreRowIJF90()` when you no longer need access to the data 7878 7879 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()` 7880 M*/ 7881 7882 /*MC 7883 MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()` 7884 7885 Synopsis: 7886 MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 7887 7888 Not Collective 7889 7890 Input Parameters: 7891 + A - the matrix 7892 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7893 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7894 inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7895 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7896 always used. 7897 . n - number of local rows in the (possibly compressed) matrix 7898 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 7899 . ja - the column indices 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 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()` 7906 M*/ 7907 7908 /*@C 7909 MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix 7910 7911 Collective 7912 7913 Input Parameters: 7914 + mat - the matrix 7915 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7916 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7917 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7918 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7919 always used. 7920 7921 Output Parameters: 7922 + n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed 7923 . 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 7924 . ja - the column indices, use `NULL` if not needed 7925 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7926 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7927 7928 Level: developer 7929 7930 Notes: 7931 You CANNOT change any of the ia[] or ja[] values. 7932 7933 Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values. 7934 7935 Fortran Notes: 7936 Use 7937 .vb 7938 PetscInt, pointer :: ia(:),ja(:) 7939 call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr) 7940 ! Access the ith and jth entries via ia(i) and ja(j) 7941 .ve 7942 `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()` 7943 7944 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()` 7945 @*/ 7946 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7947 { 7948 PetscFunctionBegin; 7949 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7950 PetscValidType(mat, 1); 7951 if (n) PetscValidIntPointer(n, 5); 7952 if (ia) PetscValidPointer(ia, 6); 7953 if (ja) PetscValidPointer(ja, 7); 7954 if (done) PetscValidBoolPointer(done, 8); 7955 MatCheckPreallocated(mat, 1); 7956 if (!mat->ops->getrowij && done) *done = PETSC_FALSE; 7957 else { 7958 if (done) *done = PETSC_TRUE; 7959 PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0)); 7960 PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done); 7961 PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0)); 7962 } 7963 PetscFunctionReturn(PETSC_SUCCESS); 7964 } 7965 7966 /*@C 7967 MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices. 7968 7969 Collective 7970 7971 Input Parameters: 7972 + mat - the matrix 7973 . shift - 1 or zero indicating we want the indices starting at 0 or 1 7974 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be 7975 symmetrized 7976 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7977 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7978 always used. 7979 . n - number of columns in the (possibly compressed) matrix 7980 . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix 7981 - ja - the row indices 7982 7983 Output Parameter: 7984 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned 7985 7986 Level: developer 7987 7988 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 7989 @*/ 7990 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7991 { 7992 PetscFunctionBegin; 7993 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7994 PetscValidType(mat, 1); 7995 PetscValidIntPointer(n, 5); 7996 if (ia) PetscValidPointer(ia, 6); 7997 if (ja) PetscValidPointer(ja, 7); 7998 PetscValidBoolPointer(done, 8); 7999 MatCheckPreallocated(mat, 1); 8000 if (!mat->ops->getcolumnij) *done = PETSC_FALSE; 8001 else { 8002 *done = PETSC_TRUE; 8003 PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8004 } 8005 PetscFunctionReturn(PETSC_SUCCESS); 8006 } 8007 8008 /*@C 8009 MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`. 8010 8011 Collective 8012 8013 Input Parameters: 8014 + mat - the matrix 8015 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8016 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8017 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8018 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8019 always used. 8020 . n - size of (possibly compressed) matrix 8021 . ia - the row pointers 8022 - ja - the column indices 8023 8024 Output Parameter: 8025 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8026 8027 Level: developer 8028 8029 Note: 8030 This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental 8031 us of the array after it has been restored. If you pass `NULL`, it will 8032 not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid. 8033 8034 Fortran Note: 8035 `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()` 8036 8037 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()` 8038 @*/ 8039 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8040 { 8041 PetscFunctionBegin; 8042 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8043 PetscValidType(mat, 1); 8044 if (ia) PetscValidPointer(ia, 6); 8045 if (ja) PetscValidPointer(ja, 7); 8046 if (done) PetscValidBoolPointer(done, 8); 8047 MatCheckPreallocated(mat, 1); 8048 8049 if (!mat->ops->restorerowij && done) *done = PETSC_FALSE; 8050 else { 8051 if (done) *done = PETSC_TRUE; 8052 PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8053 if (n) *n = 0; 8054 if (ia) *ia = NULL; 8055 if (ja) *ja = NULL; 8056 } 8057 PetscFunctionReturn(PETSC_SUCCESS); 8058 } 8059 8060 /*@C 8061 MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`. 8062 8063 Collective 8064 8065 Input Parameters: 8066 + mat - the matrix 8067 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8068 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8069 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8070 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8071 always used. 8072 8073 Output Parameters: 8074 + n - size of (possibly compressed) matrix 8075 . ia - the column pointers 8076 . ja - the row indices 8077 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8078 8079 Level: developer 8080 8081 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()` 8082 @*/ 8083 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8084 { 8085 PetscFunctionBegin; 8086 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8087 PetscValidType(mat, 1); 8088 if (ia) PetscValidPointer(ia, 6); 8089 if (ja) PetscValidPointer(ja, 7); 8090 PetscValidBoolPointer(done, 8); 8091 MatCheckPreallocated(mat, 1); 8092 8093 if (!mat->ops->restorecolumnij) *done = PETSC_FALSE; 8094 else { 8095 *done = PETSC_TRUE; 8096 PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8097 if (n) *n = 0; 8098 if (ia) *ia = NULL; 8099 if (ja) *ja = NULL; 8100 } 8101 PetscFunctionReturn(PETSC_SUCCESS); 8102 } 8103 8104 /*@C 8105 MatColoringPatch -Used inside matrix coloring routines that use `MatGetRowIJ()` and/or `MatGetColumnIJ()`. 8106 8107 Collective 8108 8109 Input Parameters: 8110 + mat - the matrix 8111 . ncolors - maximum color value 8112 . n - number of entries in colorarray 8113 - colorarray - array indicating color for each column 8114 8115 Output Parameter: 8116 . iscoloring - coloring generated using colorarray information 8117 8118 Level: developer 8119 8120 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()` 8121 @*/ 8122 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring) 8123 { 8124 PetscFunctionBegin; 8125 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8126 PetscValidType(mat, 1); 8127 PetscValidIntPointer(colorarray, 4); 8128 PetscValidPointer(iscoloring, 5); 8129 MatCheckPreallocated(mat, 1); 8130 8131 if (!mat->ops->coloringpatch) { 8132 PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring)); 8133 } else { 8134 PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring); 8135 } 8136 PetscFunctionReturn(PETSC_SUCCESS); 8137 } 8138 8139 /*@ 8140 MatSetUnfactored - Resets a factored matrix to be treated as unfactored. 8141 8142 Logically Collective 8143 8144 Input Parameter: 8145 . mat - the factored matrix to be reset 8146 8147 Level: developer 8148 8149 Notes: 8150 This routine should be used only with factored matrices formed by in-place 8151 factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE` 8152 format). This option can save memory, for example, when solving nonlinear 8153 systems with a matrix-free Newton-Krylov method and a matrix-based, in-place 8154 ILU(0) preconditioner. 8155 8156 One can specify in-place ILU(0) factorization by calling 8157 .vb 8158 PCType(pc,PCILU); 8159 PCFactorSeUseInPlace(pc); 8160 .ve 8161 or by using the options -pc_type ilu -pc_factor_in_place 8162 8163 In-place factorization ILU(0) can also be used as a local 8164 solver for the blocks within the block Jacobi or additive Schwarz 8165 methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc 8166 for details on setting local solver options. 8167 8168 Most users should employ the `KSP` interface for linear solvers 8169 instead of working directly with matrix algebra routines such as this. 8170 See, e.g., `KSPCreate()`. 8171 8172 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()` 8173 @*/ 8174 PetscErrorCode MatSetUnfactored(Mat mat) 8175 { 8176 PetscFunctionBegin; 8177 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8178 PetscValidType(mat, 1); 8179 MatCheckPreallocated(mat, 1); 8180 mat->factortype = MAT_FACTOR_NONE; 8181 if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS); 8182 PetscUseTypeMethod(mat, setunfactored); 8183 PetscFunctionReturn(PETSC_SUCCESS); 8184 } 8185 8186 /*MC 8187 MatDenseGetArrayF90 - Accesses a matrix array from Fortran 8188 8189 Synopsis: 8190 MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8191 8192 Not Collective 8193 8194 Input Parameter: 8195 . x - matrix 8196 8197 Output Parameters: 8198 + xx_v - the Fortran pointer to the array 8199 - ierr - error code 8200 8201 Example of Usage: 8202 .vb 8203 PetscScalar, pointer xx_v(:,:) 8204 .... 8205 call MatDenseGetArrayF90(x,xx_v,ierr) 8206 a = xx_v(3) 8207 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8208 .ve 8209 8210 Level: advanced 8211 8212 .seealso: [](ch_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()` 8213 M*/ 8214 8215 /*MC 8216 MatDenseRestoreArrayF90 - Restores a matrix array that has been 8217 accessed with `MatDenseGetArrayF90()`. 8218 8219 Synopsis: 8220 MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8221 8222 Not Collective 8223 8224 Input Parameters: 8225 + x - matrix 8226 - xx_v - the Fortran90 pointer to the array 8227 8228 Output Parameter: 8229 . ierr - error code 8230 8231 Example of Usage: 8232 .vb 8233 PetscScalar, pointer xx_v(:,:) 8234 .... 8235 call MatDenseGetArrayF90(x,xx_v,ierr) 8236 a = xx_v(3) 8237 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8238 .ve 8239 8240 Level: advanced 8241 8242 .seealso: [](ch_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()` 8243 M*/ 8244 8245 /*MC 8246 MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran. 8247 8248 Synopsis: 8249 MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8250 8251 Not Collective 8252 8253 Input Parameter: 8254 . x - matrix 8255 8256 Output Parameters: 8257 + xx_v - the Fortran pointer to the array 8258 - ierr - error code 8259 8260 Example of Usage: 8261 .vb 8262 PetscScalar, pointer xx_v(:) 8263 .... 8264 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8265 a = xx_v(3) 8266 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8267 .ve 8268 8269 Level: advanced 8270 8271 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()` 8272 M*/ 8273 8274 /*MC 8275 MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been 8276 accessed with `MatSeqAIJGetArrayF90()`. 8277 8278 Synopsis: 8279 MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8280 8281 Not Collective 8282 8283 Input Parameters: 8284 + x - matrix 8285 - xx_v - the Fortran90 pointer to the array 8286 8287 Output Parameter: 8288 . ierr - error code 8289 8290 Example of Usage: 8291 .vb 8292 PetscScalar, pointer xx_v(:) 8293 .... 8294 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8295 a = xx_v(3) 8296 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8297 .ve 8298 8299 Level: advanced 8300 8301 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()` 8302 M*/ 8303 8304 /*@ 8305 MatCreateSubMatrix - Gets a single submatrix on the same number of processors 8306 as the original matrix. 8307 8308 Collective 8309 8310 Input Parameters: 8311 + mat - the original matrix 8312 . isrow - parallel `IS` containing the rows this processor should obtain 8313 . 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. 8314 - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 8315 8316 Output Parameter: 8317 . newmat - the new submatrix, of the same type as the original matrix 8318 8319 Level: advanced 8320 8321 Notes: 8322 The submatrix will be able to be multiplied with vectors using the same layout as `iscol`. 8323 8324 Some matrix types place restrictions on the row and column indices, such 8325 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; 8326 for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row. 8327 8328 The index sets may not have duplicate entries. 8329 8330 The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`, 8331 the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls 8332 to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX` 8333 will reuse the matrix generated the first time. You should call `MatDestroy()` on `newmat` when 8334 you are finished using it. 8335 8336 The communicator of the newly obtained matrix is ALWAYS the same as the communicator of 8337 the input matrix. 8338 8339 If `iscol` is `NULL` then all columns are obtained (not supported in Fortran). 8340 8341 Example usage: 8342 Consider the following 8x8 matrix with 34 non-zero values, that is 8343 assembled across 3 processors. Let's assume that proc0 owns 3 rows, 8344 proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 8345 as follows 8346 .vb 8347 1 2 0 | 0 3 0 | 0 4 8348 Proc0 0 5 6 | 7 0 0 | 8 0 8349 9 0 10 | 11 0 0 | 12 0 8350 ------------------------------------- 8351 13 0 14 | 15 16 17 | 0 0 8352 Proc1 0 18 0 | 19 20 21 | 0 0 8353 0 0 0 | 22 23 0 | 24 0 8354 ------------------------------------- 8355 Proc2 25 26 27 | 0 0 28 | 29 0 8356 30 0 0 | 31 32 33 | 0 34 8357 .ve 8358 8359 Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6]. The resulting submatrix is 8360 8361 .vb 8362 2 0 | 0 3 0 | 0 8363 Proc0 5 6 | 7 0 0 | 8 8364 ------------------------------- 8365 Proc1 18 0 | 19 20 21 | 0 8366 ------------------------------- 8367 Proc2 26 27 | 0 0 28 | 29 8368 0 0 | 31 32 33 | 0 8369 .ve 8370 8371 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()` 8372 @*/ 8373 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat) 8374 { 8375 PetscMPIInt size; 8376 Mat *local; 8377 IS iscoltmp; 8378 PetscBool flg; 8379 8380 PetscFunctionBegin; 8381 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8382 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 8383 if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 8384 PetscValidPointer(newmat, 5); 8385 if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5); 8386 PetscValidType(mat, 1); 8387 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8388 PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX"); 8389 8390 MatCheckPreallocated(mat, 1); 8391 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8392 8393 if (!iscol || isrow == iscol) { 8394 PetscBool stride; 8395 PetscMPIInt grabentirematrix = 0, grab; 8396 PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride)); 8397 if (stride) { 8398 PetscInt first, step, n, rstart, rend; 8399 PetscCall(ISStrideGetInfo(isrow, &first, &step)); 8400 if (step == 1) { 8401 PetscCall(MatGetOwnershipRange(mat, &rstart, &rend)); 8402 if (rstart == first) { 8403 PetscCall(ISGetLocalSize(isrow, &n)); 8404 if (n == rend - rstart) grabentirematrix = 1; 8405 } 8406 } 8407 } 8408 PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat))); 8409 if (grab) { 8410 PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n")); 8411 if (cll == MAT_INITIAL_MATRIX) { 8412 *newmat = mat; 8413 PetscCall(PetscObjectReference((PetscObject)mat)); 8414 } 8415 PetscFunctionReturn(PETSC_SUCCESS); 8416 } 8417 } 8418 8419 if (!iscol) { 8420 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp)); 8421 } else { 8422 iscoltmp = iscol; 8423 } 8424 8425 /* if original matrix is on just one processor then use submatrix generated */ 8426 if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) { 8427 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat)); 8428 goto setproperties; 8429 } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) { 8430 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local)); 8431 *newmat = *local; 8432 PetscCall(PetscFree(local)); 8433 goto setproperties; 8434 } else if (!mat->ops->createsubmatrix) { 8435 /* Create a new matrix type that implements the operation using the full matrix */ 8436 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8437 switch (cll) { 8438 case MAT_INITIAL_MATRIX: 8439 PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat)); 8440 break; 8441 case MAT_REUSE_MATRIX: 8442 PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp)); 8443 break; 8444 default: 8445 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX"); 8446 } 8447 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8448 goto setproperties; 8449 } 8450 8451 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8452 PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat); 8453 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8454 8455 setproperties: 8456 PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg)); 8457 if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat)); 8458 if (!iscol) PetscCall(ISDestroy(&iscoltmp)); 8459 if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat)); 8460 PetscFunctionReturn(PETSC_SUCCESS); 8461 } 8462 8463 /*@ 8464 MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix 8465 8466 Not Collective 8467 8468 Input Parameters: 8469 + A - the matrix we wish to propagate options from 8470 - B - the matrix we wish to propagate options to 8471 8472 Level: beginner 8473 8474 Note: 8475 Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL` 8476 8477 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, MatIsStructurallySymmetricKnown()` 8478 @*/ 8479 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B) 8480 { 8481 PetscFunctionBegin; 8482 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8483 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 8484 B->symmetry_eternal = A->symmetry_eternal; 8485 B->structural_symmetry_eternal = A->structural_symmetry_eternal; 8486 B->symmetric = A->symmetric; 8487 B->structurally_symmetric = A->structurally_symmetric; 8488 B->spd = A->spd; 8489 B->hermitian = A->hermitian; 8490 PetscFunctionReturn(PETSC_SUCCESS); 8491 } 8492 8493 /*@ 8494 MatStashSetInitialSize - sets the sizes of the matrix stash, that is 8495 used during the assembly process to store values that belong to 8496 other processors. 8497 8498 Not Collective 8499 8500 Input Parameters: 8501 + mat - the matrix 8502 . size - the initial size of the stash. 8503 - bsize - the initial size of the block-stash(if used). 8504 8505 Options Database Keys: 8506 + -matstash_initial_size <size> or <size0,size1,...sizep-1> 8507 - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1> 8508 8509 Level: intermediate 8510 8511 Notes: 8512 The block-stash is used for values set with `MatSetValuesBlocked()` while 8513 the stash is used for values set with `MatSetValues()` 8514 8515 Run with the option -info and look for output of the form 8516 MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs. 8517 to determine the appropriate value, MM, to use for size and 8518 MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs. 8519 to determine the value, BMM to use for bsize 8520 8521 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()` 8522 @*/ 8523 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize) 8524 { 8525 PetscFunctionBegin; 8526 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8527 PetscValidType(mat, 1); 8528 PetscCall(MatStashSetInitialSize_Private(&mat->stash, size)); 8529 PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize)); 8530 PetscFunctionReturn(PETSC_SUCCESS); 8531 } 8532 8533 /*@ 8534 MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of 8535 the matrix 8536 8537 Neighbor-wise Collective 8538 8539 Input Parameters: 8540 + mat - the matrix 8541 . x - the vector to be multiplied by the interpolation operator 8542 - y - the vector to be added to the result 8543 8544 Output Parameter: 8545 . w - the resulting vector 8546 8547 Level: intermediate 8548 8549 Notes: 8550 `w` may be the same vector as `y`. 8551 8552 This allows one to use either the restriction or interpolation (its transpose) 8553 matrix to do the interpolation 8554 8555 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8556 @*/ 8557 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w) 8558 { 8559 PetscInt M, N, Ny; 8560 8561 PetscFunctionBegin; 8562 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8563 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8564 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8565 PetscValidHeaderSpecific(w, VEC_CLASSID, 4); 8566 PetscCall(MatGetSize(A, &M, &N)); 8567 PetscCall(VecGetSize(y, &Ny)); 8568 if (M == Ny) { 8569 PetscCall(MatMultAdd(A, x, y, w)); 8570 } else { 8571 PetscCall(MatMultTransposeAdd(A, x, y, w)); 8572 } 8573 PetscFunctionReturn(PETSC_SUCCESS); 8574 } 8575 8576 /*@ 8577 MatInterpolate - y = A*x or A'*x depending on the shape of 8578 the matrix 8579 8580 Neighbor-wise Collective 8581 8582 Input Parameters: 8583 + mat - the matrix 8584 - x - the vector to be interpolated 8585 8586 Output Parameter: 8587 . y - the resulting vector 8588 8589 Level: intermediate 8590 8591 Note: 8592 This allows one to use either the restriction or interpolation (its transpose) 8593 matrix to do the interpolation 8594 8595 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8596 @*/ 8597 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y) 8598 { 8599 PetscInt M, N, Ny; 8600 8601 PetscFunctionBegin; 8602 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8603 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8604 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8605 PetscCall(MatGetSize(A, &M, &N)); 8606 PetscCall(VecGetSize(y, &Ny)); 8607 if (M == Ny) { 8608 PetscCall(MatMult(A, x, y)); 8609 } else { 8610 PetscCall(MatMultTranspose(A, x, y)); 8611 } 8612 PetscFunctionReturn(PETSC_SUCCESS); 8613 } 8614 8615 /*@ 8616 MatRestrict - y = A*x or A'*x 8617 8618 Neighbor-wise Collective 8619 8620 Input Parameters: 8621 + mat - the matrix 8622 - x - the vector to be restricted 8623 8624 Output Parameter: 8625 . y - the resulting vector 8626 8627 Level: intermediate 8628 8629 Note: 8630 This allows one to use either the restriction or interpolation (its transpose) 8631 matrix to do the restriction 8632 8633 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG` 8634 @*/ 8635 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y) 8636 { 8637 PetscInt M, N, Ny; 8638 8639 PetscFunctionBegin; 8640 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8641 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8642 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8643 PetscCall(MatGetSize(A, &M, &N)); 8644 PetscCall(VecGetSize(y, &Ny)); 8645 if (M == Ny) { 8646 PetscCall(MatMult(A, x, y)); 8647 } else { 8648 PetscCall(MatMultTranspose(A, x, y)); 8649 } 8650 PetscFunctionReturn(PETSC_SUCCESS); 8651 } 8652 8653 /*@ 8654 MatMatInterpolateAdd - Y = W + A*X or W + A'*X 8655 8656 Neighbor-wise Collective 8657 8658 Input Parameters: 8659 + mat - the matrix 8660 . x - the input dense matrix to be multiplied 8661 - w - the input dense matrix to be added to the result 8662 8663 Output Parameter: 8664 . y - the output dense matrix 8665 8666 Level: intermediate 8667 8668 Note: 8669 This allows one to use either the restriction or interpolation (its transpose) 8670 matrix to do the interpolation. y matrix can be reused if already created with the proper sizes, 8671 otherwise it will be recreated. y must be initialized to `NULL` if not supplied. 8672 8673 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG` 8674 @*/ 8675 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y) 8676 { 8677 PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0; 8678 PetscBool trans = PETSC_TRUE; 8679 MatReuse reuse = MAT_INITIAL_MATRIX; 8680 8681 PetscFunctionBegin; 8682 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8683 PetscValidHeaderSpecific(x, MAT_CLASSID, 2); 8684 PetscValidType(x, 2); 8685 if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3); 8686 if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4); 8687 PetscCall(MatGetSize(A, &M, &N)); 8688 PetscCall(MatGetSize(x, &Mx, &Nx)); 8689 if (N == Mx) trans = PETSC_FALSE; 8690 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); 8691 Mo = trans ? N : M; 8692 if (*y) { 8693 PetscCall(MatGetSize(*y, &My, &Ny)); 8694 if (Mo == My && Nx == Ny) { 8695 reuse = MAT_REUSE_MATRIX; 8696 } else { 8697 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); 8698 PetscCall(MatDestroy(y)); 8699 } 8700 } 8701 8702 if (w && *y == w) { /* this is to minimize changes in PCMG */ 8703 PetscBool flg; 8704 8705 PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w)); 8706 if (w) { 8707 PetscInt My, Ny, Mw, Nw; 8708 8709 PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg)); 8710 PetscCall(MatGetSize(*y, &My, &Ny)); 8711 PetscCall(MatGetSize(w, &Mw, &Nw)); 8712 if (!flg || My != Mw || Ny != Nw) w = NULL; 8713 } 8714 if (!w) { 8715 PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w)); 8716 PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w)); 8717 PetscCall(PetscObjectDereference((PetscObject)w)); 8718 } else { 8719 PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN)); 8720 } 8721 } 8722 if (!trans) { 8723 PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8724 } else { 8725 PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8726 } 8727 if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN)); 8728 PetscFunctionReturn(PETSC_SUCCESS); 8729 } 8730 8731 /*@ 8732 MatMatInterpolate - Y = A*X or A'*X 8733 8734 Neighbor-wise Collective 8735 8736 Input Parameters: 8737 + mat - the matrix 8738 - x - the input dense matrix 8739 8740 Output Parameter: 8741 . y - the output dense matrix 8742 8743 Level: intermediate 8744 8745 Note: 8746 This allows one to use either the restriction or interpolation (its transpose) 8747 matrix to do the interpolation. y matrix can be reused if already created with the proper sizes, 8748 otherwise it will be recreated. y must be initialized to `NULL` if not supplied. 8749 8750 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG` 8751 @*/ 8752 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y) 8753 { 8754 PetscFunctionBegin; 8755 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8756 PetscFunctionReturn(PETSC_SUCCESS); 8757 } 8758 8759 /*@ 8760 MatMatRestrict - Y = A*X or A'*X 8761 8762 Neighbor-wise Collective 8763 8764 Input Parameters: 8765 + mat - the matrix 8766 - x - the input dense matrix 8767 8768 Output Parameter: 8769 . y - the output dense matrix 8770 8771 Level: intermediate 8772 8773 Note: 8774 This allows one to use either the restriction or interpolation (its transpose) 8775 matrix to do the restriction. y matrix can be reused if already created with the proper sizes, 8776 otherwise it will be recreated. y must be initialized to `NULL` if not supplied. 8777 8778 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG` 8779 @*/ 8780 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y) 8781 { 8782 PetscFunctionBegin; 8783 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8784 PetscFunctionReturn(PETSC_SUCCESS); 8785 } 8786 8787 /*@ 8788 MatGetNullSpace - retrieves the null space of a matrix. 8789 8790 Logically Collective 8791 8792 Input Parameters: 8793 + mat - the matrix 8794 - nullsp - the null space object 8795 8796 Level: developer 8797 8798 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace` 8799 @*/ 8800 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp) 8801 { 8802 PetscFunctionBegin; 8803 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8804 PetscValidPointer(nullsp, 2); 8805 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp; 8806 PetscFunctionReturn(PETSC_SUCCESS); 8807 } 8808 8809 /*@ 8810 MatSetNullSpace - attaches a null space to a matrix. 8811 8812 Logically Collective 8813 8814 Input Parameters: 8815 + mat - the matrix 8816 - nullsp - the null space object 8817 8818 Level: advanced 8819 8820 Notes: 8821 This null space is used by the `KSP` linear solvers to solve singular systems. 8822 8823 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` 8824 8825 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 8826 to zero but the linear system will still be solved in a least squares sense. 8827 8828 The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that 8829 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). 8830 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 8831 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 8832 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). 8833 This \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix. 8834 8835 If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called 8836 `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this 8837 routine also automatically calls `MatSetTransposeNullSpace()`. 8838 8839 The user should call `MatNullSpaceDestroy()`. 8840 8841 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, 8842 `KSPSetPCSide()` 8843 @*/ 8844 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp) 8845 { 8846 PetscFunctionBegin; 8847 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8848 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8849 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8850 PetscCall(MatNullSpaceDestroy(&mat->nullsp)); 8851 mat->nullsp = nullsp; 8852 if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp)); 8853 PetscFunctionReturn(PETSC_SUCCESS); 8854 } 8855 8856 /*@ 8857 MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix. 8858 8859 Logically Collective 8860 8861 Input Parameters: 8862 + mat - the matrix 8863 - nullsp - the null space object 8864 8865 Level: developer 8866 8867 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()` 8868 @*/ 8869 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp) 8870 { 8871 PetscFunctionBegin; 8872 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8873 PetscValidType(mat, 1); 8874 PetscValidPointer(nullsp, 2); 8875 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp; 8876 PetscFunctionReturn(PETSC_SUCCESS); 8877 } 8878 8879 /*@ 8880 MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix 8881 8882 Logically Collective 8883 8884 Input Parameters: 8885 + mat - the matrix 8886 - nullsp - the null space object 8887 8888 Level: advanced 8889 8890 Notes: 8891 This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning. 8892 8893 See `MatSetNullSpace()` 8894 8895 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()` 8896 @*/ 8897 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp) 8898 { 8899 PetscFunctionBegin; 8900 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8901 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8902 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8903 PetscCall(MatNullSpaceDestroy(&mat->transnullsp)); 8904 mat->transnullsp = nullsp; 8905 PetscFunctionReturn(PETSC_SUCCESS); 8906 } 8907 8908 /*@ 8909 MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions 8910 This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix. 8911 8912 Logically Collective 8913 8914 Input Parameters: 8915 + mat - the matrix 8916 - nullsp - the null space object 8917 8918 Level: advanced 8919 8920 Notes: 8921 Overwrites any previous near null space that may have been attached 8922 8923 You can remove the null space by calling this routine with an nullsp of `NULL` 8924 8925 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()` 8926 @*/ 8927 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp) 8928 { 8929 PetscFunctionBegin; 8930 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8931 PetscValidType(mat, 1); 8932 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8933 MatCheckPreallocated(mat, 1); 8934 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8935 PetscCall(MatNullSpaceDestroy(&mat->nearnullsp)); 8936 mat->nearnullsp = nullsp; 8937 PetscFunctionReturn(PETSC_SUCCESS); 8938 } 8939 8940 /*@ 8941 MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()` 8942 8943 Not Collective 8944 8945 Input Parameter: 8946 . mat - the matrix 8947 8948 Output Parameter: 8949 . nullsp - the null space object, `NULL` if not set 8950 8951 Level: advanced 8952 8953 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()` 8954 @*/ 8955 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp) 8956 { 8957 PetscFunctionBegin; 8958 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8959 PetscValidType(mat, 1); 8960 PetscValidPointer(nullsp, 2); 8961 MatCheckPreallocated(mat, 1); 8962 *nullsp = mat->nearnullsp; 8963 PetscFunctionReturn(PETSC_SUCCESS); 8964 } 8965 8966 /*@C 8967 MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix. 8968 8969 Collective 8970 8971 Input Parameters: 8972 + mat - the matrix 8973 . row - row/column permutation 8974 - info - information on desired factorization process 8975 8976 Level: developer 8977 8978 Notes: 8979 Probably really in-place only when level of fill is zero, otherwise allocates 8980 new space to store factored matrix and deletes previous memory. 8981 8982 Most users should employ the `KSP` interface for linear solvers 8983 instead of working directly with matrix algebra routines such as this. 8984 See, e.g., `KSPCreate()`. 8985 8986 Developer Note: 8987 The Fortran interface is not autogenerated as the 8988 interface definition cannot be generated correctly [due to `MatFactorInfo`] 8989 8990 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 8991 @*/ 8992 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info) 8993 { 8994 PetscFunctionBegin; 8995 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8996 PetscValidType(mat, 1); 8997 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 8998 PetscValidPointer(info, 3); 8999 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 9000 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 9001 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 9002 MatCheckPreallocated(mat, 1); 9003 PetscUseTypeMethod(mat, iccfactor, row, info); 9004 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9005 PetscFunctionReturn(PETSC_SUCCESS); 9006 } 9007 9008 /*@ 9009 MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the 9010 ghosted ones. 9011 9012 Not Collective 9013 9014 Input Parameters: 9015 + mat - the matrix 9016 - diag - the diagonal values, including ghost ones 9017 9018 Level: developer 9019 9020 Notes: 9021 Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices 9022 9023 This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()` 9024 9025 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 9026 @*/ 9027 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag) 9028 { 9029 PetscMPIInt size; 9030 9031 PetscFunctionBegin; 9032 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9033 PetscValidHeaderSpecific(diag, VEC_CLASSID, 2); 9034 PetscValidType(mat, 1); 9035 9036 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled"); 9037 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 9038 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 9039 if (size == 1) { 9040 PetscInt n, m; 9041 PetscCall(VecGetSize(diag, &n)); 9042 PetscCall(MatGetSize(mat, NULL, &m)); 9043 PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions"); 9044 PetscCall(MatDiagonalScale(mat, NULL, diag)); 9045 } else { 9046 PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag)); 9047 } 9048 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 9049 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9050 PetscFunctionReturn(PETSC_SUCCESS); 9051 } 9052 9053 /*@ 9054 MatGetInertia - Gets the inertia from a factored matrix 9055 9056 Collective 9057 9058 Input Parameter: 9059 . mat - the matrix 9060 9061 Output Parameters: 9062 + nneg - number of negative eigenvalues 9063 . nzero - number of zero eigenvalues 9064 - npos - number of positive eigenvalues 9065 9066 Level: advanced 9067 9068 Note: 9069 Matrix must have been factored by `MatCholeskyFactor()` 9070 9071 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()` 9072 @*/ 9073 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos) 9074 { 9075 PetscFunctionBegin; 9076 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9077 PetscValidType(mat, 1); 9078 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9079 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled"); 9080 PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos); 9081 PetscFunctionReturn(PETSC_SUCCESS); 9082 } 9083 9084 /*@C 9085 MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors 9086 9087 Neighbor-wise Collective 9088 9089 Input Parameters: 9090 + mat - the factored matrix obtained with `MatGetFactor()` 9091 - b - the right-hand-side vectors 9092 9093 Output Parameter: 9094 . x - the result vectors 9095 9096 Level: developer 9097 9098 Note: 9099 The vectors `b` and `x` cannot be the same. I.e., one cannot 9100 call `MatSolves`(A,x,x). 9101 9102 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()` 9103 @*/ 9104 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x) 9105 { 9106 PetscFunctionBegin; 9107 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9108 PetscValidType(mat, 1); 9109 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 9110 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9111 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 9112 9113 MatCheckPreallocated(mat, 1); 9114 PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0)); 9115 PetscUseTypeMethod(mat, solves, b, x); 9116 PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0)); 9117 PetscFunctionReturn(PETSC_SUCCESS); 9118 } 9119 9120 /*@ 9121 MatIsSymmetric - Test whether a matrix is symmetric 9122 9123 Collective 9124 9125 Input Parameters: 9126 + A - the matrix to test 9127 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose) 9128 9129 Output Parameter: 9130 . flg - the result 9131 9132 Level: intermediate 9133 9134 Notes: 9135 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9136 9137 If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()` 9138 9139 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9140 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9141 9142 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`, 9143 `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()` 9144 @*/ 9145 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg) 9146 { 9147 PetscFunctionBegin; 9148 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9149 PetscValidBoolPointer(flg, 3); 9150 9151 if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE; 9152 else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE; 9153 else { 9154 PetscUseTypeMethod(A, issymmetric, tol, flg); 9155 if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg)); 9156 } 9157 PetscFunctionReturn(PETSC_SUCCESS); 9158 } 9159 9160 /*@ 9161 MatIsHermitian - Test whether a matrix is Hermitian 9162 9163 Collective 9164 9165 Input Parameters: 9166 + A - the matrix to test 9167 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian) 9168 9169 Output Parameter: 9170 . flg - the result 9171 9172 Level: intermediate 9173 9174 Notes: 9175 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9176 9177 If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()` 9178 9179 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9180 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`) 9181 9182 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, 9183 `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()` 9184 @*/ 9185 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg) 9186 { 9187 PetscFunctionBegin; 9188 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9189 PetscValidBoolPointer(flg, 3); 9190 9191 if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE; 9192 else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE; 9193 else { 9194 PetscUseTypeMethod(A, ishermitian, tol, flg); 9195 if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg)); 9196 } 9197 PetscFunctionReturn(PETSC_SUCCESS); 9198 } 9199 9200 /*@ 9201 MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state 9202 9203 Not Collective 9204 9205 Input Parameter: 9206 . A - the matrix to check 9207 9208 Output Parameters: 9209 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid) 9210 - flg - the result (only valid if set is `PETSC_TRUE`) 9211 9212 Level: advanced 9213 9214 Notes: 9215 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()` 9216 if you want it explicitly checked 9217 9218 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9219 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9220 9221 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9222 @*/ 9223 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9224 { 9225 PetscFunctionBegin; 9226 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9227 PetscValidBoolPointer(set, 2); 9228 PetscValidBoolPointer(flg, 3); 9229 if (A->symmetric != PETSC_BOOL3_UNKNOWN) { 9230 *set = PETSC_TRUE; 9231 *flg = PetscBool3ToBool(A->symmetric); 9232 } else { 9233 *set = PETSC_FALSE; 9234 } 9235 PetscFunctionReturn(PETSC_SUCCESS); 9236 } 9237 9238 /*@ 9239 MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state 9240 9241 Not Collective 9242 9243 Input Parameter: 9244 . A - the matrix to check 9245 9246 Output Parameters: 9247 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid) 9248 - flg - the result (only valid if set is `PETSC_TRUE`) 9249 9250 Level: advanced 9251 9252 Notes: 9253 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). 9254 9255 One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD 9256 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`) 9257 9258 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9259 @*/ 9260 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg) 9261 { 9262 PetscFunctionBegin; 9263 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9264 PetscValidBoolPointer(set, 2); 9265 PetscValidBoolPointer(flg, 3); 9266 if (A->spd != PETSC_BOOL3_UNKNOWN) { 9267 *set = PETSC_TRUE; 9268 *flg = PetscBool3ToBool(A->spd); 9269 } else { 9270 *set = PETSC_FALSE; 9271 } 9272 PetscFunctionReturn(PETSC_SUCCESS); 9273 } 9274 9275 /*@ 9276 MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state 9277 9278 Not Collective 9279 9280 Input Parameter: 9281 . A - the matrix to check 9282 9283 Output Parameters: 9284 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid) 9285 - flg - the result (only valid if set is `PETSC_TRUE`) 9286 9287 Level: advanced 9288 9289 Notes: 9290 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()` 9291 if you want it explicitly checked 9292 9293 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9294 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9295 9296 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()` 9297 @*/ 9298 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg) 9299 { 9300 PetscFunctionBegin; 9301 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9302 PetscValidBoolPointer(set, 2); 9303 PetscValidBoolPointer(flg, 3); 9304 if (A->hermitian != PETSC_BOOL3_UNKNOWN) { 9305 *set = PETSC_TRUE; 9306 *flg = PetscBool3ToBool(A->hermitian); 9307 } else { 9308 *set = PETSC_FALSE; 9309 } 9310 PetscFunctionReturn(PETSC_SUCCESS); 9311 } 9312 9313 /*@ 9314 MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric 9315 9316 Collective 9317 9318 Input Parameter: 9319 . A - the matrix to test 9320 9321 Output Parameter: 9322 . flg - the result 9323 9324 Level: intermediate 9325 9326 Notes: 9327 If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()` 9328 9329 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 9330 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9331 9332 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()` 9333 @*/ 9334 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg) 9335 { 9336 PetscFunctionBegin; 9337 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9338 PetscValidBoolPointer(flg, 2); 9339 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9340 *flg = PetscBool3ToBool(A->structurally_symmetric); 9341 } else { 9342 PetscUseTypeMethod(A, isstructurallysymmetric, flg); 9343 PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg)); 9344 } 9345 PetscFunctionReturn(PETSC_SUCCESS); 9346 } 9347 9348 /*@ 9349 MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state 9350 9351 Not Collective 9352 9353 Input Parameter: 9354 . A - the matrix to check 9355 9356 Output Parameters: 9357 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid) 9358 - flg - the result (only valid if set is PETSC_TRUE) 9359 9360 Level: advanced 9361 9362 Notes: 9363 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 9364 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9365 9366 Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation) 9367 9368 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9369 @*/ 9370 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9371 { 9372 PetscFunctionBegin; 9373 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9374 PetscValidBoolPointer(set, 2); 9375 PetscValidBoolPointer(flg, 3); 9376 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9377 *set = PETSC_TRUE; 9378 *flg = PetscBool3ToBool(A->structurally_symmetric); 9379 } else { 9380 *set = PETSC_FALSE; 9381 } 9382 PetscFunctionReturn(PETSC_SUCCESS); 9383 } 9384 9385 /*@ 9386 MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need 9387 to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process 9388 9389 Not Collective 9390 9391 Input Parameter: 9392 . mat - the matrix 9393 9394 Output Parameters: 9395 + nstash - the size of the stash 9396 . reallocs - the number of additional mallocs incurred. 9397 . bnstash - the size of the block stash 9398 - breallocs - the number of additional mallocs incurred.in the block stash 9399 9400 Level: advanced 9401 9402 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()` 9403 @*/ 9404 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs) 9405 { 9406 PetscFunctionBegin; 9407 PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs)); 9408 PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs)); 9409 PetscFunctionReturn(PETSC_SUCCESS); 9410 } 9411 9412 /*@C 9413 MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same 9414 parallel layout, `PetscLayout` for rows and columns 9415 9416 Collective 9417 9418 Input Parameter: 9419 . mat - the matrix 9420 9421 Output Parameters: 9422 + right - (optional) vector that the matrix can be multiplied against 9423 - left - (optional) vector that the matrix vector product can be stored in 9424 9425 Level: advanced 9426 9427 Notes: 9428 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()`. 9429 9430 These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed 9431 9432 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()` 9433 @*/ 9434 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left) 9435 { 9436 PetscFunctionBegin; 9437 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9438 PetscValidType(mat, 1); 9439 if (mat->ops->getvecs) { 9440 PetscUseTypeMethod(mat, getvecs, right, left); 9441 } else { 9442 PetscInt rbs, cbs; 9443 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 9444 if (right) { 9445 PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup"); 9446 PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), right)); 9447 PetscCall(VecSetSizes(*right, mat->cmap->n, PETSC_DETERMINE)); 9448 PetscCall(VecSetBlockSize(*right, cbs)); 9449 PetscCall(VecSetType(*right, mat->defaultvectype)); 9450 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9451 if (mat->boundtocpu && mat->bindingpropagates) { 9452 PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE)); 9453 PetscCall(VecBindToCPU(*right, PETSC_TRUE)); 9454 } 9455 #endif 9456 PetscCall(PetscLayoutReference(mat->cmap, &(*right)->map)); 9457 } 9458 if (left) { 9459 PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup"); 9460 PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), left)); 9461 PetscCall(VecSetSizes(*left, mat->rmap->n, PETSC_DETERMINE)); 9462 PetscCall(VecSetBlockSize(*left, rbs)); 9463 PetscCall(VecSetType(*left, mat->defaultvectype)); 9464 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9465 if (mat->boundtocpu && mat->bindingpropagates) { 9466 PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE)); 9467 PetscCall(VecBindToCPU(*left, PETSC_TRUE)); 9468 } 9469 #endif 9470 PetscCall(PetscLayoutReference(mat->rmap, &(*left)->map)); 9471 } 9472 } 9473 PetscFunctionReturn(PETSC_SUCCESS); 9474 } 9475 9476 /*@C 9477 MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure 9478 with default values. 9479 9480 Not Collective 9481 9482 Input Parameter: 9483 . info - the `MatFactorInfo` data structure 9484 9485 Level: developer 9486 9487 Notes: 9488 The solvers are generally used through the `KSP` and `PC` objects, for example 9489 `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC` 9490 9491 Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed 9492 9493 Developer Note: 9494 The Fortran interface is not autogenerated as the 9495 interface definition cannot be generated correctly [due to `MatFactorInfo`] 9496 9497 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo` 9498 @*/ 9499 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info) 9500 { 9501 PetscFunctionBegin; 9502 PetscCall(PetscMemzero(info, sizeof(MatFactorInfo))); 9503 PetscFunctionReturn(PETSC_SUCCESS); 9504 } 9505 9506 /*@ 9507 MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed 9508 9509 Collective 9510 9511 Input Parameters: 9512 + mat - the factored matrix 9513 - is - the index set defining the Schur indices (0-based) 9514 9515 Level: advanced 9516 9517 Notes: 9518 Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system. 9519 9520 You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call. 9521 9522 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9523 9524 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`, 9525 `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9526 @*/ 9527 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is) 9528 { 9529 PetscErrorCode (*f)(Mat, IS); 9530 9531 PetscFunctionBegin; 9532 PetscValidType(mat, 1); 9533 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9534 PetscValidType(is, 2); 9535 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 9536 PetscCheckSameComm(mat, 1, is, 2); 9537 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 9538 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f)); 9539 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO"); 9540 PetscCall(MatDestroy(&mat->schur)); 9541 PetscCall((*f)(mat, is)); 9542 PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created"); 9543 PetscFunctionReturn(PETSC_SUCCESS); 9544 } 9545 9546 /*@ 9547 MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step 9548 9549 Logically Collective 9550 9551 Input Parameters: 9552 + F - the factored matrix obtained by calling `MatGetFactor()` 9553 . S - location where to return the Schur complement, can be `NULL` 9554 - status - the status of the Schur complement matrix, can be `NULL` 9555 9556 Level: advanced 9557 9558 Notes: 9559 You must call `MatFactorSetSchurIS()` before calling this routine. 9560 9561 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9562 9563 The routine provides a copy of the Schur matrix stored within the solver data structures. 9564 The caller must destroy the object when it is no longer needed. 9565 If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse. 9566 9567 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) 9568 9569 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9570 9571 Developer Note: 9572 The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc 9573 matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix. 9574 9575 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9576 @*/ 9577 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9578 { 9579 PetscFunctionBegin; 9580 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9581 if (S) PetscValidPointer(S, 2); 9582 if (status) PetscValidPointer(status, 3); 9583 if (S) { 9584 PetscErrorCode (*f)(Mat, Mat *); 9585 9586 PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f)); 9587 if (f) { 9588 PetscCall((*f)(F, S)); 9589 } else { 9590 PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S)); 9591 } 9592 } 9593 if (status) *status = F->schur_status; 9594 PetscFunctionReturn(PETSC_SUCCESS); 9595 } 9596 9597 /*@ 9598 MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix 9599 9600 Logically Collective 9601 9602 Input Parameters: 9603 + F - the factored matrix obtained by calling `MatGetFactor()` 9604 . *S - location where to return the Schur complement, can be `NULL` 9605 - status - the status of the Schur complement matrix, can be `NULL` 9606 9607 Level: advanced 9608 9609 Notes: 9610 You must call `MatFactorSetSchurIS()` before calling this routine. 9611 9612 Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS` 9613 9614 The routine returns a the Schur Complement stored within the data structures of the solver. 9615 9616 If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement. 9617 9618 The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed. 9619 9620 Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix 9621 9622 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9623 9624 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9625 @*/ 9626 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9627 { 9628 PetscFunctionBegin; 9629 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9630 if (S) PetscValidPointer(S, 2); 9631 if (status) PetscValidPointer(status, 3); 9632 if (S) *S = F->schur; 9633 if (status) *status = F->schur_status; 9634 PetscFunctionReturn(PETSC_SUCCESS); 9635 } 9636 9637 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F) 9638 { 9639 Mat S = F->schur; 9640 9641 PetscFunctionBegin; 9642 switch (F->schur_status) { 9643 case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through 9644 case MAT_FACTOR_SCHUR_INVERTED: 9645 if (S) { 9646 S->ops->solve = NULL; 9647 S->ops->matsolve = NULL; 9648 S->ops->solvetranspose = NULL; 9649 S->ops->matsolvetranspose = NULL; 9650 S->ops->solveadd = NULL; 9651 S->ops->solvetransposeadd = NULL; 9652 S->factortype = MAT_FACTOR_NONE; 9653 PetscCall(PetscFree(S->solvertype)); 9654 } 9655 case MAT_FACTOR_SCHUR_FACTORED: // fall-through 9656 break; 9657 default: 9658 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9659 } 9660 PetscFunctionReturn(PETSC_SUCCESS); 9661 } 9662 9663 /*@ 9664 MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()` 9665 9666 Logically Collective 9667 9668 Input Parameters: 9669 + F - the factored matrix obtained by calling `MatGetFactor()` 9670 . *S - location where the Schur complement is stored 9671 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`) 9672 9673 Level: advanced 9674 9675 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9676 @*/ 9677 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status) 9678 { 9679 PetscFunctionBegin; 9680 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9681 if (S) { 9682 PetscValidHeaderSpecific(*S, MAT_CLASSID, 2); 9683 *S = NULL; 9684 } 9685 F->schur_status = status; 9686 PetscCall(MatFactorUpdateSchurStatus_Private(F)); 9687 PetscFunctionReturn(PETSC_SUCCESS); 9688 } 9689 9690 /*@ 9691 MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step 9692 9693 Logically Collective 9694 9695 Input Parameters: 9696 + F - the factored matrix obtained by calling `MatGetFactor()` 9697 . rhs - location where the right hand side of the Schur complement system is stored 9698 - sol - location where the solution of the Schur complement system has to be returned 9699 9700 Level: advanced 9701 9702 Notes: 9703 The sizes of the vectors should match the size of the Schur complement 9704 9705 Must be called after `MatFactorSetSchurIS()` 9706 9707 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()` 9708 @*/ 9709 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol) 9710 { 9711 PetscFunctionBegin; 9712 PetscValidType(F, 1); 9713 PetscValidType(rhs, 2); 9714 PetscValidType(sol, 3); 9715 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9716 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9717 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9718 PetscCheckSameComm(F, 1, rhs, 2); 9719 PetscCheckSameComm(F, 1, sol, 3); 9720 PetscCall(MatFactorFactorizeSchurComplement(F)); 9721 switch (F->schur_status) { 9722 case MAT_FACTOR_SCHUR_FACTORED: 9723 PetscCall(MatSolveTranspose(F->schur, rhs, sol)); 9724 break; 9725 case MAT_FACTOR_SCHUR_INVERTED: 9726 PetscCall(MatMultTranspose(F->schur, rhs, sol)); 9727 break; 9728 default: 9729 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9730 } 9731 PetscFunctionReturn(PETSC_SUCCESS); 9732 } 9733 9734 /*@ 9735 MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step 9736 9737 Logically Collective 9738 9739 Input Parameters: 9740 + F - the factored matrix obtained by calling `MatGetFactor()` 9741 . rhs - location where the right hand side of the Schur complement system is stored 9742 - sol - location where the solution of the Schur complement system has to be returned 9743 9744 Level: advanced 9745 9746 Notes: 9747 The sizes of the vectors should match the size of the Schur complement 9748 9749 Must be called after `MatFactorSetSchurIS()` 9750 9751 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()` 9752 @*/ 9753 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol) 9754 { 9755 PetscFunctionBegin; 9756 PetscValidType(F, 1); 9757 PetscValidType(rhs, 2); 9758 PetscValidType(sol, 3); 9759 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9760 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9761 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9762 PetscCheckSameComm(F, 1, rhs, 2); 9763 PetscCheckSameComm(F, 1, sol, 3); 9764 PetscCall(MatFactorFactorizeSchurComplement(F)); 9765 switch (F->schur_status) { 9766 case MAT_FACTOR_SCHUR_FACTORED: 9767 PetscCall(MatSolve(F->schur, rhs, sol)); 9768 break; 9769 case MAT_FACTOR_SCHUR_INVERTED: 9770 PetscCall(MatMult(F->schur, rhs, sol)); 9771 break; 9772 default: 9773 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9774 } 9775 PetscFunctionReturn(PETSC_SUCCESS); 9776 } 9777 9778 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat); 9779 #if PetscDefined(HAVE_CUDA) 9780 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat); 9781 #endif 9782 9783 /* Schur status updated in the interface */ 9784 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F) 9785 { 9786 Mat S = F->schur; 9787 9788 PetscFunctionBegin; 9789 if (S) { 9790 PetscMPIInt size; 9791 PetscBool isdense, isdensecuda; 9792 9793 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size)); 9794 PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented"); 9795 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense)); 9796 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda)); 9797 PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name); 9798 PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0)); 9799 if (isdense) { 9800 PetscCall(MatSeqDenseInvertFactors_Private(S)); 9801 } else if (isdensecuda) { 9802 #if defined(PETSC_HAVE_CUDA) 9803 PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S)); 9804 #endif 9805 } 9806 // HIP?????????????? 9807 PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0)); 9808 } 9809 PetscFunctionReturn(PETSC_SUCCESS); 9810 } 9811 9812 /*@ 9813 MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step 9814 9815 Logically Collective 9816 9817 Input Parameter: 9818 . F - the factored matrix obtained by calling `MatGetFactor()` 9819 9820 Level: advanced 9821 9822 Notes: 9823 Must be called after `MatFactorSetSchurIS()`. 9824 9825 Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it. 9826 9827 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()` 9828 @*/ 9829 PetscErrorCode MatFactorInvertSchurComplement(Mat F) 9830 { 9831 PetscFunctionBegin; 9832 PetscValidType(F, 1); 9833 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9834 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS); 9835 PetscCall(MatFactorFactorizeSchurComplement(F)); 9836 PetscCall(MatFactorInvertSchurComplement_Private(F)); 9837 F->schur_status = MAT_FACTOR_SCHUR_INVERTED; 9838 PetscFunctionReturn(PETSC_SUCCESS); 9839 } 9840 9841 /*@ 9842 MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step 9843 9844 Logically Collective 9845 9846 Input Parameter: 9847 . F - the factored matrix obtained by calling `MatGetFactor()` 9848 9849 Level: advanced 9850 9851 Note: 9852 Must be called after `MatFactorSetSchurIS()` 9853 9854 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()` 9855 @*/ 9856 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F) 9857 { 9858 MatFactorInfo info; 9859 9860 PetscFunctionBegin; 9861 PetscValidType(F, 1); 9862 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9863 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS); 9864 PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0)); 9865 PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo))); 9866 if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */ 9867 PetscCall(MatCholeskyFactor(F->schur, NULL, &info)); 9868 } else { 9869 PetscCall(MatLUFactor(F->schur, NULL, NULL, &info)); 9870 } 9871 PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0)); 9872 F->schur_status = MAT_FACTOR_SCHUR_FACTORED; 9873 PetscFunctionReturn(PETSC_SUCCESS); 9874 } 9875 9876 /*@ 9877 MatPtAP - Creates the matrix product C = P^T * A * P 9878 9879 Neighbor-wise Collective 9880 9881 Input Parameters: 9882 + A - the matrix 9883 . P - the projection matrix 9884 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9885 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate 9886 if the result is a dense matrix this is irrelevant 9887 9888 Output Parameter: 9889 . C - the product matrix 9890 9891 Level: intermediate 9892 9893 Notes: 9894 C will be created and must be destroyed by the user with `MatDestroy()`. 9895 9896 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9897 9898 Developer Note: 9899 For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`. 9900 9901 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()` 9902 @*/ 9903 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C) 9904 { 9905 PetscFunctionBegin; 9906 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 9907 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9908 9909 if (scall == MAT_INITIAL_MATRIX) { 9910 PetscCall(MatProductCreate(A, P, NULL, C)); 9911 PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP)); 9912 PetscCall(MatProductSetAlgorithm(*C, "default")); 9913 PetscCall(MatProductSetFill(*C, fill)); 9914 9915 (*C)->product->api_user = PETSC_TRUE; 9916 PetscCall(MatProductSetFromOptions(*C)); 9917 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); 9918 PetscCall(MatProductSymbolic(*C)); 9919 } else { /* scall == MAT_REUSE_MATRIX */ 9920 PetscCall(MatProductReplaceMats(A, P, NULL, *C)); 9921 } 9922 9923 PetscCall(MatProductNumeric(*C)); 9924 (*C)->symmetric = A->symmetric; 9925 (*C)->spd = A->spd; 9926 PetscFunctionReturn(PETSC_SUCCESS); 9927 } 9928 9929 /*@ 9930 MatRARt - Creates the matrix product C = R * A * R^T 9931 9932 Neighbor-wise Collective 9933 9934 Input Parameters: 9935 + A - the matrix 9936 . R - the projection matrix 9937 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9938 - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate 9939 if the result is a dense matrix this is irrelevant 9940 9941 Output Parameter: 9942 . C - the product matrix 9943 9944 Level: intermediate 9945 9946 Notes: 9947 C will be created and must be destroyed by the user with `MatDestroy()`. 9948 9949 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9950 9951 This routine is currently only implemented for pairs of `MATAIJ` matrices and classes 9952 which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes, 9953 parallel MatRARt is implemented via explicit transpose of R, which could be very expensive. 9954 We recommend using MatPtAP(). 9955 9956 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()` 9957 @*/ 9958 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C) 9959 { 9960 PetscFunctionBegin; 9961 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 9962 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9963 9964 if (scall == MAT_INITIAL_MATRIX) { 9965 PetscCall(MatProductCreate(A, R, NULL, C)); 9966 PetscCall(MatProductSetType(*C, MATPRODUCT_RARt)); 9967 PetscCall(MatProductSetAlgorithm(*C, "default")); 9968 PetscCall(MatProductSetFill(*C, fill)); 9969 9970 (*C)->product->api_user = PETSC_TRUE; 9971 PetscCall(MatProductSetFromOptions(*C)); 9972 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); 9973 PetscCall(MatProductSymbolic(*C)); 9974 } else { /* scall == MAT_REUSE_MATRIX */ 9975 PetscCall(MatProductReplaceMats(A, R, NULL, *C)); 9976 } 9977 9978 PetscCall(MatProductNumeric(*C)); 9979 if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 9980 PetscFunctionReturn(PETSC_SUCCESS); 9981 } 9982 9983 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C) 9984 { 9985 PetscFunctionBegin; 9986 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9987 9988 if (scall == MAT_INITIAL_MATRIX) { 9989 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype])); 9990 PetscCall(MatProductCreate(A, B, NULL, C)); 9991 PetscCall(MatProductSetType(*C, ptype)); 9992 PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT)); 9993 PetscCall(MatProductSetFill(*C, fill)); 9994 9995 (*C)->product->api_user = PETSC_TRUE; 9996 PetscCall(MatProductSetFromOptions(*C)); 9997 PetscCall(MatProductSymbolic(*C)); 9998 } else { /* scall == MAT_REUSE_MATRIX */ 9999 Mat_Product *product = (*C)->product; 10000 PetscBool isdense; 10001 10002 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, "")); 10003 if (isdense && product && product->type != ptype) { 10004 PetscCall(MatProductClear(*C)); 10005 product = NULL; 10006 } 10007 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype])); 10008 if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */ 10009 PetscCheck(isdense, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first"); 10010 PetscCall(MatProductCreate_Private(A, B, NULL, *C)); 10011 product = (*C)->product; 10012 product->fill = fill; 10013 product->api_user = PETSC_TRUE; 10014 product->clear = PETSC_TRUE; 10015 10016 PetscCall(MatProductSetType(*C, ptype)); 10017 PetscCall(MatProductSetFromOptions(*C)); 10018 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); 10019 PetscCall(MatProductSymbolic(*C)); 10020 } else { /* user may change input matrices A or B when REUSE */ 10021 PetscCall(MatProductReplaceMats(A, B, NULL, *C)); 10022 } 10023 } 10024 PetscCall(MatProductNumeric(*C)); 10025 PetscFunctionReturn(PETSC_SUCCESS); 10026 } 10027 10028 /*@ 10029 MatMatMult - Performs matrix-matrix multiplication C=A*B. 10030 10031 Neighbor-wise Collective 10032 10033 Input Parameters: 10034 + A - the left matrix 10035 . B - the right matrix 10036 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10037 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate 10038 if the result is a dense matrix this is irrelevant 10039 10040 Output Parameter: 10041 . C - the product matrix 10042 10043 Notes: 10044 Unless scall is `MAT_REUSE_MATRIX` C will be created. 10045 10046 `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 10047 call to this function with `MAT_INITIAL_MATRIX`. 10048 10049 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed. 10050 10051 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`, 10052 rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse. 10053 10054 Example of Usage: 10055 .vb 10056 MatProductCreate(A,B,NULL,&C); 10057 MatProductSetType(C,MATPRODUCT_AB); 10058 MatProductSymbolic(C); 10059 MatProductNumeric(C); // compute C=A * B 10060 MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1 10061 MatProductNumeric(C); 10062 MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1 10063 MatProductNumeric(C); 10064 .ve 10065 10066 Level: intermediate 10067 10068 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()` 10069 @*/ 10070 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10071 { 10072 PetscFunctionBegin; 10073 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C)); 10074 PetscFunctionReturn(PETSC_SUCCESS); 10075 } 10076 10077 /*@ 10078 MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T. 10079 10080 Neighbor-wise Collective 10081 10082 Input Parameters: 10083 + A - the left matrix 10084 . B - the right matrix 10085 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10086 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 10087 10088 Output Parameter: 10089 . C - the product matrix 10090 10091 Level: intermediate 10092 10093 Notes: 10094 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10095 10096 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call 10097 10098 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10099 actually needed. 10100 10101 This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class, 10102 and for pairs of `MATMPIDENSE` matrices. 10103 10104 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt` 10105 10106 Options Database Keys: 10107 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the 10108 first redundantly copies the transposed B matrix on each process and requires O(log P) communication complexity; 10109 the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity. 10110 10111 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductCreate()`, `MatProductAlgorithm`, `MatProductType`, `MATPRODUCT_ABt` 10112 @*/ 10113 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10114 { 10115 PetscFunctionBegin; 10116 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C)); 10117 if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10118 PetscFunctionReturn(PETSC_SUCCESS); 10119 } 10120 10121 /*@ 10122 MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B. 10123 10124 Neighbor-wise Collective 10125 10126 Input Parameters: 10127 + A - the left matrix 10128 . B - the right matrix 10129 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10130 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 10131 10132 Output Parameter: 10133 . C - the product matrix 10134 10135 Level: intermediate 10136 10137 Notes: 10138 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10139 10140 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call. 10141 10142 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB` 10143 10144 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10145 actually needed. 10146 10147 This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes 10148 which inherit from `MATSEQAIJ`. C will be of the same type as the input matrices. 10149 10150 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()` 10151 @*/ 10152 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10153 { 10154 PetscFunctionBegin; 10155 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C)); 10156 PetscFunctionReturn(PETSC_SUCCESS); 10157 } 10158 10159 /*@ 10160 MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C. 10161 10162 Neighbor-wise Collective 10163 10164 Input Parameters: 10165 + A - the left matrix 10166 . B - the middle matrix 10167 . C - the right matrix 10168 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10169 - 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 10170 if the result is a dense matrix this is irrelevant 10171 10172 Output Parameter: 10173 . D - the product matrix 10174 10175 Level: intermediate 10176 10177 Notes: 10178 Unless scall is `MAT_REUSE_MATRIX` D will be created. 10179 10180 `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call 10181 10182 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC` 10183 10184 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10185 actually needed. 10186 10187 If you have many matrices with the same non-zero structure to multiply, you 10188 should use `MAT_REUSE_MATRIX` in all calls but the first 10189 10190 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()` 10191 @*/ 10192 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D) 10193 { 10194 PetscFunctionBegin; 10195 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6); 10196 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10197 10198 if (scall == MAT_INITIAL_MATRIX) { 10199 PetscCall(MatProductCreate(A, B, C, D)); 10200 PetscCall(MatProductSetType(*D, MATPRODUCT_ABC)); 10201 PetscCall(MatProductSetAlgorithm(*D, "default")); 10202 PetscCall(MatProductSetFill(*D, fill)); 10203 10204 (*D)->product->api_user = PETSC_TRUE; 10205 PetscCall(MatProductSetFromOptions(*D)); 10206 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, 10207 ((PetscObject)C)->type_name); 10208 PetscCall(MatProductSymbolic(*D)); 10209 } else { /* user may change input matrices when REUSE */ 10210 PetscCall(MatProductReplaceMats(A, B, C, *D)); 10211 } 10212 PetscCall(MatProductNumeric(*D)); 10213 PetscFunctionReturn(PETSC_SUCCESS); 10214 } 10215 10216 /*@ 10217 MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators. 10218 10219 Collective 10220 10221 Input Parameters: 10222 + mat - the matrix 10223 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices) 10224 . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used) 10225 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10226 10227 Output Parameter: 10228 . matredundant - redundant matrix 10229 10230 Level: advanced 10231 10232 Notes: 10233 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 10234 original matrix has not changed from that last call to MatCreateRedundantMatrix(). 10235 10236 This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before 10237 calling it. 10238 10239 `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be. 10240 10241 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubComm` 10242 @*/ 10243 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant) 10244 { 10245 MPI_Comm comm; 10246 PetscMPIInt size; 10247 PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs; 10248 Mat_Redundant *redund = NULL; 10249 PetscSubcomm psubcomm = NULL; 10250 MPI_Comm subcomm_in = subcomm; 10251 Mat *matseq; 10252 IS isrow, iscol; 10253 PetscBool newsubcomm = PETSC_FALSE; 10254 10255 PetscFunctionBegin; 10256 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10257 if (nsubcomm && reuse == MAT_REUSE_MATRIX) { 10258 PetscValidPointer(*matredundant, 5); 10259 PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5); 10260 } 10261 10262 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10263 if (size == 1 || nsubcomm == 1) { 10264 if (reuse == MAT_INITIAL_MATRIX) { 10265 PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant)); 10266 } else { 10267 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"); 10268 PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN)); 10269 } 10270 PetscFunctionReturn(PETSC_SUCCESS); 10271 } 10272 10273 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10274 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10275 MatCheckPreallocated(mat, 1); 10276 10277 PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0)); 10278 if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */ 10279 /* create psubcomm, then get subcomm */ 10280 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10281 PetscCallMPI(MPI_Comm_size(comm, &size)); 10282 PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size); 10283 10284 PetscCall(PetscSubcommCreate(comm, &psubcomm)); 10285 PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm)); 10286 PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS)); 10287 PetscCall(PetscSubcommSetFromOptions(psubcomm)); 10288 PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL)); 10289 newsubcomm = PETSC_TRUE; 10290 PetscCall(PetscSubcommDestroy(&psubcomm)); 10291 } 10292 10293 /* get isrow, iscol and a local sequential matrix matseq[0] */ 10294 if (reuse == MAT_INITIAL_MATRIX) { 10295 mloc_sub = PETSC_DECIDE; 10296 nloc_sub = PETSC_DECIDE; 10297 if (bs < 1) { 10298 PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M)); 10299 PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N)); 10300 } else { 10301 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M)); 10302 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N)); 10303 } 10304 PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm)); 10305 rstart = rend - mloc_sub; 10306 PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow)); 10307 PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol)); 10308 } else { /* reuse == MAT_REUSE_MATRIX */ 10309 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"); 10310 /* retrieve subcomm */ 10311 PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm)); 10312 redund = (*matredundant)->redundant; 10313 isrow = redund->isrow; 10314 iscol = redund->iscol; 10315 matseq = redund->matseq; 10316 } 10317 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq)); 10318 10319 /* get matredundant over subcomm */ 10320 if (reuse == MAT_INITIAL_MATRIX) { 10321 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant)); 10322 10323 /* create a supporting struct and attach it to C for reuse */ 10324 PetscCall(PetscNew(&redund)); 10325 (*matredundant)->redundant = redund; 10326 redund->isrow = isrow; 10327 redund->iscol = iscol; 10328 redund->matseq = matseq; 10329 if (newsubcomm) { 10330 redund->subcomm = subcomm; 10331 } else { 10332 redund->subcomm = MPI_COMM_NULL; 10333 } 10334 } else { 10335 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant)); 10336 } 10337 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 10338 if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) { 10339 PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE)); 10340 PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE)); 10341 } 10342 #endif 10343 PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0)); 10344 PetscFunctionReturn(PETSC_SUCCESS); 10345 } 10346 10347 /*@C 10348 MatGetMultiProcBlock - Create multiple 'parallel submatrices' from 10349 a given `Mat`. Each submatrix can span multiple procs. 10350 10351 Collective 10352 10353 Input Parameters: 10354 + mat - the matrix 10355 . subcomm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))` 10356 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10357 10358 Output Parameter: 10359 . subMat - parallel sub-matrices each spanning a given `subcomm` 10360 10361 Level: advanced 10362 10363 Notes: 10364 The submatrix partition across processors is dictated by `subComm` a 10365 communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm` 10366 is not restricted to be grouped with consecutive original ranks. 10367 10368 Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices 10369 map directly to the layout of the original matrix [wrt the local 10370 row,col partitioning]. So the original 'DiagonalMat' naturally maps 10371 into the 'DiagonalMat' of the `subMat`, hence it is used directly from 10372 the `subMat`. However the offDiagMat looses some columns - and this is 10373 reconstructed with `MatSetValues()` 10374 10375 This is used by `PCBJACOBI` when a single block spans multiple MPI processes. 10376 10377 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI` 10378 @*/ 10379 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) 10380 { 10381 PetscMPIInt commsize, subCommSize; 10382 10383 PetscFunctionBegin; 10384 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize)); 10385 PetscCallMPI(MPI_Comm_size(subComm, &subCommSize)); 10386 PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize); 10387 10388 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"); 10389 PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10390 PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat); 10391 PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10392 PetscFunctionReturn(PETSC_SUCCESS); 10393 } 10394 10395 /*@ 10396 MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering 10397 10398 Not Collective 10399 10400 Input Parameters: 10401 + mat - matrix to extract local submatrix from 10402 . isrow - local row indices for submatrix 10403 - iscol - local column indices for submatrix 10404 10405 Output Parameter: 10406 . submat - the submatrix 10407 10408 Level: intermediate 10409 10410 Notes: 10411 `submat` should be disposed of with `MatRestoreLocalSubMatrix()`. 10412 10413 Depending on the format of `mat`, the returned submat may not implement `MatMult()`. Its communicator may be 10414 the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of `mat`'s. 10415 10416 `submat` always implements `MatSetValuesLocal()`. If `isrow` and `iscol` have the same block size, then 10417 `MatSetValuesBlockedLocal()` will also be implemented. 10418 10419 `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`. 10420 Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided. 10421 10422 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()` 10423 @*/ 10424 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10425 { 10426 PetscFunctionBegin; 10427 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10428 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10429 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10430 PetscCheckSameComm(isrow, 2, iscol, 3); 10431 PetscValidPointer(submat, 4); 10432 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call"); 10433 10434 if (mat->ops->getlocalsubmatrix) { 10435 PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat); 10436 } else { 10437 PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat)); 10438 } 10439 PetscFunctionReturn(PETSC_SUCCESS); 10440 } 10441 10442 /*@ 10443 MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()` 10444 10445 Not Collective 10446 10447 Input Parameters: 10448 + mat - matrix to extract local submatrix from 10449 . isrow - local row indices for submatrix 10450 . iscol - local column indices for submatrix 10451 - submat - the submatrix 10452 10453 Level: intermediate 10454 10455 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()` 10456 @*/ 10457 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10458 { 10459 PetscFunctionBegin; 10460 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10461 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10462 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10463 PetscCheckSameComm(isrow, 2, iscol, 3); 10464 PetscValidPointer(submat, 4); 10465 if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4); 10466 10467 if (mat->ops->restorelocalsubmatrix) { 10468 PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat); 10469 } else { 10470 PetscCall(MatDestroy(submat)); 10471 } 10472 *submat = NULL; 10473 PetscFunctionReturn(PETSC_SUCCESS); 10474 } 10475 10476 /*@ 10477 MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix 10478 10479 Collective 10480 10481 Input Parameter: 10482 . mat - the matrix 10483 10484 Output Parameter: 10485 . is - if any rows have zero diagonals this contains the list of them 10486 10487 Level: developer 10488 10489 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10490 @*/ 10491 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is) 10492 { 10493 PetscFunctionBegin; 10494 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10495 PetscValidType(mat, 1); 10496 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10497 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10498 10499 if (!mat->ops->findzerodiagonals) { 10500 Vec diag; 10501 const PetscScalar *a; 10502 PetscInt *rows; 10503 PetscInt rStart, rEnd, r, nrow = 0; 10504 10505 PetscCall(MatCreateVecs(mat, &diag, NULL)); 10506 PetscCall(MatGetDiagonal(mat, diag)); 10507 PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd)); 10508 PetscCall(VecGetArrayRead(diag, &a)); 10509 for (r = 0; r < rEnd - rStart; ++r) 10510 if (a[r] == 0.0) ++nrow; 10511 PetscCall(PetscMalloc1(nrow, &rows)); 10512 nrow = 0; 10513 for (r = 0; r < rEnd - rStart; ++r) 10514 if (a[r] == 0.0) rows[nrow++] = r + rStart; 10515 PetscCall(VecRestoreArrayRead(diag, &a)); 10516 PetscCall(VecDestroy(&diag)); 10517 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is)); 10518 } else { 10519 PetscUseTypeMethod(mat, findzerodiagonals, is); 10520 } 10521 PetscFunctionReturn(PETSC_SUCCESS); 10522 } 10523 10524 /*@ 10525 MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size) 10526 10527 Collective 10528 10529 Input Parameter: 10530 . mat - the matrix 10531 10532 Output Parameter: 10533 . is - contains the list of rows with off block diagonal entries 10534 10535 Level: developer 10536 10537 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10538 @*/ 10539 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is) 10540 { 10541 PetscFunctionBegin; 10542 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10543 PetscValidType(mat, 1); 10544 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10545 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10546 10547 PetscUseTypeMethod(mat, findoffblockdiagonalentries, is); 10548 PetscFunctionReturn(PETSC_SUCCESS); 10549 } 10550 10551 /*@C 10552 MatInvertBlockDiagonal - Inverts the block diagonal entries. 10553 10554 Collective; No Fortran Support 10555 10556 Input Parameter: 10557 . mat - the matrix 10558 10559 Output Parameter: 10560 . values - the block inverses in column major order (FORTRAN-like) 10561 10562 Level: advanced 10563 10564 Notes: 10565 The size of the blocks is determined by the block size of the matrix. 10566 10567 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10568 10569 The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size 10570 10571 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()` 10572 @*/ 10573 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values) 10574 { 10575 PetscFunctionBegin; 10576 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10577 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10578 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10579 PetscUseTypeMethod(mat, invertblockdiagonal, values); 10580 PetscFunctionReturn(PETSC_SUCCESS); 10581 } 10582 10583 /*@C 10584 MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries. 10585 10586 Collective; No Fortran Support 10587 10588 Input Parameters: 10589 + mat - the matrix 10590 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()` 10591 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()` 10592 10593 Output Parameter: 10594 . values - the block inverses in column major order (FORTRAN-like) 10595 10596 Level: advanced 10597 10598 Notes: 10599 Use `MatInvertBlockDiagonal()` if all blocks have the same size 10600 10601 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10602 10603 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()` 10604 @*/ 10605 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values) 10606 { 10607 PetscFunctionBegin; 10608 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10609 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10610 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10611 PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values); 10612 PetscFunctionReturn(PETSC_SUCCESS); 10613 } 10614 10615 /*@ 10616 MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A 10617 10618 Collective 10619 10620 Input Parameters: 10621 + A - the matrix 10622 - C - matrix with inverted block diagonal of `A`. This matrix should be created and may have its type set. 10623 10624 Level: advanced 10625 10626 Note: 10627 The blocksize of the matrix is used to determine the blocks on the diagonal of `C` 10628 10629 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()` 10630 @*/ 10631 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C) 10632 { 10633 const PetscScalar *vals; 10634 PetscInt *dnnz; 10635 PetscInt m, rstart, rend, bs, i, j; 10636 10637 PetscFunctionBegin; 10638 PetscCall(MatInvertBlockDiagonal(A, &vals)); 10639 PetscCall(MatGetBlockSize(A, &bs)); 10640 PetscCall(MatGetLocalSize(A, &m, NULL)); 10641 PetscCall(MatSetLayouts(C, A->rmap, A->cmap)); 10642 PetscCall(PetscMalloc1(m / bs, &dnnz)); 10643 for (j = 0; j < m / bs; j++) dnnz[j] = 1; 10644 PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL)); 10645 PetscCall(PetscFree(dnnz)); 10646 PetscCall(MatGetOwnershipRange(C, &rstart, &rend)); 10647 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE)); 10648 for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES)); 10649 PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 10650 PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 10651 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE)); 10652 PetscFunctionReturn(PETSC_SUCCESS); 10653 } 10654 10655 /*@C 10656 MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created 10657 via `MatTransposeColoringCreate()`. 10658 10659 Collective 10660 10661 Input Parameter: 10662 . c - coloring context 10663 10664 Level: intermediate 10665 10666 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()` 10667 @*/ 10668 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c) 10669 { 10670 MatTransposeColoring matcolor = *c; 10671 10672 PetscFunctionBegin; 10673 if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS); 10674 if (--((PetscObject)matcolor)->refct > 0) { 10675 matcolor = NULL; 10676 PetscFunctionReturn(PETSC_SUCCESS); 10677 } 10678 10679 PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow)); 10680 PetscCall(PetscFree(matcolor->rows)); 10681 PetscCall(PetscFree(matcolor->den2sp)); 10682 PetscCall(PetscFree(matcolor->colorforcol)); 10683 PetscCall(PetscFree(matcolor->columns)); 10684 if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart)); 10685 PetscCall(PetscHeaderDestroy(c)); 10686 PetscFunctionReturn(PETSC_SUCCESS); 10687 } 10688 10689 /*@C 10690 MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which 10691 a `MatTransposeColoring` context has been created, computes a dense B^T by applying 10692 `MatTransposeColoring` to sparse B. 10693 10694 Collective 10695 10696 Input Parameters: 10697 + coloring - coloring context created with `MatTransposeColoringCreate()` 10698 - B - sparse matrix 10699 10700 Output Parameter: 10701 . Btdense - dense matrix B^T 10702 10703 Level: developer 10704 10705 Note: 10706 These are used internally for some implementations of `MatRARt()` 10707 10708 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()` 10709 @*/ 10710 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense) 10711 { 10712 PetscFunctionBegin; 10713 PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10714 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 10715 PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3); 10716 10717 PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense)); 10718 PetscFunctionReturn(PETSC_SUCCESS); 10719 } 10720 10721 /*@C 10722 MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which 10723 a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense 10724 in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix 10725 `Csp` from `Cden`. 10726 10727 Collective 10728 10729 Input Parameters: 10730 + matcoloring - coloring context created with `MatTransposeColoringCreate()` 10731 - Cden - matrix product of a sparse matrix and a dense matrix Btdense 10732 10733 Output Parameter: 10734 . Csp - sparse matrix 10735 10736 Level: developer 10737 10738 Note: 10739 These are used internally for some implementations of `MatRARt()` 10740 10741 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()` 10742 @*/ 10743 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp) 10744 { 10745 PetscFunctionBegin; 10746 PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10747 PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2); 10748 PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3); 10749 10750 PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp)); 10751 PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY)); 10752 PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY)); 10753 PetscFunctionReturn(PETSC_SUCCESS); 10754 } 10755 10756 /*@C 10757 MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T. 10758 10759 Collective 10760 10761 Input Parameters: 10762 + mat - the matrix product C 10763 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()` 10764 10765 Output Parameter: 10766 . color - the new coloring context 10767 10768 Level: intermediate 10769 10770 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`, 10771 `MatTransColoringApplyDenToSp()` 10772 @*/ 10773 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color) 10774 { 10775 MatTransposeColoring c; 10776 MPI_Comm comm; 10777 10778 PetscFunctionBegin; 10779 PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10780 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10781 PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL)); 10782 10783 c->ctype = iscoloring->ctype; 10784 PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c); 10785 10786 *color = c; 10787 PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10788 PetscFunctionReturn(PETSC_SUCCESS); 10789 } 10790 10791 /*@ 10792 MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the 10793 matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the 10794 same, otherwise it will be larger 10795 10796 Not Collective 10797 10798 Input Parameter: 10799 . A - the matrix 10800 10801 Output Parameter: 10802 . state - the current state 10803 10804 Level: intermediate 10805 10806 Notes: 10807 You can only compare states from two different calls to the SAME matrix, you cannot compare calls between 10808 different matrices 10809 10810 Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix 10811 10812 Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers. 10813 10814 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()` 10815 @*/ 10816 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state) 10817 { 10818 PetscFunctionBegin; 10819 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10820 *state = mat->nonzerostate; 10821 PetscFunctionReturn(PETSC_SUCCESS); 10822 } 10823 10824 /*@ 10825 MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential 10826 matrices from each processor 10827 10828 Collective 10829 10830 Input Parameters: 10831 + comm - the communicators the parallel matrix will live on 10832 . seqmat - the input sequential matrices 10833 . n - number of local columns (or `PETSC_DECIDE`) 10834 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10835 10836 Output Parameter: 10837 . mpimat - the parallel matrix generated 10838 10839 Level: developer 10840 10841 Note: 10842 The number of columns of the matrix in EACH processor MUST be the same. 10843 10844 .seealso: [](ch_matrices), `Mat` 10845 @*/ 10846 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat) 10847 { 10848 PetscMPIInt size; 10849 10850 PetscFunctionBegin; 10851 PetscCallMPI(MPI_Comm_size(comm, &size)); 10852 if (size == 1) { 10853 if (reuse == MAT_INITIAL_MATRIX) { 10854 PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat)); 10855 } else { 10856 PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN)); 10857 } 10858 PetscFunctionReturn(PETSC_SUCCESS); 10859 } 10860 10861 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"); 10862 10863 PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0)); 10864 PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat)); 10865 PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0)); 10866 PetscFunctionReturn(PETSC_SUCCESS); 10867 } 10868 10869 /*@ 10870 MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI ranks' ownership ranges. 10871 10872 Collective 10873 10874 Input Parameters: 10875 + A - the matrix to create subdomains from 10876 - N - requested number of subdomains 10877 10878 Output Parameters: 10879 + n - number of subdomains resulting on this MPI process 10880 - iss - `IS` list with indices of subdomains on this MPI process 10881 10882 Level: advanced 10883 10884 Note: 10885 The number of subdomains must be smaller than the communicator size 10886 10887 .seealso: [](ch_matrices), `Mat`, `IS` 10888 @*/ 10889 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[]) 10890 { 10891 MPI_Comm comm, subcomm; 10892 PetscMPIInt size, rank, color; 10893 PetscInt rstart, rend, k; 10894 10895 PetscFunctionBegin; 10896 PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 10897 PetscCallMPI(MPI_Comm_size(comm, &size)); 10898 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 10899 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); 10900 *n = 1; 10901 k = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */ 10902 color = rank / k; 10903 PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm)); 10904 PetscCall(PetscMalloc1(1, iss)); 10905 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 10906 PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0])); 10907 PetscCallMPI(MPI_Comm_free(&subcomm)); 10908 PetscFunctionReturn(PETSC_SUCCESS); 10909 } 10910 10911 /*@ 10912 MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection. 10913 10914 If the interpolation and restriction operators are the same, uses `MatPtAP()`. 10915 If they are not the same, uses `MatMatMatMult()`. 10916 10917 Once the coarse grid problem is constructed, correct for interpolation operators 10918 that are not of full rank, which can legitimately happen in the case of non-nested 10919 geometric multigrid. 10920 10921 Input Parameters: 10922 + restrct - restriction operator 10923 . dA - fine grid matrix 10924 . interpolate - interpolation operator 10925 . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10926 - fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate 10927 10928 Output Parameter: 10929 . A - the Galerkin coarse matrix 10930 10931 Options Database Key: 10932 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used 10933 10934 Level: developer 10935 10936 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()` 10937 @*/ 10938 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A) 10939 { 10940 IS zerorows; 10941 Vec diag; 10942 10943 PetscFunctionBegin; 10944 PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10945 /* Construct the coarse grid matrix */ 10946 if (interpolate == restrct) { 10947 PetscCall(MatPtAP(dA, interpolate, reuse, fill, A)); 10948 } else { 10949 PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A)); 10950 } 10951 10952 /* If the interpolation matrix is not of full rank, A will have zero rows. 10953 This can legitimately happen in the case of non-nested geometric multigrid. 10954 In that event, we set the rows of the matrix to the rows of the identity, 10955 ignoring the equations (as the RHS will also be zero). */ 10956 10957 PetscCall(MatFindZeroRows(*A, &zerorows)); 10958 10959 if (zerorows != NULL) { /* if there are any zero rows */ 10960 PetscCall(MatCreateVecs(*A, &diag, NULL)); 10961 PetscCall(MatGetDiagonal(*A, diag)); 10962 PetscCall(VecISSet(diag, zerorows, 1.0)); 10963 PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES)); 10964 PetscCall(VecDestroy(&diag)); 10965 PetscCall(ISDestroy(&zerorows)); 10966 } 10967 PetscFunctionReturn(PETSC_SUCCESS); 10968 } 10969 10970 /*@C 10971 MatSetOperation - Allows user to set a matrix operation for any matrix type 10972 10973 Logically Collective 10974 10975 Input Parameters: 10976 + mat - the matrix 10977 . op - the name of the operation 10978 - f - the function that provides the operation 10979 10980 Level: developer 10981 10982 Usage: 10983 .vb 10984 extern PetscErrorCode usermult(Mat, Vec, Vec); 10985 10986 PetscCall(MatCreateXXX(comm, ..., &A)); 10987 PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFunction)usermult)); 10988 .ve 10989 10990 Notes: 10991 See the file `include/petscmat.h` for a complete list of matrix 10992 operations, which all have the form MATOP_<OPERATION>, where 10993 <OPERATION> is the name (in all capital letters) of the 10994 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 10995 10996 All user-provided functions (except for `MATOP_DESTROY`) should have the same calling 10997 sequence as the usual matrix interface routines, since they 10998 are intended to be accessed via the usual matrix interface 10999 routines, e.g., 11000 .vb 11001 MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec) 11002 .ve 11003 11004 In particular each function MUST return `PETSC_SUCCESS` on success and 11005 nonzero on failure. 11006 11007 This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type. 11008 11009 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()` 11010 @*/ 11011 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void)) 11012 { 11013 PetscFunctionBegin; 11014 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11015 if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view; 11016 (((void (**)(void))mat->ops)[op]) = f; 11017 PetscFunctionReturn(PETSC_SUCCESS); 11018 } 11019 11020 /*@C 11021 MatGetOperation - Gets a matrix operation for any matrix type. 11022 11023 Not Collective 11024 11025 Input Parameters: 11026 + mat - the matrix 11027 - op - the name of the operation 11028 11029 Output Parameter: 11030 . f - the function that provides the operation 11031 11032 Level: developer 11033 11034 Usage: 11035 .vb 11036 PetscErrorCode (*usermult)(Mat, Vec, Vec); 11037 MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult); 11038 .ve 11039 11040 Notes: 11041 See the file include/petscmat.h for a complete list of matrix 11042 operations, which all have the form MATOP_<OPERATION>, where 11043 <OPERATION> is the name (in all capital letters) of the 11044 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11045 11046 This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type. 11047 11048 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()` 11049 @*/ 11050 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void)) 11051 { 11052 PetscFunctionBegin; 11053 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11054 *f = (((void (**)(void))mat->ops)[op]); 11055 PetscFunctionReturn(PETSC_SUCCESS); 11056 } 11057 11058 /*@ 11059 MatHasOperation - Determines whether the given matrix supports the particular operation. 11060 11061 Not Collective 11062 11063 Input Parameters: 11064 + mat - the matrix 11065 - op - the operation, for example, `MATOP_GET_DIAGONAL` 11066 11067 Output Parameter: 11068 . has - either `PETSC_TRUE` or `PETSC_FALSE` 11069 11070 Level: advanced 11071 11072 Note: 11073 See `MatSetOperation()` for additional discussion on naming convention and usage of `op`. 11074 11075 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()` 11076 @*/ 11077 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has) 11078 { 11079 PetscFunctionBegin; 11080 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11081 PetscValidBoolPointer(has, 3); 11082 if (mat->ops->hasoperation) { 11083 PetscUseTypeMethod(mat, hasoperation, op, has); 11084 } else { 11085 if (((void **)mat->ops)[op]) *has = PETSC_TRUE; 11086 else { 11087 *has = PETSC_FALSE; 11088 if (op == MATOP_CREATE_SUBMATRIX) { 11089 PetscMPIInt size; 11090 11091 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 11092 if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has)); 11093 } 11094 } 11095 } 11096 PetscFunctionReturn(PETSC_SUCCESS); 11097 } 11098 11099 /*@ 11100 MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent 11101 11102 Collective 11103 11104 Input Parameter: 11105 . mat - the matrix 11106 11107 Output Parameter: 11108 . cong - either `PETSC_TRUE` or `PETSC_FALSE` 11109 11110 Level: beginner 11111 11112 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout` 11113 @*/ 11114 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong) 11115 { 11116 PetscFunctionBegin; 11117 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11118 PetscValidType(mat, 1); 11119 PetscValidBoolPointer(cong, 2); 11120 if (!mat->rmap || !mat->cmap) { 11121 *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE; 11122 PetscFunctionReturn(PETSC_SUCCESS); 11123 } 11124 if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */ 11125 PetscCall(PetscLayoutSetUp(mat->rmap)); 11126 PetscCall(PetscLayoutSetUp(mat->cmap)); 11127 PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong)); 11128 if (*cong) mat->congruentlayouts = 1; 11129 else mat->congruentlayouts = 0; 11130 } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE; 11131 PetscFunctionReturn(PETSC_SUCCESS); 11132 } 11133 11134 PetscErrorCode MatSetInf(Mat A) 11135 { 11136 PetscFunctionBegin; 11137 PetscUseTypeMethod(A, setinf); 11138 PetscFunctionReturn(PETSC_SUCCESS); 11139 } 11140 11141 /*@C 11142 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 11143 and possibly removes small values from the graph structure. 11144 11145 Collective 11146 11147 Input Parameters: 11148 + A - the matrix 11149 . sym - `PETSC_TRUE` indicates that the graph should be symmetrized 11150 . scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry 11151 - filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value 11152 11153 Output Parameter: 11154 . graph - the resulting graph 11155 11156 Level: advanced 11157 11158 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG` 11159 @*/ 11160 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph) 11161 { 11162 PetscFunctionBegin; 11163 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11164 PetscValidType(A, 1); 11165 PetscValidLogicalCollectiveBool(A, scale, 3); 11166 PetscValidPointer(graph, 5); 11167 PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph); 11168 PetscFunctionReturn(PETSC_SUCCESS); 11169 } 11170 11171 /*@ 11172 MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place, 11173 meaning the same memory is used for the matrix, and no new memory is allocated. 11174 11175 Collective 11176 11177 Input Parameter: 11178 . A - the matrix 11179 11180 Level: intermediate 11181 11182 Developer Note: 11183 The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end 11184 of the arrays in the data structure are unneeded. 11185 11186 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatChop()` 11187 @*/ 11188 PetscErrorCode MatEliminateZeros(Mat A) 11189 { 11190 PetscFunctionBegin; 11191 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11192 PetscUseTypeMethod(A, eliminatezeros); 11193 PetscFunctionReturn(PETSC_SUCCESS); 11194 } 11195