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: [](chapter_matrices), `Mat`, `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomCreate()`, `PetscRandomDestroy()` 77 @*/ 78 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx) 79 { 80 PetscRandom randObj = NULL; 81 82 PetscFunctionBegin; 83 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 84 if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2); 85 PetscValidType(x, 1); 86 MatCheckPreallocated(x, 1); 87 88 if (!rctx) { 89 MPI_Comm comm; 90 PetscCall(PetscObjectGetComm((PetscObject)x, &comm)); 91 PetscCall(PetscRandomCreate(comm, &randObj)); 92 PetscCall(PetscRandomSetType(randObj, x->defaultrandtype)); 93 PetscCall(PetscRandomSetFromOptions(randObj)); 94 rctx = randObj; 95 } 96 PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0)); 97 PetscUseTypeMethod(x, setrandom, rctx); 98 PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0)); 99 100 PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY)); 101 PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY)); 102 PetscCall(PetscRandomDestroy(&randObj)); 103 PetscFunctionReturn(PETSC_SUCCESS); 104 } 105 106 /*@ 107 MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in 108 109 Logically Collective 110 111 Input Parameter: 112 . mat - the factored matrix 113 114 Output Parameters: 115 + pivot - the pivot value computed 116 - row - the row that the zero pivot occurred. This row value must be interpreted carefully due to row reorderings and which processes 117 the share the matrix 118 119 Level: advanced 120 121 Notes: 122 This routine does not work for factorizations done with external packages. 123 124 This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT` 125 126 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 127 128 .seealso: [](chapter_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, 129 `MAT_FACTOR_NUMERIC_ZEROPIVOT` 130 @*/ 131 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row) 132 { 133 PetscFunctionBegin; 134 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 135 PetscValidRealPointer(pivot, 2); 136 PetscValidIntPointer(row, 3); 137 *pivot = mat->factorerror_zeropivot_value; 138 *row = mat->factorerror_zeropivot_row; 139 PetscFunctionReturn(PETSC_SUCCESS); 140 } 141 142 /*@ 143 MatFactorGetError - gets the error code from a factorization 144 145 Logically Collective 146 147 Input Parameter: 148 . mat - the factored matrix 149 150 Output Parameter: 151 . err - the error code 152 153 Level: advanced 154 155 Note: 156 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 157 158 .seealso: [](chapter_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, 159 `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, `MatFactorError` 160 @*/ 161 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err) 162 { 163 PetscFunctionBegin; 164 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 165 PetscValidPointer(err, 2); 166 *err = mat->factorerrortype; 167 PetscFunctionReturn(PETSC_SUCCESS); 168 } 169 170 /*@ 171 MatFactorClearError - clears the error code in a factorization 172 173 Logically Collective 174 175 Input Parameter: 176 . mat - the factored matrix 177 178 Level: developer 179 180 Note: 181 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 182 183 .seealso: [](chapter_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`, 184 `MatGetErrorCode()`, `MatFactorError` 185 @*/ 186 PetscErrorCode MatFactorClearError(Mat mat) 187 { 188 PetscFunctionBegin; 189 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 190 mat->factorerrortype = MAT_FACTOR_NOERROR; 191 mat->factorerror_zeropivot_value = 0.0; 192 mat->factorerror_zeropivot_row = 0; 193 PetscFunctionReturn(PETSC_SUCCESS); 194 } 195 196 PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero) 197 { 198 Vec r, l; 199 const PetscScalar *al; 200 PetscInt i, nz, gnz, N, n; 201 202 PetscFunctionBegin; 203 PetscCall(MatCreateVecs(mat, &r, &l)); 204 if (!cols) { /* nonzero rows */ 205 PetscCall(MatGetSize(mat, &N, NULL)); 206 PetscCall(MatGetLocalSize(mat, &n, NULL)); 207 PetscCall(VecSet(l, 0.0)); 208 PetscCall(VecSetRandom(r, NULL)); 209 PetscCall(MatMult(mat, r, l)); 210 PetscCall(VecGetArrayRead(l, &al)); 211 } else { /* nonzero columns */ 212 PetscCall(MatGetSize(mat, NULL, &N)); 213 PetscCall(MatGetLocalSize(mat, NULL, &n)); 214 PetscCall(VecSet(r, 0.0)); 215 PetscCall(VecSetRandom(l, NULL)); 216 PetscCall(MatMultTranspose(mat, l, r)); 217 PetscCall(VecGetArrayRead(r, &al)); 218 } 219 if (tol <= 0.0) { 220 for (i = 0, nz = 0; i < n; i++) 221 if (al[i] != 0.0) nz++; 222 } else { 223 for (i = 0, nz = 0; i < n; i++) 224 if (PetscAbsScalar(al[i]) > tol) nz++; 225 } 226 PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 227 if (gnz != N) { 228 PetscInt *nzr; 229 PetscCall(PetscMalloc1(nz, &nzr)); 230 if (nz) { 231 if (tol < 0) { 232 for (i = 0, nz = 0; i < n; i++) 233 if (al[i] != 0.0) nzr[nz++] = i; 234 } else { 235 for (i = 0, nz = 0; i < n; i++) 236 if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i; 237 } 238 } 239 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero)); 240 } else *nonzero = NULL; 241 if (!cols) { /* nonzero rows */ 242 PetscCall(VecRestoreArrayRead(l, &al)); 243 } else { 244 PetscCall(VecRestoreArrayRead(r, &al)); 245 } 246 PetscCall(VecDestroy(&l)); 247 PetscCall(VecDestroy(&r)); 248 PetscFunctionReturn(PETSC_SUCCESS); 249 } 250 251 /*@ 252 MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix 253 254 Input Parameter: 255 . A - the matrix 256 257 Output Parameter: 258 . keptrows - the rows that are not completely zero 259 260 Level: intermediate 261 262 Note: 263 `keptrows` is set to `NULL` if all rows are nonzero. 264 265 .seealso: [](chapter_matrices), `Mat`, `MatFindZeroRows()` 266 @*/ 267 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows) 268 { 269 PetscFunctionBegin; 270 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 271 PetscValidType(mat, 1); 272 PetscValidPointer(keptrows, 2); 273 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 274 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 275 if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows); 276 else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows)); 277 PetscFunctionReturn(PETSC_SUCCESS); 278 } 279 280 /*@ 281 MatFindZeroRows - Locate all rows that are completely zero in the matrix 282 283 Input Parameter: 284 . A - the matrix 285 286 Output Parameter: 287 . zerorows - the rows that are completely zero 288 289 Level: intermediate 290 291 Note: 292 `zerorows` is set to `NULL` if no rows are zero. 293 294 .seealso: [](chapter_matrices), `Mat`, `MatFindNonzeroRows()` 295 @*/ 296 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows) 297 { 298 IS keptrows; 299 PetscInt m, n; 300 301 PetscFunctionBegin; 302 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 303 PetscValidType(mat, 1); 304 PetscValidPointer(zerorows, 2); 305 PetscCall(MatFindNonzeroRows(mat, &keptrows)); 306 /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows. 307 In keeping with this convention, we set zerorows to NULL if there are no zero 308 rows. */ 309 if (keptrows == NULL) { 310 *zerorows = NULL; 311 } else { 312 PetscCall(MatGetOwnershipRange(mat, &m, &n)); 313 PetscCall(ISComplement(keptrows, m, n, zerorows)); 314 PetscCall(ISDestroy(&keptrows)); 315 } 316 PetscFunctionReturn(PETSC_SUCCESS); 317 } 318 319 /*@ 320 MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling 321 322 Not Collective 323 324 Input Parameter: 325 . A - the matrix 326 327 Output Parameter: 328 . a - the diagonal part (which is a SEQUENTIAL matrix) 329 330 Level: advanced 331 332 Notes: 333 See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix. 334 335 Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation. 336 337 .seealso: [](chapter_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ` 338 @*/ 339 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a) 340 { 341 PetscFunctionBegin; 342 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 343 PetscValidType(A, 1); 344 PetscValidPointer(a, 2); 345 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 346 if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a); 347 else { 348 PetscMPIInt size; 349 350 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 351 PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name); 352 *a = A; 353 } 354 PetscFunctionReturn(PETSC_SUCCESS); 355 } 356 357 /*@ 358 MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries. 359 360 Collective 361 362 Input Parameter: 363 . mat - the matrix 364 365 Output Parameter: 366 . trace - the sum of the diagonal entries 367 368 Level: advanced 369 370 .seealso: [](chapter_matrices), `Mat` 371 @*/ 372 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace) 373 { 374 Vec diag; 375 376 PetscFunctionBegin; 377 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 378 PetscValidScalarPointer(trace, 2); 379 PetscCall(MatCreateVecs(mat, &diag, NULL)); 380 PetscCall(MatGetDiagonal(mat, diag)); 381 PetscCall(VecSum(diag, trace)); 382 PetscCall(VecDestroy(&diag)); 383 PetscFunctionReturn(PETSC_SUCCESS); 384 } 385 386 /*@ 387 MatRealPart - Zeros out the imaginary part of the matrix 388 389 Logically Collective 390 391 Input Parameter: 392 . mat - the matrix 393 394 Level: advanced 395 396 .seealso: [](chapter_matrices), `Mat`, `MatImaginaryPart()` 397 @*/ 398 PetscErrorCode MatRealPart(Mat mat) 399 { 400 PetscFunctionBegin; 401 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 402 PetscValidType(mat, 1); 403 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 404 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 405 MatCheckPreallocated(mat, 1); 406 PetscUseTypeMethod(mat, realpart); 407 PetscFunctionReturn(PETSC_SUCCESS); 408 } 409 410 /*@C 411 MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix 412 413 Collective 414 415 Input Parameter: 416 . mat - the matrix 417 418 Output Parameters: 419 + nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each block) 420 - ghosts - the global indices of the ghost points 421 422 Level: advanced 423 424 Note: 425 `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()` 426 427 .seealso: [](chapter_matrices), `Mat`, `VecCreateGhost()` 428 @*/ 429 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[]) 430 { 431 PetscFunctionBegin; 432 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 433 PetscValidType(mat, 1); 434 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 435 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 436 if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts); 437 else { 438 if (nghosts) *nghosts = 0; 439 if (ghosts) *ghosts = NULL; 440 } 441 PetscFunctionReturn(PETSC_SUCCESS); 442 } 443 444 /*@ 445 MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part 446 447 Logically Collective 448 449 Input Parameter: 450 . mat - the matrix 451 452 Level: advanced 453 454 .seealso: [](chapter_matrices), `Mat`, `MatRealPart()` 455 @*/ 456 PetscErrorCode MatImaginaryPart(Mat mat) 457 { 458 PetscFunctionBegin; 459 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 460 PetscValidType(mat, 1); 461 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 462 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 463 MatCheckPreallocated(mat, 1); 464 PetscUseTypeMethod(mat, imaginarypart); 465 PetscFunctionReturn(PETSC_SUCCESS); 466 } 467 468 /*@ 469 MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices) 470 471 Not Collective 472 473 Input Parameter: 474 . mat - the matrix 475 476 Output Parameters: 477 + missing - is any diagonal missing 478 - dd - first diagonal entry that is missing (optional) on this process 479 480 Level: advanced 481 482 .seealso: [](chapter_matrices), `Mat` 483 @*/ 484 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd) 485 { 486 PetscFunctionBegin; 487 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 488 PetscValidType(mat, 1); 489 PetscValidBoolPointer(missing, 2); 490 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name); 491 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 492 PetscUseTypeMethod(mat, missingdiagonal, missing, dd); 493 PetscFunctionReturn(PETSC_SUCCESS); 494 } 495 496 /*@C 497 MatGetRow - Gets a row of a matrix. You MUST call `MatRestoreRow()` 498 for each row that you get to ensure that your application does 499 not bleed memory. 500 501 Not Collective 502 503 Input Parameters: 504 + mat - the matrix 505 - row - the row to get 506 507 Output Parameters: 508 + ncols - if not `NULL`, the number of nonzeros in the row 509 . cols - if not `NULL`, the column numbers 510 - vals - if not `NULL`, the values 511 512 Level: advanced 513 514 Notes: 515 This routine is provided for people who need to have direct access 516 to the structure of a matrix. We hope that we provide enough 517 high-level matrix routines that few users will need it. 518 519 `MatGetRow()` always returns 0-based column indices, regardless of 520 whether the internal representation is 0-based (default) or 1-based. 521 522 For better efficiency, set cols and/or vals to `NULL` if you do 523 not wish to extract these quantities. 524 525 The user can only examine the values extracted with `MatGetRow()`; 526 the values cannot be altered. To change the matrix entries, one 527 must use `MatSetValues()`. 528 529 You can only have one call to `MatGetRow()` outstanding for a particular 530 matrix at a time, per processor. `MatGetRow()` can only obtain rows 531 associated with the given processor, it cannot get rows from the 532 other processors; for that we suggest using `MatCreateSubMatrices()`, then 533 MatGetRow() on the submatrix. The row index passed to `MatGetRow()` 534 is in the global number of rows. 535 536 Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix. 537 538 Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly. 539 540 Fortran Note: 541 The calling sequence is 542 .vb 543 MatGetRow(matrix,row,ncols,cols,values,ierr) 544 Mat matrix (input) 545 integer row (input) 546 integer ncols (output) 547 integer cols(maxcols) (output) 548 double precision (or double complex) values(maxcols) output 549 .ve 550 where maxcols >= maximum nonzeros in any row of the matrix. 551 552 Caution: 553 Do not try to change the contents of the output arrays (`cols` and `vals`). 554 In some cases, this may corrupt the matrix. 555 556 .seealso: [](chapter_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()` 557 @*/ 558 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 559 { 560 PetscInt incols; 561 562 PetscFunctionBegin; 563 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 564 PetscValidType(mat, 1); 565 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 566 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 567 MatCheckPreallocated(mat, 1); 568 PetscCheck(row >= mat->rmap->rstart && row < mat->rmap->rend, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Only for local rows, %" PetscInt_FMT " not in [%" PetscInt_FMT ",%" PetscInt_FMT ")", row, mat->rmap->rstart, mat->rmap->rend); 569 PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0)); 570 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: [](chapter_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()` 587 @*/ 588 PetscErrorCode MatConjugate(Mat mat) 589 { 590 PetscFunctionBegin; 591 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 592 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 593 if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) { 594 PetscUseTypeMethod(mat, conjugate); 595 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 596 } 597 PetscFunctionReturn(PETSC_SUCCESS); 598 } 599 600 /*@C 601 MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`. 602 603 Not Collective 604 605 Input Parameters: 606 + mat - the matrix 607 . row - the row to get 608 . ncols - the number of nonzeros 609 . cols - the columns of the nonzeros 610 - vals - if nonzero the column values 611 612 Level: advanced 613 614 Notes: 615 This routine should be called after you have finished examining the entries. 616 617 This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental 618 us of the array after it has been restored. If you pass `NULL`, it will 619 not zero the pointers. Use of `cols` or `vals` after `MatRestoreRow()` is invalid. 620 621 Fortran Notes: 622 The calling sequence is 623 .vb 624 MatRestoreRow(matrix,row,ncols,cols,values,ierr) 625 Mat matrix (input) 626 integer row (input) 627 integer ncols (output) 628 integer cols(maxcols) (output) 629 double precision (or double complex) values(maxcols) output 630 .ve 631 Where maxcols >= maximum nonzeros in any row of the matrix. 632 633 In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()` 634 before another call to `MatGetRow()` can be made. 635 636 .seealso: [](chapter_matrices), `Mat`, `MatGetRow()` 637 @*/ 638 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 639 { 640 PetscFunctionBegin; 641 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 642 if (ncols) PetscValidIntPointer(ncols, 3); 643 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 644 if (!mat->ops->restorerow) PetscFunctionReturn(PETSC_SUCCESS); 645 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: [](chapter_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()` 667 @*/ 668 PetscErrorCode MatGetRowUpperTriangular(Mat mat) 669 { 670 PetscFunctionBegin; 671 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 672 PetscValidType(mat, 1); 673 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 674 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 675 MatCheckPreallocated(mat, 1); 676 if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS); 677 PetscUseTypeMethod(mat, getrowuppertriangular); 678 PetscFunctionReturn(PETSC_SUCCESS); 679 } 680 681 /*@ 682 MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 683 684 Not Collective 685 686 Input Parameter: 687 . mat - the matrix 688 689 Level: advanced 690 691 Note: 692 This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`. 693 694 .seealso: [](chapter_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()` 695 @*/ 696 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat) 697 { 698 PetscFunctionBegin; 699 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 700 PetscValidType(mat, 1); 701 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 702 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 703 MatCheckPreallocated(mat, 1); 704 if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS); 705 PetscUseTypeMethod(mat, restorerowuppertriangular); 706 PetscFunctionReturn(PETSC_SUCCESS); 707 } 708 709 /*@C 710 MatSetOptionsPrefix - Sets the prefix used for searching for all 711 `Mat` options in the database. 712 713 Logically Collective 714 715 Input Parameters: 716 + A - the matrix 717 - prefix - the prefix to prepend to all option names 718 719 Level: advanced 720 721 Notes: 722 A hyphen (-) must NOT be given at the beginning of the prefix name. 723 The first character of all runtime options is AUTOMATICALLY the hyphen. 724 725 This is NOT used for options for the factorization of the matrix. Normally the 726 prefix is automatically passed in from the PC calling the factorization. To set 727 it directly use `MatSetOptionsPrefixFactor()` 728 729 .seealso: [](chapter_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()` 730 @*/ 731 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[]) 732 { 733 PetscFunctionBegin; 734 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 735 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix)); 736 PetscFunctionReturn(PETSC_SUCCESS); 737 } 738 739 /*@C 740 MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for 741 for matrices created with `MatGetFactor()` 742 743 Logically Collective 744 745 Input Parameters: 746 + A - the matrix 747 - prefix - the prefix to prepend to all option names for the factored matrix 748 749 Level: developer 750 751 Notes: 752 A hyphen (-) must NOT be given at the beginning of the prefix name. 753 The first character of all runtime options is AUTOMATICALLY the hyphen. 754 755 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 756 it directly when not using `KSP`/`PC` use `MatSetOptionsPrefixFactor()` 757 758 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()` 759 @*/ 760 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[]) 761 { 762 PetscFunctionBegin; 763 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 764 if (prefix) { 765 PetscValidCharPointer(prefix, 2); 766 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 767 if (prefix != A->factorprefix) { 768 PetscCall(PetscFree(A->factorprefix)); 769 PetscCall(PetscStrallocpy(prefix, &A->factorprefix)); 770 } 771 } else PetscCall(PetscFree(A->factorprefix)); 772 PetscFunctionReturn(PETSC_SUCCESS); 773 } 774 775 /*@C 776 MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for 777 for matrices created with `MatGetFactor()` 778 779 Logically Collective 780 781 Input Parameters: 782 + A - the matrix 783 - prefix - the prefix to prepend to all option names for the factored matrix 784 785 Level: developer 786 787 Notes: 788 A hyphen (-) must NOT be given at the beginning of the prefix name. 789 The first character of all runtime options is AUTOMATICALLY the hyphen. 790 791 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 792 it directly when not using `KSP`/`PC` use `MatAppendOptionsPrefixFactor()` 793 794 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`, 795 `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`, 796 `MatSetOptionsPrefix()` 797 @*/ 798 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[]) 799 { 800 size_t len1, len2, new_len; 801 802 PetscFunctionBegin; 803 PetscValidHeader(A, 1); 804 if (!prefix) PetscFunctionReturn(PETSC_SUCCESS); 805 if (!A->factorprefix) { 806 PetscCall(MatSetOptionsPrefixFactor(A, prefix)); 807 PetscFunctionReturn(PETSC_SUCCESS); 808 } 809 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 810 811 PetscCall(PetscStrlen(A->factorprefix, &len1)); 812 PetscCall(PetscStrlen(prefix, &len2)); 813 new_len = len1 + len2 + 1; 814 PetscCall(PetscRealloc(new_len * sizeof(*(A->factorprefix)), &A->factorprefix)); 815 PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1)); 816 PetscFunctionReturn(PETSC_SUCCESS); 817 } 818 819 /*@C 820 MatAppendOptionsPrefix - Appends to the prefix used for searching for all 821 matrix options in the database. 822 823 Logically Collective 824 825 Input Parameters: 826 + A - the matrix 827 - prefix - the prefix to prepend to all option names 828 829 Level: advanced 830 831 Note: 832 A hyphen (-) must NOT be given at the beginning of the prefix name. 833 The first character of all runtime options is AUTOMATICALLY the hyphen. 834 835 .seealso: [](chapter_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()` 836 @*/ 837 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[]) 838 { 839 PetscFunctionBegin; 840 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 841 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix)); 842 PetscFunctionReturn(PETSC_SUCCESS); 843 } 844 845 /*@C 846 MatGetOptionsPrefix - Gets the prefix used for searching for all 847 matrix options in the database. 848 849 Not Collective 850 851 Input Parameter: 852 . A - the matrix 853 854 Output Parameter: 855 . prefix - pointer to the prefix string used 856 857 Level: advanced 858 859 Fortran Note: 860 The user should pass in a string `prefix` of 861 sufficient length to hold the prefix. 862 863 .seealso: [](chapter_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()` 864 @*/ 865 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[]) 866 { 867 PetscFunctionBegin; 868 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 869 PetscValidPointer(prefix, 2); 870 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix)); 871 PetscFunctionReturn(PETSC_SUCCESS); 872 } 873 874 /*@ 875 MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by users. 876 877 Collective 878 879 Input Parameter: 880 . A - the matrix 881 882 Level: beginner 883 884 Notes: 885 The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`. 886 887 Users can reset the preallocation to access the original memory. 888 889 Currently only supported for `MATAIJ` matrices. 890 891 .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()` 892 @*/ 893 PetscErrorCode MatResetPreallocation(Mat A) 894 { 895 PetscFunctionBegin; 896 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 897 PetscValidType(A, 1); 898 PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A)); 899 PetscFunctionReturn(PETSC_SUCCESS); 900 } 901 902 /*@ 903 MatSetUp - Sets up the internal matrix data structures for later use. 904 905 Collective 906 907 Input Parameter: 908 . A - the matrix 909 910 Level: intermediate 911 912 Notes: 913 If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of 914 setting values in the matrix. 915 916 If a suitable preallocation routine is used, this function does not need to be called. 917 918 This routine is called internally by other matrix functions when needed so rarely needs to be called by users 919 920 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()` 921 @*/ 922 PetscErrorCode MatSetUp(Mat A) 923 { 924 PetscFunctionBegin; 925 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 926 if (!((PetscObject)A)->type_name) { 927 PetscMPIInt size; 928 929 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 930 PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ)); 931 } 932 if (!A->preallocated) PetscTryTypeMethod(A, setup); 933 PetscCall(PetscLayoutSetUp(A->rmap)); 934 PetscCall(PetscLayoutSetUp(A->cmap)); 935 A->preallocated = PETSC_TRUE; 936 PetscFunctionReturn(PETSC_SUCCESS); 937 } 938 939 #if defined(PETSC_HAVE_SAWS) 940 #include <petscviewersaws.h> 941 #endif 942 943 /*@C 944 MatViewFromOptions - View properties of the matrix based on options set in the options database 945 946 Collective 947 948 Input Parameters: 949 + A - the matrix 950 . obj - optional additional object that provides the options prefix to use 951 - name - command line option 952 953 Options Database Key: 954 . -mat_view [viewertype]:... - the viewer and its options 955 956 Level: intermediate 957 958 Notes: 959 .vb 960 If no value is provided ascii:stdout is used 961 ascii[:[filename][:[format][:append]]] defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab, 962 for example ascii::ascii_info prints just the information about the object not all details 963 unless :append is given filename opens in write mode, overwriting what was already there 964 binary[:[filename][:[format][:append]]] defaults to the file binaryoutput 965 draw[:drawtype[:filename]] for example, draw:tikz, draw:tikz:figure.tex or draw:x 966 socket[:port] defaults to the standard output port 967 saws[:communicatorname] publishes object to the Scientific Application Webserver (SAWs) 968 .ve 969 970 .seealso: [](chapter_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()` 971 @*/ 972 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[]) 973 { 974 PetscFunctionBegin; 975 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 976 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 977 PetscFunctionReturn(PETSC_SUCCESS); 978 } 979 980 /*@C 981 MatView - display information about a matrix in a variety ways 982 983 Collective 984 985 Input Parameters: 986 + mat - the matrix 987 - viewer - visualization context 988 989 Options Database Keys: 990 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 991 . -mat_view ::ascii_info_detail - Prints more detailed info 992 . -mat_view - Prints matrix in ASCII format 993 . -mat_view ::ascii_matlab - Prints matrix in Matlab format 994 . -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 995 . -display <name> - Sets display name (default is host) 996 . -draw_pause <sec> - Sets number of seconds to pause after display 997 . -mat_view socket - Sends matrix to socket, can be accessed from Matlab (see Users-Manual: ch_matlab for details) 998 . -viewer_socket_machine <machine> - 999 . -viewer_socket_port <port> - 1000 . -mat_view binary - save matrix to file in binary format 1001 - -viewer_binary_filename <name> - 1002 1003 Level: beginner 1004 1005 Notes: 1006 The available visualization contexts include 1007 + `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices 1008 . `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD` 1009 . `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm 1010 - `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure 1011 1012 The user can open alternative visualization contexts with 1013 + `PetscViewerASCIIOpen()` - Outputs matrix to a specified file 1014 . `PetscViewerBinaryOpen()` - Outputs matrix in binary to a 1015 specified file; corresponding input uses `MatLoad()` 1016 . `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to 1017 an X window display 1018 - `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer. 1019 Currently only the `MATSEQDENSE` and `MATAIJ` 1020 matrix types support the Socket viewer. 1021 1022 The user can call `PetscViewerPushFormat()` to specify the output 1023 format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`, 1024 `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`). Available formats include 1025 + `PETSC_VIEWER_DEFAULT` - default, prints matrix contents 1026 . `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in Matlab format 1027 . `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros 1028 . `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse 1029 format common among all matrix types 1030 . `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific 1031 format (which is in many cases the same as the default) 1032 . `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix 1033 size and structure (not the matrix entries) 1034 - `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about 1035 the matrix structure 1036 1037 The ASCII viewers are only recommended for small matrices on at most a moderate number of processes, 1038 the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format. 1039 1040 In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer). 1041 1042 See the manual page for `MatLoad()` for the exact format of the binary file when the binary 1043 viewer is used. 1044 1045 See share/petsc/matlab/PetscBinaryRead.m for a Matlab code that can read in the binary file when the binary 1046 viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python. 1047 1048 One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure, 1049 and then use the following mouse functions. 1050 .vb 1051 left mouse: zoom in 1052 middle mouse: zoom out 1053 right mouse: continue with the simulation 1054 .ve 1055 1056 .seealso: [](chapter_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`, 1057 `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()` 1058 @*/ 1059 PetscErrorCode MatView(Mat mat, PetscViewer viewer) 1060 { 1061 PetscInt rows, cols, rbs, cbs; 1062 PetscBool isascii, isstring, issaws; 1063 PetscViewerFormat format; 1064 PetscMPIInt size; 1065 1066 PetscFunctionBegin; 1067 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1068 PetscValidType(mat, 1); 1069 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer)); 1070 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1071 PetscCheckSameComm(mat, 1, viewer, 2); 1072 1073 PetscCall(PetscViewerGetFormat(viewer, &format)); 1074 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 1075 if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS); 1076 1077 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 1078 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 1079 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws)); 1080 PetscCheck((isascii && (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL)) || !mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "No viewers for factored matrix except ASCII, info, or info_detail"); 1081 1082 PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0)); 1083 if (isascii) { 1084 if (!mat->preallocated) { 1085 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n")); 1086 PetscFunctionReturn(PETSC_SUCCESS); 1087 } 1088 if (!mat->assembled) { 1089 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n")); 1090 PetscFunctionReturn(PETSC_SUCCESS); 1091 } 1092 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer)); 1093 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1094 MatNullSpace nullsp, transnullsp; 1095 1096 PetscCall(PetscViewerASCIIPushTab(viewer)); 1097 PetscCall(MatGetSize(mat, &rows, &cols)); 1098 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1099 if (rbs != 1 || cbs != 1) { 1100 if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs)); 1101 else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs)); 1102 } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols)); 1103 if (mat->factortype) { 1104 MatSolverType solver; 1105 PetscCall(MatFactorGetSolverType(mat, &solver)); 1106 PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver)); 1107 } 1108 if (mat->ops->getinfo) { 1109 MatInfo info; 1110 PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info)); 1111 PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated)); 1112 if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs)); 1113 } 1114 PetscCall(MatGetNullSpace(mat, &nullsp)); 1115 PetscCall(MatGetTransposeNullSpace(mat, &transnullsp)); 1116 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached null space\n")); 1117 if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached transposed null space\n")); 1118 PetscCall(MatGetNearNullSpace(mat, &nullsp)); 1119 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached near null space\n")); 1120 PetscCall(PetscViewerASCIIPushTab(viewer)); 1121 PetscCall(MatProductView(mat, viewer)); 1122 PetscCall(PetscViewerASCIIPopTab(viewer)); 1123 } 1124 } else if (issaws) { 1125 #if defined(PETSC_HAVE_SAWS) 1126 PetscMPIInt rank; 1127 1128 PetscCall(PetscObjectName((PetscObject)mat)); 1129 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 1130 if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer)); 1131 #endif 1132 } else if (isstring) { 1133 const char *type; 1134 PetscCall(MatGetType(mat, &type)); 1135 PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type)); 1136 PetscTryTypeMethod(mat, view, viewer); 1137 } 1138 if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) { 1139 PetscCall(PetscViewerASCIIPushTab(viewer)); 1140 PetscUseTypeMethod(mat, viewnative, viewer); 1141 PetscCall(PetscViewerASCIIPopTab(viewer)); 1142 } else if (mat->ops->view) { 1143 PetscCall(PetscViewerASCIIPushTab(viewer)); 1144 PetscUseTypeMethod(mat, view, viewer); 1145 PetscCall(PetscViewerASCIIPopTab(viewer)); 1146 } 1147 if (isascii) { 1148 PetscCall(PetscViewerGetFormat(viewer, &format)); 1149 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer)); 1150 } 1151 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1152 PetscFunctionReturn(PETSC_SUCCESS); 1153 } 1154 1155 #if defined(PETSC_USE_DEBUG) 1156 #include <../src/sys/totalview/tv_data_display.h> 1157 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat) 1158 { 1159 TV_add_row("Local rows", "int", &mat->rmap->n); 1160 TV_add_row("Local columns", "int", &mat->cmap->n); 1161 TV_add_row("Global rows", "int", &mat->rmap->N); 1162 TV_add_row("Global columns", "int", &mat->cmap->N); 1163 TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name); 1164 return TV_format_OK; 1165 } 1166 #endif 1167 1168 /*@C 1169 MatLoad - Loads a matrix that has been stored in binary/HDF5 format 1170 with `MatView()`. The matrix format is determined from the options database. 1171 Generates a parallel MPI matrix if the communicator has more than one 1172 processor. The default matrix type is `MATAIJ`. 1173 1174 Collective 1175 1176 Input Parameters: 1177 + mat - the newly loaded matrix, this needs to have been created with `MatCreate()` 1178 or some related function before a call to `MatLoad()` 1179 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer 1180 1181 Options Database Keys: 1182 Used with block matrix formats (`MATSEQBAIJ`, ...) to specify 1183 block size 1184 . -matload_block_size <bs> - set block size 1185 1186 Level: beginner 1187 1188 Notes: 1189 If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the 1190 `Mat` before calling this routine if you wish to set it from the options database. 1191 1192 `MatLoad()` automatically loads into the options database any options 1193 given in the file filename.info where filename is the name of the file 1194 that was passed to the `PetscViewerBinaryOpen()`. The options in the info 1195 file will be ignored if you use the -viewer_binary_skip_info option. 1196 1197 If the type or size of mat is not set before a call to `MatLoad()`, PETSc 1198 sets the default matrix type AIJ and sets the local and global sizes. 1199 If type and/or size is already set, then the same are used. 1200 1201 In parallel, each processor can load a subset of rows (or the 1202 entire matrix). This routine is especially useful when a large 1203 matrix is stored on disk and only part of it is desired on each 1204 processor. For example, a parallel solver may access only some of 1205 the rows from each processor. The algorithm used here reads 1206 relatively small blocks of data rather than reading the entire 1207 matrix and then subsetting it. 1208 1209 Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`. 1210 Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`, 1211 or the sequence like 1212 .vb 1213 `PetscViewer` v; 1214 `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v); 1215 `PetscViewerSetType`(v,`PETSCVIEWERBINARY`); 1216 `PetscViewerSetFromOptions`(v); 1217 `PetscViewerFileSetMode`(v,`FILE_MODE_READ`); 1218 `PetscViewerFileSetName`(v,"datafile"); 1219 .ve 1220 The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option 1221 $ -viewer_type {binary, hdf5} 1222 1223 See the example src/ksp/ksp/tutorials/ex27.c with the first approach, 1224 and src/mat/tutorials/ex10.c with the second approach. 1225 1226 In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks 1227 is read onto MPI rank 0 and then shipped to its destination MPI rank, one after another. 1228 Multiple objects, both matrices and vectors, can be stored within the same file. 1229 Their `PetscObject` name is ignored; they are loaded in the order of their storage. 1230 1231 Most users should not need to know the details of the binary storage 1232 format, since `MatLoad()` and `MatView()` completely hide these details. 1233 But for anyone who is interested, the standard binary matrix storage 1234 format is 1235 1236 .vb 1237 PetscInt MAT_FILE_CLASSID 1238 PetscInt number of rows 1239 PetscInt number of columns 1240 PetscInt total number of nonzeros 1241 PetscInt *number nonzeros in each row 1242 PetscInt *column indices of all nonzeros (starting index is zero) 1243 PetscScalar *values of all nonzeros 1244 .ve 1245 If PETSc was not configured with `--with-64-bit-indices` then only `MATMPIAIJ` matrices with more than `PETSC_INT_MAX` non-zeros can be 1246 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 1247 case will not fit in a (32-bit) `PetscInt` the value `PETSC_INT_MAX` is used for the header entry `total number of nonzeros`. 1248 1249 PETSc automatically does the byte swapping for 1250 machines that store the bytes reversed. Thus if you write your own binary 1251 read/write routines you have to swap the bytes; see `PetscBinaryRead()` 1252 and `PetscBinaryWrite()` to see how this may be done. 1253 1254 In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used. 1255 Each processor's chunk is loaded independently by its owning MPI process. 1256 Multiple objects, both matrices and vectors, can be stored within the same file. 1257 They are looked up by their PetscObject name. 1258 1259 As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use 1260 by default the same structure and naming of the AIJ arrays and column count 1261 within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g. 1262 $ save example.mat A b -v7.3 1263 can be directly read by this routine (see Reference 1 for details). 1264 1265 Depending on your MATLAB version, this format might be a default, 1266 otherwise you can set it as default in Preferences. 1267 1268 Unless -nocompression flag is used to save the file in MATLAB, 1269 PETSc must be configured with ZLIB package. 1270 1271 See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c 1272 1273 This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5` 1274 1275 Corresponding `MatView()` is not yet implemented. 1276 1277 The loaded matrix is actually a transpose of the original one in MATLAB, 1278 unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above). 1279 With this format, matrix is automatically transposed by PETSc, 1280 unless the matrix is marked as SPD or symmetric 1281 (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`). 1282 1283 References: 1284 . * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version 1285 1286 .seealso: [](chapter_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()` 1287 @*/ 1288 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer) 1289 { 1290 PetscBool flg; 1291 1292 PetscFunctionBegin; 1293 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1294 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1295 1296 if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ)); 1297 1298 flg = PETSC_FALSE; 1299 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL)); 1300 if (flg) { 1301 PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE)); 1302 PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE)); 1303 } 1304 flg = PETSC_FALSE; 1305 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL)); 1306 if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE)); 1307 1308 PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0)); 1309 PetscUseTypeMethod(mat, load, viewer); 1310 PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0)); 1311 PetscFunctionReturn(PETSC_SUCCESS); 1312 } 1313 1314 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant) 1315 { 1316 Mat_Redundant *redund = *redundant; 1317 1318 PetscFunctionBegin; 1319 if (redund) { 1320 if (redund->matseq) { /* via MatCreateSubMatrices() */ 1321 PetscCall(ISDestroy(&redund->isrow)); 1322 PetscCall(ISDestroy(&redund->iscol)); 1323 PetscCall(MatDestroySubMatrices(1, &redund->matseq)); 1324 } else { 1325 PetscCall(PetscFree2(redund->send_rank, redund->recv_rank)); 1326 PetscCall(PetscFree(redund->sbuf_j)); 1327 PetscCall(PetscFree(redund->sbuf_a)); 1328 for (PetscInt i = 0; i < redund->nrecvs; i++) { 1329 PetscCall(PetscFree(redund->rbuf_j[i])); 1330 PetscCall(PetscFree(redund->rbuf_a[i])); 1331 } 1332 PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a)); 1333 } 1334 1335 if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm)); 1336 PetscCall(PetscFree(redund)); 1337 } 1338 PetscFunctionReturn(PETSC_SUCCESS); 1339 } 1340 1341 /*@C 1342 MatDestroy - Frees space taken by a matrix. 1343 1344 Collective 1345 1346 Input Parameter: 1347 . A - the matrix 1348 1349 Level: beginner 1350 1351 Developer Note: 1352 Some special arrays of matrices are not destroyed in this routine but instead by the routines called by 1353 `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines. 1354 `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes 1355 if changes are needed here. 1356 1357 .seealso: [](chapter_matrices), `Mat`, `MatCreate()` 1358 @*/ 1359 PetscErrorCode MatDestroy(Mat *A) 1360 { 1361 PetscFunctionBegin; 1362 if (!*A) PetscFunctionReturn(PETSC_SUCCESS); 1363 PetscValidHeaderSpecific(*A, MAT_CLASSID, 1); 1364 if (--((PetscObject)(*A))->refct > 0) { 1365 *A = NULL; 1366 PetscFunctionReturn(PETSC_SUCCESS); 1367 } 1368 1369 /* if memory was published with SAWs then destroy it */ 1370 PetscCall(PetscObjectSAWsViewOff((PetscObject)*A)); 1371 PetscTryTypeMethod((*A), destroy); 1372 1373 PetscCall(PetscFree((*A)->factorprefix)); 1374 PetscCall(PetscFree((*A)->defaultvectype)); 1375 PetscCall(PetscFree((*A)->defaultrandtype)); 1376 PetscCall(PetscFree((*A)->bsizes)); 1377 PetscCall(PetscFree((*A)->solvertype)); 1378 for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i])); 1379 if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL; 1380 PetscCall(MatDestroy_Redundant(&(*A)->redundant)); 1381 PetscCall(MatProductClear(*A)); 1382 PetscCall(MatNullSpaceDestroy(&(*A)->nullsp)); 1383 PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp)); 1384 PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp)); 1385 PetscCall(MatDestroy(&(*A)->schur)); 1386 PetscCall(PetscLayoutDestroy(&(*A)->rmap)); 1387 PetscCall(PetscLayoutDestroy(&(*A)->cmap)); 1388 PetscCall(PetscHeaderDestroy(A)); 1389 PetscFunctionReturn(PETSC_SUCCESS); 1390 } 1391 1392 /*@C 1393 MatSetValues - Inserts or adds a block of values into a matrix. 1394 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1395 MUST be called after all calls to `MatSetValues()` have been completed. 1396 1397 Not Collective 1398 1399 Input Parameters: 1400 + mat - the matrix 1401 . v - a logically two-dimensional array of values 1402 . m - the number of rows 1403 . idxm - the global indices of the rows 1404 . n - the number of columns 1405 . idxn - the global indices of the columns 1406 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1407 1408 Level: beginner 1409 1410 Notes: 1411 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1412 1413 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1414 options cannot be mixed without intervening calls to the assembly 1415 routines. 1416 1417 `MatSetValues()` uses 0-based row and column numbers in Fortran 1418 as well as in C. 1419 1420 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1421 simply ignored. This allows easily inserting element stiffness matrices 1422 with homogeneous Dirchlet boundary conditions that you don't want represented 1423 in the matrix. 1424 1425 Efficiency Alert: 1426 The routine `MatSetValuesBlocked()` may offer much better efficiency 1427 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1428 1429 Developer Note: 1430 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1431 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1432 1433 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1434 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1435 @*/ 1436 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1437 { 1438 PetscFunctionBeginHot; 1439 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1440 PetscValidType(mat, 1); 1441 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1442 PetscValidIntPointer(idxm, 3); 1443 PetscValidIntPointer(idxn, 5); 1444 MatCheckPreallocated(mat, 1); 1445 1446 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1447 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1448 1449 if (PetscDefined(USE_DEBUG)) { 1450 PetscInt i, j; 1451 1452 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1453 for (i = 0; i < m; i++) { 1454 for (j = 0; j < n; j++) { 1455 if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j])) 1456 #if defined(PETSC_USE_COMPLEX) 1457 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]); 1458 #else 1459 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]); 1460 #endif 1461 } 1462 } 1463 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); 1464 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); 1465 } 1466 1467 if (mat->assembled) { 1468 mat->was_assembled = PETSC_TRUE; 1469 mat->assembled = PETSC_FALSE; 1470 } 1471 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1472 PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv); 1473 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1474 PetscFunctionReturn(PETSC_SUCCESS); 1475 } 1476 1477 /*@C 1478 MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns 1479 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1480 MUST be called after all calls to `MatSetValues()` have been completed. 1481 1482 Not Collective 1483 1484 Input Parameters: 1485 + mat - the matrix 1486 . v - a logically two-dimensional array of values 1487 . ism - the rows to provide 1488 . isn - the columns to provide 1489 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1490 1491 Level: beginner 1492 1493 Notes: 1494 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1495 1496 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1497 options cannot be mixed without intervening calls to the assembly 1498 routines. 1499 1500 `MatSetValues()` uses 0-based row and column numbers in Fortran 1501 as well as in C. 1502 1503 Negative indices may be passed in `ism` and `isn`, these rows and columns are 1504 simply ignored. This allows easily inserting element stiffness matrices 1505 with homogeneous Dirchlet boundary conditions that you don't want represented 1506 in the matrix. 1507 1508 Efficiency Alert: 1509 The routine `MatSetValuesBlocked()` may offer much better efficiency 1510 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1511 1512 This is currently not optimized for any particular `ISType` 1513 1514 Developer Notes: 1515 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1516 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1517 1518 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1519 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()` 1520 @*/ 1521 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv) 1522 { 1523 PetscInt m, n; 1524 const PetscInt *rows, *cols; 1525 1526 PetscFunctionBeginHot; 1527 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1528 PetscCall(ISGetIndices(ism, &rows)); 1529 PetscCall(ISGetIndices(isn, &cols)); 1530 PetscCall(ISGetLocalSize(ism, &m)); 1531 PetscCall(ISGetLocalSize(isn, &n)); 1532 PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv)); 1533 PetscCall(ISRestoreIndices(ism, &rows)); 1534 PetscCall(ISRestoreIndices(isn, &cols)); 1535 PetscFunctionReturn(PETSC_SUCCESS); 1536 } 1537 1538 /*@ 1539 MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1540 values into a matrix 1541 1542 Not Collective 1543 1544 Input Parameters: 1545 + mat - the matrix 1546 . row - the (block) row to set 1547 - v - a logically two-dimensional array of values 1548 1549 Level: intermediate 1550 1551 Notes: 1552 The values, `v`, are column-oriented (for the block version) and sorted 1553 1554 All the nonzeros in the row must be provided 1555 1556 The matrix must have previously had its column indices set, likely by having been assembled. 1557 1558 The row must belong to this process 1559 1560 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1561 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()` 1562 @*/ 1563 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[]) 1564 { 1565 PetscInt globalrow; 1566 1567 PetscFunctionBegin; 1568 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1569 PetscValidType(mat, 1); 1570 PetscValidScalarPointer(v, 3); 1571 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow)); 1572 PetscCall(MatSetValuesRow(mat, globalrow, v)); 1573 PetscFunctionReturn(PETSC_SUCCESS); 1574 } 1575 1576 /*@ 1577 MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1578 values into a matrix 1579 1580 Not Collective 1581 1582 Input Parameters: 1583 + mat - the matrix 1584 . row - the (block) row to set 1585 - 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 1586 1587 Level: advanced 1588 1589 Notes: 1590 The values, `v`, are column-oriented for the block version. 1591 1592 All the nonzeros in the row must be provided 1593 1594 THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used. 1595 1596 The row must belong to this process 1597 1598 .seealso: [](chapter_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1599 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()` 1600 @*/ 1601 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[]) 1602 { 1603 PetscFunctionBeginHot; 1604 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1605 PetscValidType(mat, 1); 1606 MatCheckPreallocated(mat, 1); 1607 PetscValidScalarPointer(v, 3); 1608 PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values"); 1609 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1610 mat->insertmode = INSERT_VALUES; 1611 1612 if (mat->assembled) { 1613 mat->was_assembled = PETSC_TRUE; 1614 mat->assembled = PETSC_FALSE; 1615 } 1616 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1617 PetscUseTypeMethod(mat, setvaluesrow, row, v); 1618 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1619 PetscFunctionReturn(PETSC_SUCCESS); 1620 } 1621 1622 /*@ 1623 MatSetValuesStencil - Inserts or adds a block of values into a matrix. 1624 Using structured grid indexing 1625 1626 Not Collective 1627 1628 Input Parameters: 1629 + mat - the matrix 1630 . m - number of rows being entered 1631 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered 1632 . n - number of columns being entered 1633 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered 1634 . v - a logically two-dimensional array of values 1635 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values 1636 1637 Level: beginner 1638 1639 Notes: 1640 By default the values, `v`, are row-oriented. See `MatSetOption()` for other options. 1641 1642 Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1643 options cannot be mixed without intervening calls to the assembly 1644 routines. 1645 1646 The grid coordinates are across the entire grid, not just the local portion 1647 1648 `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran 1649 as well as in C. 1650 1651 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1652 1653 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1654 or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1655 1656 The columns and rows in the stencil passed in MUST be contained within the 1657 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1658 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1659 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1660 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1661 1662 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 1663 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 1664 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 1665 `DM_BOUNDARY_PERIODIC` boundary type. 1666 1667 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 1668 a single value per point) you can skip filling those indices. 1669 1670 Inspired by the structured grid interface to the HYPRE package 1671 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1672 1673 Efficiency Alert: 1674 The routine `MatSetValuesBlockedStencil()` may offer much better efficiency 1675 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1676 1677 Fortran Note: 1678 `idxm` and `idxn` should be declared as 1679 $ MatStencil idxm(4,m),idxn(4,n) 1680 and the values inserted using 1681 .vb 1682 idxm(MatStencil_i,1) = i 1683 idxm(MatStencil_j,1) = j 1684 idxm(MatStencil_k,1) = k 1685 idxm(MatStencil_c,1) = c 1686 etc 1687 .ve 1688 1689 .seealso: [](chapter_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1690 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil` 1691 @*/ 1692 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1693 { 1694 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1695 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1696 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1697 1698 PetscFunctionBegin; 1699 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1700 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1701 PetscValidType(mat, 1); 1702 PetscValidPointer(idxm, 3); 1703 PetscValidPointer(idxn, 5); 1704 1705 if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 1706 jdxm = buf; 1707 jdxn = buf + m; 1708 } else { 1709 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1710 jdxm = bufm; 1711 jdxn = bufn; 1712 } 1713 for (i = 0; i < m; i++) { 1714 for (j = 0; j < 3 - sdim; j++) dxm++; 1715 tmp = *dxm++ - starts[0]; 1716 for (j = 0; j < dim - 1; j++) { 1717 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1718 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1719 } 1720 if (mat->stencil.noc) dxm++; 1721 jdxm[i] = tmp; 1722 } 1723 for (i = 0; i < n; i++) { 1724 for (j = 0; j < 3 - sdim; j++) dxn++; 1725 tmp = *dxn++ - starts[0]; 1726 for (j = 0; j < dim - 1; j++) { 1727 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1728 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1729 } 1730 if (mat->stencil.noc) dxn++; 1731 jdxn[i] = tmp; 1732 } 1733 PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv)); 1734 PetscCall(PetscFree2(bufm, bufn)); 1735 PetscFunctionReturn(PETSC_SUCCESS); 1736 } 1737 1738 /*@ 1739 MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix. 1740 Using structured grid indexing 1741 1742 Not Collective 1743 1744 Input Parameters: 1745 + mat - the matrix 1746 . m - number of rows being entered 1747 . idxm - grid coordinates for matrix rows being entered 1748 . n - number of columns being entered 1749 . idxn - grid coordinates for matrix columns being entered 1750 . v - a logically two-dimensional array of values 1751 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values 1752 1753 Level: beginner 1754 1755 Notes: 1756 By default the values, `v`, are row-oriented and unsorted. 1757 See `MatSetOption()` for other options. 1758 1759 Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1760 options cannot be mixed without intervening calls to the assembly 1761 routines. 1762 1763 The grid coordinates are across the entire grid, not just the local portion 1764 1765 `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran 1766 as well as in C. 1767 1768 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1769 1770 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1771 or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1772 1773 The columns and rows in the stencil passed in MUST be contained within the 1774 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1775 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1776 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1777 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1778 1779 Negative indices may be passed in idxm and idxn, these rows and columns are 1780 simply ignored. This allows easily inserting element stiffness matrices 1781 with homogeneous Dirchlet boundary conditions that you don't want represented 1782 in the matrix. 1783 1784 Inspired by the structured grid interface to the HYPRE package 1785 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1786 1787 Fortran Note: 1788 `idxm` and `idxn` should be declared as 1789 $ MatStencil idxm(4,m),idxn(4,n) 1790 and the values inserted using 1791 .vb 1792 idxm(MatStencil_i,1) = i 1793 idxm(MatStencil_j,1) = j 1794 idxm(MatStencil_k,1) = k 1795 etc 1796 .ve 1797 1798 .seealso: [](chapter_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1799 `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`, 1800 `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` 1801 @*/ 1802 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1803 { 1804 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1805 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1806 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1807 1808 PetscFunctionBegin; 1809 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1810 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1811 PetscValidType(mat, 1); 1812 PetscValidPointer(idxm, 3); 1813 PetscValidPointer(idxn, 5); 1814 PetscValidScalarPointer(v, 6); 1815 1816 if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 1817 jdxm = buf; 1818 jdxn = buf + m; 1819 } else { 1820 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1821 jdxm = bufm; 1822 jdxn = bufn; 1823 } 1824 for (i = 0; i < m; i++) { 1825 for (j = 0; j < 3 - sdim; j++) dxm++; 1826 tmp = *dxm++ - starts[0]; 1827 for (j = 0; j < sdim - 1; j++) { 1828 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1829 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1830 } 1831 dxm++; 1832 jdxm[i] = tmp; 1833 } 1834 for (i = 0; i < n; i++) { 1835 for (j = 0; j < 3 - sdim; j++) dxn++; 1836 tmp = *dxn++ - starts[0]; 1837 for (j = 0; j < sdim - 1; j++) { 1838 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1839 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1840 } 1841 dxn++; 1842 jdxn[i] = tmp; 1843 } 1844 PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv)); 1845 PetscCall(PetscFree2(bufm, bufn)); 1846 PetscFunctionReturn(PETSC_SUCCESS); 1847 } 1848 1849 /*@ 1850 MatSetStencil - Sets the grid information for setting values into a matrix via 1851 `MatSetValuesStencil()` 1852 1853 Not Collective 1854 1855 Input Parameters: 1856 + mat - the matrix 1857 . dim - dimension of the grid 1, 2, or 3 1858 . dims - number of grid points in x, y, and z direction, including ghost points on your processor 1859 . starts - starting point of ghost nodes on your processor in x, y, and z direction 1860 - dof - number of degrees of freedom per node 1861 1862 Level: beginner 1863 1864 Notes: 1865 Inspired by the structured grid interface to the HYPRE package 1866 (www.llnl.gov/CASC/hyper) 1867 1868 For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the 1869 user. 1870 1871 .seealso: [](chapter_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1872 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()` 1873 @*/ 1874 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof) 1875 { 1876 PetscFunctionBegin; 1877 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1878 PetscValidIntPointer(dims, 3); 1879 PetscValidIntPointer(starts, 4); 1880 1881 mat->stencil.dim = dim + (dof > 1); 1882 for (PetscInt i = 0; i < dim; i++) { 1883 mat->stencil.dims[i] = dims[dim - i - 1]; /* copy the values in backwards */ 1884 mat->stencil.starts[i] = starts[dim - i - 1]; 1885 } 1886 mat->stencil.dims[dim] = dof; 1887 mat->stencil.starts[dim] = 0; 1888 mat->stencil.noc = (PetscBool)(dof == 1); 1889 PetscFunctionReturn(PETSC_SUCCESS); 1890 } 1891 1892 /*@C 1893 MatSetValuesBlocked - Inserts or adds a block of values into a matrix. 1894 1895 Not Collective 1896 1897 Input Parameters: 1898 + mat - the matrix 1899 . v - a logically two-dimensional array of values 1900 . m - the number of block rows 1901 . idxm - the global block indices 1902 . n - the number of block columns 1903 . idxn - the global block indices 1904 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values 1905 1906 Level: intermediate 1907 1908 Notes: 1909 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call 1910 MatXXXXSetPreallocation() or `MatSetUp()` before using this routine. 1911 1912 The `m` and `n` count the NUMBER of blocks in the row direction and column direction, 1913 NOT the total number of rows/columns; for example, if the block size is 2 and 1914 you are passing in values for rows 2,3,4,5 then m would be 2 (not 4). 1915 The values in idxm would be 1 2; that is the first index for each block divided by 1916 the block size. 1917 1918 You must call `MatSetBlockSize()` when constructing this matrix (before 1919 preallocating it). 1920 1921 By default the values, `v`, are row-oriented, so the layout of 1922 `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options. 1923 1924 Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES` 1925 options cannot be mixed without intervening calls to the assembly 1926 routines. 1927 1928 `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran 1929 as well as in C. 1930 1931 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1932 simply ignored. This allows easily inserting element stiffness matrices 1933 with homogeneous Dirchlet boundary conditions that you don't want represented 1934 in the matrix. 1935 1936 Each time an entry is set within a sparse matrix via `MatSetValues()`, 1937 internal searching must be done to determine where to place the 1938 data in the matrix storage space. By instead inserting blocks of 1939 entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is 1940 reduced. 1941 1942 Example: 1943 .vb 1944 Suppose m=n=2 and block size(bs) = 2 The array is 1945 1946 1 2 | 3 4 1947 5 6 | 7 8 1948 - - - | - - - 1949 9 10 | 11 12 1950 13 14 | 15 16 1951 1952 v[] should be passed in like 1953 v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] 1954 1955 If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then 1956 v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16] 1957 .ve 1958 1959 .seealso: [](chapter_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()` 1960 @*/ 1961 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1962 { 1963 PetscFunctionBeginHot; 1964 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1965 PetscValidType(mat, 1); 1966 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1967 PetscValidIntPointer(idxm, 3); 1968 PetscValidIntPointer(idxn, 5); 1969 MatCheckPreallocated(mat, 1); 1970 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1971 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1972 if (PetscDefined(USE_DEBUG)) { 1973 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1974 PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 1975 } 1976 if (PetscDefined(USE_DEBUG)) { 1977 PetscInt rbs, cbs, M, N, i; 1978 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1979 PetscCall(MatGetSize(mat, &M, &N)); 1980 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); 1981 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); 1982 } 1983 if (mat->assembled) { 1984 mat->was_assembled = PETSC_TRUE; 1985 mat->assembled = PETSC_FALSE; 1986 } 1987 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1988 if (mat->ops->setvaluesblocked) { 1989 PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv); 1990 } else { 1991 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn; 1992 PetscInt i, j, bs, cbs; 1993 1994 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 1995 if (m * bs + n * cbs <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 1996 iidxm = buf; 1997 iidxn = buf + m * bs; 1998 } else { 1999 PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc)); 2000 iidxm = bufr; 2001 iidxn = bufc; 2002 } 2003 for (i = 0; i < m; i++) { 2004 for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j; 2005 } 2006 if (m != n || bs != cbs || idxm != idxn) { 2007 for (i = 0; i < n; i++) { 2008 for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j; 2009 } 2010 } else iidxn = iidxm; 2011 PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv)); 2012 PetscCall(PetscFree2(bufr, bufc)); 2013 } 2014 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2015 PetscFunctionReturn(PETSC_SUCCESS); 2016 } 2017 2018 /*@C 2019 MatGetValues - Gets a block of local values from a matrix. 2020 2021 Not Collective; can only return values that are owned by the give process 2022 2023 Input Parameters: 2024 + mat - the matrix 2025 . v - a logically two-dimensional array for storing the values 2026 . m - the number of rows 2027 . idxm - the global indices of the rows 2028 . n - the number of columns 2029 - idxn - the global indices of the columns 2030 2031 Level: advanced 2032 2033 Notes: 2034 The user must allocate space (m*n `PetscScalar`s) for the values, `v`. 2035 The values, `v`, are then returned in a row-oriented format, 2036 analogous to that used by default in `MatSetValues()`. 2037 2038 `MatGetValues()` uses 0-based row and column numbers in 2039 Fortran as well as in C. 2040 2041 `MatGetValues()` requires that the matrix has been assembled 2042 with `MatAssemblyBegin()`/`MatAssemblyEnd()`. Thus, calls to 2043 `MatSetValues()` and `MatGetValues()` CANNOT be made in succession 2044 without intermediate matrix assembly. 2045 2046 Negative row or column indices will be ignored and those locations in `v` will be 2047 left unchanged. 2048 2049 For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI process. 2050 That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable 2051 from `MatGetOwnershipRange`(mat,&rstart,&rend). 2052 2053 .seealso: [](chapter_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()` 2054 @*/ 2055 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) 2056 { 2057 PetscFunctionBegin; 2058 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2059 PetscValidType(mat, 1); 2060 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); 2061 PetscValidIntPointer(idxm, 3); 2062 PetscValidIntPointer(idxn, 5); 2063 PetscValidScalarPointer(v, 6); 2064 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2065 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2066 MatCheckPreallocated(mat, 1); 2067 2068 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2069 PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v); 2070 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2071 PetscFunctionReturn(PETSC_SUCCESS); 2072 } 2073 2074 /*@C 2075 MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices 2076 defined previously by `MatSetLocalToGlobalMapping()` 2077 2078 Not Collective 2079 2080 Input Parameters: 2081 + mat - the matrix 2082 . nrow - number of rows 2083 . irow - the row local indices 2084 . ncol - number of columns 2085 - icol - the column local indices 2086 2087 Output Parameter: 2088 . y - a logically two-dimensional array of values 2089 2090 Level: advanced 2091 2092 Notes: 2093 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine. 2094 2095 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, 2096 are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can 2097 determine if the resulting global row associated with the local row r is owned by the requesting MPI process by applying the `ISLocalToGlobalMapping` set 2098 with `MatSetLocalToGlobalMapping()`. 2099 2100 Developer Note: 2101 This is labelled with C so does not automatically generate Fortran stubs and interfaces 2102 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2103 2104 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2105 `MatSetValuesLocal()`, `MatGetValues()` 2106 @*/ 2107 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[]) 2108 { 2109 PetscFunctionBeginHot; 2110 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2111 PetscValidType(mat, 1); 2112 MatCheckPreallocated(mat, 1); 2113 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */ 2114 PetscValidIntPointer(irow, 3); 2115 PetscValidIntPointer(icol, 5); 2116 if (PetscDefined(USE_DEBUG)) { 2117 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2118 PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2119 } 2120 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2121 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2122 if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y); 2123 else { 2124 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm; 2125 if ((nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2126 irowm = buf; 2127 icolm = buf + nrow; 2128 } else { 2129 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2130 irowm = bufr; 2131 icolm = bufc; 2132 } 2133 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping())."); 2134 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping())."); 2135 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm)); 2136 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm)); 2137 PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y)); 2138 PetscCall(PetscFree2(bufr, bufc)); 2139 } 2140 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2141 PetscFunctionReturn(PETSC_SUCCESS); 2142 } 2143 2144 /*@ 2145 MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and 2146 the same size. Currently, this can only be called once and creates the given matrix. 2147 2148 Not Collective 2149 2150 Input Parameters: 2151 + mat - the matrix 2152 . nb - the number of blocks 2153 . bs - the number of rows (and columns) in each block 2154 . rows - a concatenation of the rows for each block 2155 - v - a concatenation of logically two-dimensional arrays of values 2156 2157 Level: advanced 2158 2159 Note: 2160 `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values 2161 2162 In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix. 2163 2164 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 2165 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()` 2166 @*/ 2167 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[]) 2168 { 2169 PetscFunctionBegin; 2170 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2171 PetscValidType(mat, 1); 2172 PetscValidIntPointer(rows, 4); 2173 PetscValidScalarPointer(v, 5); 2174 PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2175 2176 PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0)); 2177 if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v); 2178 else { 2179 for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES)); 2180 } 2181 PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0)); 2182 PetscFunctionReturn(PETSC_SUCCESS); 2183 } 2184 2185 /*@ 2186 MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by 2187 the routine `MatSetValuesLocal()` to allow users to insert matrix entries 2188 using a local (per-processor) numbering. 2189 2190 Not Collective 2191 2192 Input Parameters: 2193 + x - the matrix 2194 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()` 2195 - cmapping - column mapping 2196 2197 Level: intermediate 2198 2199 Note: 2200 If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix 2201 2202 .seealso: [](chapter_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()` 2203 @*/ 2204 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping) 2205 { 2206 PetscFunctionBegin; 2207 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 2208 PetscValidType(x, 1); 2209 if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2); 2210 if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3); 2211 if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping); 2212 else { 2213 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping)); 2214 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping)); 2215 } 2216 PetscFunctionReturn(PETSC_SUCCESS); 2217 } 2218 2219 /*@ 2220 MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()` 2221 2222 Not Collective 2223 2224 Input Parameter: 2225 . A - the matrix 2226 2227 Output Parameters: 2228 + rmapping - row mapping 2229 - cmapping - column mapping 2230 2231 Level: advanced 2232 2233 .seealso: [](chapter_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()` 2234 @*/ 2235 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping) 2236 { 2237 PetscFunctionBegin; 2238 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2239 PetscValidType(A, 1); 2240 if (rmapping) { 2241 PetscValidPointer(rmapping, 2); 2242 *rmapping = A->rmap->mapping; 2243 } 2244 if (cmapping) { 2245 PetscValidPointer(cmapping, 3); 2246 *cmapping = A->cmap->mapping; 2247 } 2248 PetscFunctionReturn(PETSC_SUCCESS); 2249 } 2250 2251 /*@ 2252 MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix 2253 2254 Logically Collective 2255 2256 Input Parameters: 2257 + A - the matrix 2258 . rmap - row layout 2259 - cmap - column layout 2260 2261 Level: advanced 2262 2263 Note: 2264 The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called. 2265 2266 .seealso: [](chapter_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()` 2267 @*/ 2268 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap) 2269 { 2270 PetscFunctionBegin; 2271 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2272 PetscCall(PetscLayoutReference(rmap, &A->rmap)); 2273 PetscCall(PetscLayoutReference(cmap, &A->cmap)); 2274 PetscFunctionReturn(PETSC_SUCCESS); 2275 } 2276 2277 /*@ 2278 MatGetLayouts - Gets the `PetscLayout` objects for rows and columns 2279 2280 Not Collective 2281 2282 Input Parameter: 2283 . A - the matrix 2284 2285 Output Parameters: 2286 + rmap - row layout 2287 - cmap - column layout 2288 2289 Level: advanced 2290 2291 .seealso: [](chapter_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()` 2292 @*/ 2293 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap) 2294 { 2295 PetscFunctionBegin; 2296 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2297 PetscValidType(A, 1); 2298 if (rmap) { 2299 PetscValidPointer(rmap, 2); 2300 *rmap = A->rmap; 2301 } 2302 if (cmap) { 2303 PetscValidPointer(cmap, 3); 2304 *cmap = A->cmap; 2305 } 2306 PetscFunctionReturn(PETSC_SUCCESS); 2307 } 2308 2309 /*@C 2310 MatSetValuesLocal - Inserts or adds values into certain locations of a matrix, 2311 using a local numbering of the nodes. 2312 2313 Not Collective 2314 2315 Input Parameters: 2316 + mat - the matrix 2317 . nrow - number of rows 2318 . irow - the row local indices 2319 . ncol - number of columns 2320 . icol - the column local indices 2321 . y - a logically two-dimensional array of values 2322 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2323 2324 Level: intermediate 2325 2326 Notes: 2327 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 2328 `MatSetUp()` before using this routine 2329 2330 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine 2331 2332 Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2333 options cannot be mixed without intervening calls to the assembly 2334 routines. 2335 2336 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2337 MUST be called after all calls to `MatSetValuesLocal()` have been completed. 2338 2339 Developer Note: 2340 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2341 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2342 2343 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2344 `MatGetValuesLocal()` 2345 @*/ 2346 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2347 { 2348 PetscFunctionBeginHot; 2349 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2350 PetscValidType(mat, 1); 2351 MatCheckPreallocated(mat, 1); 2352 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2353 PetscValidIntPointer(irow, 3); 2354 PetscValidIntPointer(icol, 5); 2355 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2356 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2357 if (PetscDefined(USE_DEBUG)) { 2358 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2359 PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2360 } 2361 2362 if (mat->assembled) { 2363 mat->was_assembled = PETSC_TRUE; 2364 mat->assembled = PETSC_FALSE; 2365 } 2366 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2367 if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv); 2368 else { 2369 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2370 const PetscInt *irowm, *icolm; 2371 2372 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2373 bufr = buf; 2374 bufc = buf + nrow; 2375 irowm = bufr; 2376 icolm = bufc; 2377 } else { 2378 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2379 irowm = bufr; 2380 icolm = bufc; 2381 } 2382 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr)); 2383 else irowm = irow; 2384 if (mat->cmap->mapping) { 2385 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2386 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc)); 2387 } else icolm = irowm; 2388 } else icolm = icol; 2389 PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv)); 2390 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2391 } 2392 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2393 PetscFunctionReturn(PETSC_SUCCESS); 2394 } 2395 2396 /*@C 2397 MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix, 2398 using a local ordering of the nodes a block at a time. 2399 2400 Not Collective 2401 2402 Input Parameters: 2403 + x - the matrix 2404 . nrow - number of rows 2405 . irow - the row local indices 2406 . ncol - number of columns 2407 . icol - the column local indices 2408 . y - a logically two-dimensional array of values 2409 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2410 2411 Level: intermediate 2412 2413 Notes: 2414 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 2415 `MatSetUp()` before using this routine 2416 2417 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()` 2418 before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the 2419 2420 Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2421 options cannot be mixed without intervening calls to the assembly 2422 routines. 2423 2424 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2425 MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed. 2426 2427 Developer Note: 2428 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2429 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2430 2431 .seealso: [](chapter_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, 2432 `MatSetValuesLocal()`, `MatSetValuesBlocked()` 2433 @*/ 2434 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2435 { 2436 PetscFunctionBeginHot; 2437 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2438 PetscValidType(mat, 1); 2439 MatCheckPreallocated(mat, 1); 2440 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2441 PetscValidIntPointer(irow, 3); 2442 PetscValidIntPointer(icol, 5); 2443 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2444 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2445 if (PetscDefined(USE_DEBUG)) { 2446 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2447 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); 2448 } 2449 2450 if (mat->assembled) { 2451 mat->was_assembled = PETSC_TRUE; 2452 mat->assembled = PETSC_FALSE; 2453 } 2454 if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */ 2455 PetscInt irbs, rbs; 2456 PetscCall(MatGetBlockSizes(mat, &rbs, NULL)); 2457 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs)); 2458 PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs); 2459 } 2460 if (PetscUnlikelyDebug(mat->cmap->mapping)) { 2461 PetscInt icbs, cbs; 2462 PetscCall(MatGetBlockSizes(mat, NULL, &cbs)); 2463 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs)); 2464 PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs); 2465 } 2466 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2467 if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv); 2468 else { 2469 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2470 const PetscInt *irowm, *icolm; 2471 2472 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2473 bufr = buf; 2474 bufc = buf + nrow; 2475 irowm = bufr; 2476 icolm = bufc; 2477 } else { 2478 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2479 irowm = bufr; 2480 icolm = bufc; 2481 } 2482 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr)); 2483 else irowm = irow; 2484 if (mat->cmap->mapping) { 2485 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2486 PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc)); 2487 } else icolm = irowm; 2488 } else icolm = icol; 2489 PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv)); 2490 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2491 } 2492 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2493 PetscFunctionReturn(PETSC_SUCCESS); 2494 } 2495 2496 /*@ 2497 MatMultDiagonalBlock - Computes the matrix-vector product, y = Dx. Where D is defined by the inode or block structure of the diagonal 2498 2499 Collective 2500 2501 Input Parameters: 2502 + mat - the matrix 2503 - x - the vector to be multiplied 2504 2505 Output Parameter: 2506 . y - the result 2507 2508 Level: developer 2509 2510 Note: 2511 The vectors `x` and `y` cannot be the same. I.e., one cannot 2512 call `MatMultDiagonalBlock`(A,y,y). 2513 2514 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2515 @*/ 2516 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y) 2517 { 2518 PetscFunctionBegin; 2519 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2520 PetscValidType(mat, 1); 2521 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2522 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2523 2524 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2525 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2526 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2527 MatCheckPreallocated(mat, 1); 2528 2529 PetscUseTypeMethod(mat, multdiagonalblock, x, y); 2530 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2531 PetscFunctionReturn(PETSC_SUCCESS); 2532 } 2533 2534 /*@ 2535 MatMult - Computes the matrix-vector product, y = Ax. 2536 2537 Neighbor-wise Collective 2538 2539 Input Parameters: 2540 + mat - the matrix 2541 - x - the vector to be multiplied 2542 2543 Output Parameter: 2544 . y - the result 2545 2546 Level: beginner 2547 2548 Note: 2549 The vectors `x` and `y` cannot be the same. I.e., one cannot 2550 call `MatMult`(A,y,y). 2551 2552 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2553 @*/ 2554 PetscErrorCode MatMult(Mat mat, Vec x, Vec y) 2555 { 2556 PetscFunctionBegin; 2557 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2558 PetscValidType(mat, 1); 2559 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2560 VecCheckAssembled(x); 2561 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2562 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2563 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2564 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2565 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); 2566 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); 2567 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); 2568 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); 2569 PetscCall(VecSetErrorIfLocked(y, 3)); 2570 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2571 MatCheckPreallocated(mat, 1); 2572 2573 PetscCall(VecLockReadPush(x)); 2574 PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0)); 2575 PetscUseTypeMethod(mat, mult, x, y); 2576 PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0)); 2577 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2578 PetscCall(VecLockReadPop(x)); 2579 PetscFunctionReturn(PETSC_SUCCESS); 2580 } 2581 2582 /*@ 2583 MatMultTranspose - Computes matrix transpose times a vector y = A^T * x. 2584 2585 Neighbor-wise Collective 2586 2587 Input Parameters: 2588 + mat - the matrix 2589 - x - the vector to be multiplied 2590 2591 Output Parameter: 2592 . y - the result 2593 2594 Level: beginner 2595 2596 Notes: 2597 The vectors `x` and `y` cannot be the same. I.e., one cannot 2598 call `MatMultTranspose`(A,y,y). 2599 2600 For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple, 2601 use `MatMultHermitianTranspose()` 2602 2603 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()` 2604 @*/ 2605 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y) 2606 { 2607 PetscErrorCode (*op)(Mat, Vec, Vec) = NULL; 2608 2609 PetscFunctionBegin; 2610 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2611 PetscValidType(mat, 1); 2612 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2613 VecCheckAssembled(x); 2614 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2615 2616 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2617 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2618 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2619 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); 2620 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); 2621 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); 2622 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); 2623 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2624 MatCheckPreallocated(mat, 1); 2625 2626 if (!mat->ops->multtranspose) { 2627 if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult; 2628 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); 2629 } else op = mat->ops->multtranspose; 2630 PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0)); 2631 PetscCall(VecLockReadPush(x)); 2632 PetscCall((*op)(mat, x, y)); 2633 PetscCall(VecLockReadPop(x)); 2634 PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0)); 2635 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2636 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2637 PetscFunctionReturn(PETSC_SUCCESS); 2638 } 2639 2640 /*@ 2641 MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector. 2642 2643 Neighbor-wise Collective 2644 2645 Input Parameters: 2646 + mat - the matrix 2647 - x - the vector to be multilplied 2648 2649 Output Parameter: 2650 . y - the result 2651 2652 Level: beginner 2653 2654 Notes: 2655 The vectors `x` and `y` cannot be the same. I.e., one cannot 2656 call `MatMultHermitianTranspose`(A,y,y). 2657 2658 Also called the conjugate transpose, complex conjugate transpose, or adjoint. 2659 2660 For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical. 2661 2662 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()` 2663 @*/ 2664 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y) 2665 { 2666 PetscFunctionBegin; 2667 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2668 PetscValidType(mat, 1); 2669 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2670 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2671 2672 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2673 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2674 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2675 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); 2676 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); 2677 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); 2678 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); 2679 MatCheckPreallocated(mat, 1); 2680 2681 PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0)); 2682 #if defined(PETSC_USE_COMPLEX) 2683 if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) { 2684 PetscCall(VecLockReadPush(x)); 2685 if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y); 2686 else PetscUseTypeMethod(mat, mult, x, y); 2687 PetscCall(VecLockReadPop(x)); 2688 } else { 2689 Vec w; 2690 PetscCall(VecDuplicate(x, &w)); 2691 PetscCall(VecCopy(x, w)); 2692 PetscCall(VecConjugate(w)); 2693 PetscCall(MatMultTranspose(mat, w, y)); 2694 PetscCall(VecDestroy(&w)); 2695 PetscCall(VecConjugate(y)); 2696 } 2697 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2698 #else 2699 PetscCall(MatMultTranspose(mat, x, y)); 2700 #endif 2701 PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0)); 2702 PetscFunctionReturn(PETSC_SUCCESS); 2703 } 2704 2705 /*@ 2706 MatMultAdd - Computes v3 = v2 + A * v1. 2707 2708 Neighbor-wise Collective 2709 2710 Input Parameters: 2711 + mat - the matrix 2712 . v1 - the vector to be multiplied by `mat` 2713 - v2 - the vector to be added to the result 2714 2715 Output Parameter: 2716 . v3 - the result 2717 2718 Level: beginner 2719 2720 Note: 2721 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2722 call `MatMultAdd`(A,v1,v2,v1). 2723 2724 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()` 2725 @*/ 2726 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2727 { 2728 PetscFunctionBegin; 2729 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2730 PetscValidType(mat, 1); 2731 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2732 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2733 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2734 2735 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2736 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2737 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); 2738 /* 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); 2739 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); */ 2740 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); 2741 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); 2742 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2743 MatCheckPreallocated(mat, 1); 2744 2745 PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3)); 2746 PetscCall(VecLockReadPush(v1)); 2747 PetscUseTypeMethod(mat, multadd, v1, v2, v3); 2748 PetscCall(VecLockReadPop(v1)); 2749 PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3)); 2750 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2751 PetscFunctionReturn(PETSC_SUCCESS); 2752 } 2753 2754 /*@ 2755 MatMultTransposeAdd - Computes v3 = v2 + A' * v1. 2756 2757 Neighbor-wise Collective 2758 2759 Input Parameters: 2760 + mat - the matrix 2761 . v1 - the vector to be multiplied by the transpose of the matrix 2762 - v2 - the vector to be added to the result 2763 2764 Output Parameter: 2765 . v3 - the result 2766 2767 Level: beginner 2768 2769 Note: 2770 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2771 call `MatMultTransposeAdd`(A,v1,v2,v1). 2772 2773 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2774 @*/ 2775 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2776 { 2777 PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd; 2778 2779 PetscFunctionBegin; 2780 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2781 PetscValidType(mat, 1); 2782 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2783 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2784 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2785 2786 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2787 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2788 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); 2789 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); 2790 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); 2791 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2792 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2793 MatCheckPreallocated(mat, 1); 2794 2795 PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2796 PetscCall(VecLockReadPush(v1)); 2797 PetscCall((*op)(mat, v1, v2, v3)); 2798 PetscCall(VecLockReadPop(v1)); 2799 PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2800 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2801 PetscFunctionReturn(PETSC_SUCCESS); 2802 } 2803 2804 /*@ 2805 MatMultHermitianTransposeAdd - Computes v3 = v2 + A^H * v1. 2806 2807 Neighbor-wise Collective 2808 2809 Input Parameters: 2810 + mat - the matrix 2811 . v1 - the vector to be multiplied by the Hermitian transpose 2812 - v2 - the vector to be added to the result 2813 2814 Output Parameter: 2815 . v3 - the result 2816 2817 Level: beginner 2818 2819 Note: 2820 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2821 call `MatMultHermitianTransposeAdd`(A,v1,v2,v1). 2822 2823 .seealso: [](chapter_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2824 @*/ 2825 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2826 { 2827 PetscFunctionBegin; 2828 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2829 PetscValidType(mat, 1); 2830 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2831 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2832 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2833 2834 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2835 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2836 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2837 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); 2838 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); 2839 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); 2840 MatCheckPreallocated(mat, 1); 2841 2842 PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2843 PetscCall(VecLockReadPush(v1)); 2844 if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3); 2845 else { 2846 Vec w, z; 2847 PetscCall(VecDuplicate(v1, &w)); 2848 PetscCall(VecCopy(v1, w)); 2849 PetscCall(VecConjugate(w)); 2850 PetscCall(VecDuplicate(v3, &z)); 2851 PetscCall(MatMultTranspose(mat, w, z)); 2852 PetscCall(VecDestroy(&w)); 2853 PetscCall(VecConjugate(z)); 2854 if (v2 != v3) { 2855 PetscCall(VecWAXPY(v3, 1.0, v2, z)); 2856 } else { 2857 PetscCall(VecAXPY(v3, 1.0, z)); 2858 } 2859 PetscCall(VecDestroy(&z)); 2860 } 2861 PetscCall(VecLockReadPop(v1)); 2862 PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2863 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2864 PetscFunctionReturn(PETSC_SUCCESS); 2865 } 2866 2867 /*@C 2868 MatGetFactorType - gets the type of factorization it is 2869 2870 Not Collective 2871 2872 Input Parameter: 2873 . mat - the matrix 2874 2875 Output Parameter: 2876 . 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` 2877 2878 Level: intermediate 2879 2880 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2881 `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2882 @*/ 2883 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t) 2884 { 2885 PetscFunctionBegin; 2886 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2887 PetscValidType(mat, 1); 2888 PetscValidPointer(t, 2); 2889 *t = mat->factortype; 2890 PetscFunctionReturn(PETSC_SUCCESS); 2891 } 2892 2893 /*@C 2894 MatSetFactorType - sets the type of factorization it is 2895 2896 Logically Collective 2897 2898 Input Parameters: 2899 + mat - the matrix 2900 - 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` 2901 2902 Level: intermediate 2903 2904 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2905 `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2906 @*/ 2907 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t) 2908 { 2909 PetscFunctionBegin; 2910 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2911 PetscValidType(mat, 1); 2912 mat->factortype = t; 2913 PetscFunctionReturn(PETSC_SUCCESS); 2914 } 2915 2916 /*@C 2917 MatGetInfo - Returns information about matrix storage (number of 2918 nonzeros, memory, etc.). 2919 2920 Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag 2921 2922 Input Parameters: 2923 + mat - the matrix 2924 - 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) 2925 2926 Output Parameter: 2927 . info - matrix information context 2928 2929 Options Database Key: 2930 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT` 2931 2932 Notes: 2933 The `MatInfo` context contains a variety of matrix data, including 2934 number of nonzeros allocated and used, number of mallocs during 2935 matrix assembly, etc. Additional information for factored matrices 2936 is provided (such as the fill ratio, number of mallocs during 2937 factorization, etc.). 2938 2939 Example: 2940 See the file ${PETSC_DIR}/include/petscmat.h for a complete list of 2941 data within the MatInfo context. For example, 2942 .vb 2943 MatInfo info; 2944 Mat A; 2945 double mal, nz_a, nz_u; 2946 2947 MatGetInfo(A, MAT_LOCAL, &info); 2948 mal = info.mallocs; 2949 nz_a = info.nz_allocated; 2950 .ve 2951 2952 Fortran users should declare info as a double precision 2953 array of dimension `MAT_INFO_SIZE`, and then extract the parameters 2954 of interest. See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h 2955 a complete list of parameter names. 2956 .vb 2957 double precision info(MAT_INFO_SIZE) 2958 double precision mal, nz_a 2959 Mat A 2960 integer ierr 2961 2962 call MatGetInfo(A, MAT_LOCAL, info, ierr) 2963 mal = info(MAT_INFO_MALLOCS) 2964 nz_a = info(MAT_INFO_NZ_ALLOCATED) 2965 .ve 2966 2967 Level: intermediate 2968 2969 Developer Note: 2970 The Fortran interface is not autogenerated as the 2971 interface definition cannot be generated correctly [due to `MatInfo` argument] 2972 2973 .seealso: [](chapter_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()` 2974 @*/ 2975 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info) 2976 { 2977 PetscFunctionBegin; 2978 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2979 PetscValidType(mat, 1); 2980 PetscValidPointer(info, 3); 2981 MatCheckPreallocated(mat, 1); 2982 PetscUseTypeMethod(mat, getinfo, flag, info); 2983 PetscFunctionReturn(PETSC_SUCCESS); 2984 } 2985 2986 /* 2987 This is used by external packages where it is not easy to get the info from the actual 2988 matrix factorization. 2989 */ 2990 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info) 2991 { 2992 PetscFunctionBegin; 2993 PetscCall(PetscMemzero(info, sizeof(MatInfo))); 2994 PetscFunctionReturn(PETSC_SUCCESS); 2995 } 2996 2997 /*@C 2998 MatLUFactor - Performs in-place LU factorization of matrix. 2999 3000 Collective 3001 3002 Input Parameters: 3003 + mat - the matrix 3004 . row - row permutation 3005 . col - column permutation 3006 - info - options for factorization, includes 3007 .vb 3008 fill - expected fill as ratio of original fill. 3009 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3010 Run with the option -info to determine an optimal value to use 3011 .ve 3012 Level: developer 3013 3014 Notes: 3015 Most users should employ the `KSP` interface for linear solvers 3016 instead of working directly with matrix algebra routines such as this. 3017 See, e.g., `KSPCreate()`. 3018 3019 This changes the state of the matrix to a factored matrix; it cannot be used 3020 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3021 3022 This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()` 3023 when not using `KSP`. 3024 3025 Developer Note: 3026 The Fortran interface is not autogenerated as the 3027 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3028 3029 .seealso: [](chapter_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, 3030 `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3031 @*/ 3032 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3033 { 3034 MatFactorInfo tinfo; 3035 3036 PetscFunctionBegin; 3037 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3038 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3039 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3040 if (info) PetscValidPointer(info, 4); 3041 PetscValidType(mat, 1); 3042 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3043 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3044 MatCheckPreallocated(mat, 1); 3045 if (!info) { 3046 PetscCall(MatFactorInfoInitialize(&tinfo)); 3047 info = &tinfo; 3048 } 3049 3050 PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0)); 3051 PetscUseTypeMethod(mat, lufactor, row, col, info); 3052 PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0)); 3053 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3054 PetscFunctionReturn(PETSC_SUCCESS); 3055 } 3056 3057 /*@C 3058 MatILUFactor - Performs in-place ILU factorization of matrix. 3059 3060 Collective 3061 3062 Input Parameters: 3063 + mat - the matrix 3064 . row - row permutation 3065 . col - column permutation 3066 - info - structure containing 3067 .vb 3068 levels - number of levels of fill. 3069 expected fill - as ratio of original fill. 3070 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 3071 missing diagonal entries) 3072 .ve 3073 3074 Level: developer 3075 3076 Notes: 3077 Most users should employ the `KSP` interface for linear solvers 3078 instead of working directly with matrix algebra routines such as this. 3079 See, e.g., `KSPCreate()`. 3080 3081 Probably really in-place only when level of fill is zero, otherwise allocates 3082 new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()` 3083 when not using `KSP`. 3084 3085 Developer Note: 3086 The Fortran interface is not autogenerated as the 3087 interface definition cannot be generated correctly [due to MatFactorInfo] 3088 3089 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 3090 @*/ 3091 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3092 { 3093 PetscFunctionBegin; 3094 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3095 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3096 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3097 PetscValidPointer(info, 4); 3098 PetscValidType(mat, 1); 3099 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 3100 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3101 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3102 MatCheckPreallocated(mat, 1); 3103 3104 PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0)); 3105 PetscUseTypeMethod(mat, ilufactor, row, col, info); 3106 PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0)); 3107 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3108 PetscFunctionReturn(PETSC_SUCCESS); 3109 } 3110 3111 /*@C 3112 MatLUFactorSymbolic - Performs symbolic LU factorization of matrix. 3113 Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`. 3114 3115 Collective 3116 3117 Input Parameters: 3118 + fact - the factor matrix obtained with `MatGetFactor()` 3119 . mat - the matrix 3120 . row - the row permutation 3121 . col - the column permutation 3122 - info - options for factorization, includes 3123 .vb 3124 fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use 3125 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3126 .ve 3127 3128 Level: developer 3129 3130 Notes: 3131 See [Matrix Factorization](sec_matfactor) for additional information about factorizations 3132 3133 Most users should employ the simplified `KSP` interface for linear solvers 3134 instead of working directly with matrix algebra routines such as this. 3135 See, e.g., `KSPCreate()`. 3136 3137 Developer Note: 3138 The Fortran interface is not autogenerated as the 3139 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3140 3141 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3142 @*/ 3143 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 3144 { 3145 MatFactorInfo tinfo; 3146 3147 PetscFunctionBegin; 3148 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3149 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3150 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 3151 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 3152 if (info) PetscValidPointer(info, 5); 3153 PetscValidType(fact, 1); 3154 PetscValidType(mat, 2); 3155 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3156 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3157 MatCheckPreallocated(mat, 2); 3158 if (!info) { 3159 PetscCall(MatFactorInfoInitialize(&tinfo)); 3160 info = &tinfo; 3161 } 3162 3163 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0)); 3164 PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info); 3165 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0)); 3166 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3167 PetscFunctionReturn(PETSC_SUCCESS); 3168 } 3169 3170 /*@C 3171 MatLUFactorNumeric - Performs numeric LU factorization of a matrix. 3172 Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`. 3173 3174 Collective 3175 3176 Input Parameters: 3177 + fact - the factor matrix obtained with `MatGetFactor()` 3178 . mat - the matrix 3179 - info - options for factorization 3180 3181 Level: developer 3182 3183 Notes: 3184 See `MatLUFactor()` for in-place factorization. See 3185 `MatCholeskyFactorNumeric()` for the symmetric, positive definite case. 3186 3187 Most users should employ the `KSP` interface for linear solvers 3188 instead of working directly with matrix algebra routines such as this. 3189 See, e.g., `KSPCreate()`. 3190 3191 Developer Note: 3192 The Fortran interface is not autogenerated as the 3193 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3194 3195 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()` 3196 @*/ 3197 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3198 { 3199 MatFactorInfo tinfo; 3200 3201 PetscFunctionBegin; 3202 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3203 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3204 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3205 PetscValidType(fact, 1); 3206 PetscValidType(mat, 2); 3207 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3208 PetscCheck(mat->rmap->N == (fact)->rmap->N && mat->cmap->N == (fact)->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Mat fact: global dimensions are different %" PetscInt_FMT " should = %" PetscInt_FMT " %" PetscInt_FMT " should = %" PetscInt_FMT, 3209 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3210 3211 MatCheckPreallocated(mat, 2); 3212 if (!info) { 3213 PetscCall(MatFactorInfoInitialize(&tinfo)); 3214 info = &tinfo; 3215 } 3216 3217 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3218 else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0)); 3219 PetscUseTypeMethod(fact, lufactornumeric, mat, info); 3220 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3221 else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0)); 3222 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3223 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3224 PetscFunctionReturn(PETSC_SUCCESS); 3225 } 3226 3227 /*@C 3228 MatCholeskyFactor - Performs in-place Cholesky factorization of a 3229 symmetric matrix. 3230 3231 Collective 3232 3233 Input Parameters: 3234 + mat - the matrix 3235 . perm - row and column permutations 3236 - f - expected fill as ratio of original fill 3237 3238 Level: developer 3239 3240 Notes: 3241 See `MatLUFactor()` for the nonsymmetric case. See also `MatGetFactor()`, 3242 `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`. 3243 3244 Most users should employ the `KSP` interface for linear solvers 3245 instead of working directly with matrix algebra routines such as this. 3246 See, e.g., `KSPCreate()`. 3247 3248 Developer Note: 3249 The Fortran interface is not autogenerated as the 3250 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3251 3252 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()` 3253 `MatGetOrdering()` 3254 @*/ 3255 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info) 3256 { 3257 MatFactorInfo tinfo; 3258 3259 PetscFunctionBegin; 3260 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3261 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2); 3262 if (info) PetscValidPointer(info, 3); 3263 PetscValidType(mat, 1); 3264 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3265 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3266 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3267 MatCheckPreallocated(mat, 1); 3268 if (!info) { 3269 PetscCall(MatFactorInfoInitialize(&tinfo)); 3270 info = &tinfo; 3271 } 3272 3273 PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0)); 3274 PetscUseTypeMethod(mat, choleskyfactor, perm, info); 3275 PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0)); 3276 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3277 PetscFunctionReturn(PETSC_SUCCESS); 3278 } 3279 3280 /*@C 3281 MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization 3282 of a symmetric matrix. 3283 3284 Collective 3285 3286 Input Parameters: 3287 + fact - the factor matrix obtained with `MatGetFactor()` 3288 . mat - the matrix 3289 . perm - row and column permutations 3290 - info - options for factorization, includes 3291 .vb 3292 fill - expected fill as ratio of original fill. 3293 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3294 Run with the option -info to determine an optimal value to use 3295 .ve 3296 3297 Level: developer 3298 3299 Notes: 3300 See `MatLUFactorSymbolic()` for the nonsymmetric case. See also 3301 `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`. 3302 3303 Most users should employ the `KSP` interface for linear solvers 3304 instead of working directly with matrix algebra routines such as this. 3305 See, e.g., `KSPCreate()`. 3306 3307 Developer Note: 3308 The Fortran interface is not autogenerated as the 3309 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3310 3311 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()` 3312 `MatGetOrdering()` 3313 @*/ 3314 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 3315 { 3316 MatFactorInfo tinfo; 3317 3318 PetscFunctionBegin; 3319 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3320 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3321 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 3322 if (info) PetscValidPointer(info, 4); 3323 PetscValidType(fact, 1); 3324 PetscValidType(mat, 2); 3325 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3326 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3327 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3328 MatCheckPreallocated(mat, 2); 3329 if (!info) { 3330 PetscCall(MatFactorInfoInitialize(&tinfo)); 3331 info = &tinfo; 3332 } 3333 3334 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3335 PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info); 3336 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3337 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3338 PetscFunctionReturn(PETSC_SUCCESS); 3339 } 3340 3341 /*@C 3342 MatCholeskyFactorNumeric - Performs numeric Cholesky factorization 3343 of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and 3344 `MatCholeskyFactorSymbolic()`. 3345 3346 Collective 3347 3348 Input Parameters: 3349 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored 3350 . mat - the initial matrix that is to be factored 3351 - info - options for factorization 3352 3353 Level: developer 3354 3355 Note: 3356 Most users should employ the `KSP` interface for linear solvers 3357 instead of working directly with matrix algebra routines such as this. 3358 See, e.g., `KSPCreate()`. 3359 3360 Developer Note: 3361 The Fortran interface is not autogenerated as the 3362 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3363 3364 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()` 3365 @*/ 3366 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3367 { 3368 MatFactorInfo tinfo; 3369 3370 PetscFunctionBegin; 3371 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3372 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3373 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3374 PetscValidType(fact, 1); 3375 PetscValidType(mat, 2); 3376 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3377 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, 3378 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3379 MatCheckPreallocated(mat, 2); 3380 if (!info) { 3381 PetscCall(MatFactorInfoInitialize(&tinfo)); 3382 info = &tinfo; 3383 } 3384 3385 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3386 else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0)); 3387 PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info); 3388 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3389 else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0)); 3390 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3391 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3392 PetscFunctionReturn(PETSC_SUCCESS); 3393 } 3394 3395 /*@ 3396 MatQRFactor - Performs in-place QR factorization of matrix. 3397 3398 Collective 3399 3400 Input Parameters: 3401 + mat - the matrix 3402 . col - column permutation 3403 - info - options for factorization, includes 3404 .vb 3405 fill - expected fill as ratio of original fill. 3406 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3407 Run with the option -info to determine an optimal value to use 3408 .ve 3409 3410 Level: developer 3411 3412 Notes: 3413 Most users should employ the `KSP` interface for linear solvers 3414 instead of working directly with matrix algebra routines such as this. 3415 See, e.g., `KSPCreate()`. 3416 3417 This changes the state of the matrix to a factored matrix; it cannot be used 3418 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3419 3420 Developer Note: 3421 The Fortran interface is not autogenerated as the 3422 interface definition cannot be generated correctly [due to MatFactorInfo] 3423 3424 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`, 3425 `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3426 @*/ 3427 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info) 3428 { 3429 PetscFunctionBegin; 3430 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3431 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2); 3432 if (info) PetscValidPointer(info, 3); 3433 PetscValidType(mat, 1); 3434 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3435 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3436 MatCheckPreallocated(mat, 1); 3437 PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0)); 3438 PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info)); 3439 PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0)); 3440 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3441 PetscFunctionReturn(PETSC_SUCCESS); 3442 } 3443 3444 /*@ 3445 MatQRFactorSymbolic - Performs symbolic QR factorization of matrix. 3446 Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`. 3447 3448 Collective 3449 3450 Input Parameters: 3451 + fact - the factor matrix obtained with `MatGetFactor()` 3452 . mat - the matrix 3453 . col - column permutation 3454 - info - options for factorization, includes 3455 .vb 3456 fill - expected fill as ratio of original fill. 3457 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3458 Run with the option -info to determine an optimal value to use 3459 .ve 3460 3461 Level: developer 3462 3463 Note: 3464 Most users should employ the `KSP` interface for linear solvers 3465 instead of working directly with matrix algebra routines such as this. 3466 See, e.g., `KSPCreate()`. 3467 3468 Developer Note: 3469 The Fortran interface is not autogenerated as the 3470 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3471 3472 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3473 @*/ 3474 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info) 3475 { 3476 MatFactorInfo tinfo; 3477 3478 PetscFunctionBegin; 3479 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3480 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3481 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3482 if (info) PetscValidPointer(info, 4); 3483 PetscValidType(fact, 1); 3484 PetscValidType(mat, 2); 3485 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3486 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3487 MatCheckPreallocated(mat, 2); 3488 if (!info) { 3489 PetscCall(MatFactorInfoInitialize(&tinfo)); 3490 info = &tinfo; 3491 } 3492 3493 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3494 PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info)); 3495 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3496 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3497 PetscFunctionReturn(PETSC_SUCCESS); 3498 } 3499 3500 /*@ 3501 MatQRFactorNumeric - Performs numeric QR factorization of a matrix. 3502 Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`. 3503 3504 Collective 3505 3506 Input Parameters: 3507 + fact - the factor matrix obtained with `MatGetFactor()` 3508 . mat - the matrix 3509 - info - options for factorization 3510 3511 Level: developer 3512 3513 Notes: 3514 See `MatQRFactor()` for in-place factorization. 3515 3516 Most users should employ the `KSP` interface for linear solvers 3517 instead of working directly with matrix algebra routines such as this. 3518 See, e.g., `KSPCreate()`. 3519 3520 Developer Note: 3521 The Fortran interface is not autogenerated as the 3522 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3523 3524 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()` 3525 @*/ 3526 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3527 { 3528 MatFactorInfo tinfo; 3529 3530 PetscFunctionBegin; 3531 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3532 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3533 PetscValidType(fact, 1); 3534 PetscValidType(mat, 2); 3535 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3536 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, 3537 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3538 3539 MatCheckPreallocated(mat, 2); 3540 if (!info) { 3541 PetscCall(MatFactorInfoInitialize(&tinfo)); 3542 info = &tinfo; 3543 } 3544 3545 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3546 else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0)); 3547 PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info)); 3548 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3549 else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0)); 3550 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3551 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3552 PetscFunctionReturn(PETSC_SUCCESS); 3553 } 3554 3555 /*@ 3556 MatSolve - Solves A x = b, given a factored matrix. 3557 3558 Neighbor-wise Collective 3559 3560 Input Parameters: 3561 + mat - the factored matrix 3562 - b - the right-hand-side vector 3563 3564 Output Parameter: 3565 . x - the result vector 3566 3567 Level: developer 3568 3569 Notes: 3570 The vectors `b` and `x` cannot be the same. I.e., one cannot 3571 call `MatSolve`(A,x,x). 3572 3573 Most users should employ the `KSP` interface for linear solvers 3574 instead of working directly with matrix algebra routines such as this. 3575 See, e.g., `KSPCreate()`. 3576 3577 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3578 @*/ 3579 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x) 3580 { 3581 PetscFunctionBegin; 3582 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3583 PetscValidType(mat, 1); 3584 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3585 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3586 PetscCheckSameComm(mat, 1, b, 2); 3587 PetscCheckSameComm(mat, 1, x, 3); 3588 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3589 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); 3590 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); 3591 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); 3592 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3593 MatCheckPreallocated(mat, 1); 3594 3595 PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0)); 3596 if (mat->factorerrortype) { 3597 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3598 PetscCall(VecSetInf(x)); 3599 } else PetscUseTypeMethod(mat, solve, b, x); 3600 PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0)); 3601 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3602 PetscFunctionReturn(PETSC_SUCCESS); 3603 } 3604 3605 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans) 3606 { 3607 Vec b, x; 3608 PetscInt N, i; 3609 PetscErrorCode (*f)(Mat, Vec, Vec); 3610 PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE; 3611 3612 PetscFunctionBegin; 3613 if (A->factorerrortype) { 3614 PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype)); 3615 PetscCall(MatSetInf(X)); 3616 PetscFunctionReturn(PETSC_SUCCESS); 3617 } 3618 f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose; 3619 PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 3620 PetscCall(MatBoundToCPU(A, &Abound)); 3621 if (!Abound) { 3622 PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3623 PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3624 } 3625 #if PetscDefined(HAVE_CUDA) 3626 if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B)); 3627 if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X)); 3628 #elif PetscDefined(HAVE_HIP) 3629 if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B)); 3630 if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X)); 3631 #endif 3632 PetscCall(MatGetSize(B, NULL, &N)); 3633 for (i = 0; i < N; i++) { 3634 PetscCall(MatDenseGetColumnVecRead(B, i, &b)); 3635 PetscCall(MatDenseGetColumnVecWrite(X, i, &x)); 3636 PetscCall((*f)(A, b, x)); 3637 PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x)); 3638 PetscCall(MatDenseRestoreColumnVecRead(B, i, &b)); 3639 } 3640 if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B)); 3641 if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X)); 3642 PetscFunctionReturn(PETSC_SUCCESS); 3643 } 3644 3645 /*@ 3646 MatMatSolve - Solves A X = B, given a factored matrix. 3647 3648 Neighbor-wise Collective 3649 3650 Input Parameters: 3651 + A - the factored matrix 3652 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS) 3653 3654 Output Parameter: 3655 . X - the result matrix (dense matrix) 3656 3657 Level: developer 3658 3659 Note: 3660 If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`; 3661 otherwise, `B` and `X` cannot be the same. 3662 3663 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3664 @*/ 3665 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X) 3666 { 3667 PetscFunctionBegin; 3668 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3669 PetscValidType(A, 1); 3670 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3671 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3672 PetscCheckSameComm(A, 1, B, 2); 3673 PetscCheckSameComm(A, 1, X, 3); 3674 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); 3675 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); 3676 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"); 3677 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3678 MatCheckPreallocated(A, 1); 3679 3680 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3681 if (!A->ops->matsolve) { 3682 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name)); 3683 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE)); 3684 } else PetscUseTypeMethod(A, matsolve, B, X); 3685 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3686 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3687 PetscFunctionReturn(PETSC_SUCCESS); 3688 } 3689 3690 /*@ 3691 MatMatSolveTranspose - Solves A^T X = B, given a factored matrix. 3692 3693 Neighbor-wise Collective 3694 3695 Input Parameters: 3696 + A - the factored matrix 3697 - B - the right-hand-side matrix (`MATDENSE` matrix) 3698 3699 Output Parameter: 3700 . X - the result matrix (dense matrix) 3701 3702 Level: developer 3703 3704 Note: 3705 The matrices `B` and `X` cannot be the same. I.e., one cannot 3706 call `MatMatSolveTranspose`(A,X,X). 3707 3708 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()` 3709 @*/ 3710 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X) 3711 { 3712 PetscFunctionBegin; 3713 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3714 PetscValidType(A, 1); 3715 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3716 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3717 PetscCheckSameComm(A, 1, B, 2); 3718 PetscCheckSameComm(A, 1, X, 3); 3719 PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3720 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); 3721 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); 3722 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); 3723 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"); 3724 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3725 MatCheckPreallocated(A, 1); 3726 3727 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3728 if (!A->ops->matsolvetranspose) { 3729 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name)); 3730 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE)); 3731 } else PetscUseTypeMethod(A, matsolvetranspose, B, X); 3732 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3733 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3734 PetscFunctionReturn(PETSC_SUCCESS); 3735 } 3736 3737 /*@ 3738 MatMatTransposeSolve - Solves A X = B^T, given a factored matrix. 3739 3740 Neighbor-wise Collective 3741 3742 Input Parameters: 3743 + A - the factored matrix 3744 - Bt - the transpose of right-hand-side matrix as a `MATDENSE` 3745 3746 Output Parameter: 3747 . X - the result matrix (dense matrix) 3748 3749 Level: developer 3750 3751 Note: 3752 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 3753 format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`. 3754 3755 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3756 @*/ 3757 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X) 3758 { 3759 PetscFunctionBegin; 3760 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3761 PetscValidType(A, 1); 3762 PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2); 3763 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3764 PetscCheckSameComm(A, 1, Bt, 2); 3765 PetscCheckSameComm(A, 1, X, 3); 3766 3767 PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3768 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); 3769 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); 3770 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"); 3771 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3772 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3773 MatCheckPreallocated(A, 1); 3774 3775 PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0)); 3776 PetscUseTypeMethod(A, mattransposesolve, Bt, X); 3777 PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0)); 3778 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3779 PetscFunctionReturn(PETSC_SUCCESS); 3780 } 3781 3782 /*@ 3783 MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or 3784 U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U, 3785 3786 Neighbor-wise Collective 3787 3788 Input Parameters: 3789 + mat - the factored matrix 3790 - b - the right-hand-side vector 3791 3792 Output Parameter: 3793 . x - the result vector 3794 3795 Level: developer 3796 3797 Notes: 3798 `MatSolve()` should be used for most applications, as it performs 3799 a forward solve followed by a backward solve. 3800 3801 The vectors `b` and `x` cannot be the same, i.e., one cannot 3802 call `MatForwardSolve`(A,x,x). 3803 3804 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3805 the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet. 3806 `MatForwardSolve()` solves U^T*D y = b, and 3807 `MatBackwardSolve()` solves U x = y. 3808 Thus they do not provide a symmetric preconditioner. 3809 3810 .seealso: [](chapter_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatBackwardSolve()` 3811 @*/ 3812 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x) 3813 { 3814 PetscFunctionBegin; 3815 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3816 PetscValidType(mat, 1); 3817 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3818 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3819 PetscCheckSameComm(mat, 1, b, 2); 3820 PetscCheckSameComm(mat, 1, x, 3); 3821 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3822 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); 3823 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); 3824 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); 3825 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3826 MatCheckPreallocated(mat, 1); 3827 3828 PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0)); 3829 PetscUseTypeMethod(mat, forwardsolve, b, x); 3830 PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0)); 3831 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3832 PetscFunctionReturn(PETSC_SUCCESS); 3833 } 3834 3835 /*@ 3836 MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU. 3837 D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U, 3838 3839 Neighbor-wise Collective 3840 3841 Input Parameters: 3842 + mat - the factored matrix 3843 - b - the right-hand-side vector 3844 3845 Output Parameter: 3846 . x - the result vector 3847 3848 Level: developer 3849 3850 Notes: 3851 `MatSolve()` should be used for most applications, as it performs 3852 a forward solve followed by a backward solve. 3853 3854 The vectors `b` and `x` cannot be the same. I.e., one cannot 3855 call `MatBackwardSolve`(A,x,x). 3856 3857 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3858 the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet. 3859 `MatForwardSolve()` solves U^T*D y = b, and 3860 `MatBackwardSolve()` solves U x = y. 3861 Thus they do not provide a symmetric preconditioner. 3862 3863 .seealso: [](chapter_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatForwardSolve()` 3864 @*/ 3865 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x) 3866 { 3867 PetscFunctionBegin; 3868 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3869 PetscValidType(mat, 1); 3870 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3871 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3872 PetscCheckSameComm(mat, 1, b, 2); 3873 PetscCheckSameComm(mat, 1, x, 3); 3874 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3875 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); 3876 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); 3877 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); 3878 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3879 MatCheckPreallocated(mat, 1); 3880 3881 PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0)); 3882 PetscUseTypeMethod(mat, backwardsolve, b, x); 3883 PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0)); 3884 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3885 PetscFunctionReturn(PETSC_SUCCESS); 3886 } 3887 3888 /*@ 3889 MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix. 3890 3891 Neighbor-wise Collective 3892 3893 Input Parameters: 3894 + mat - the factored matrix 3895 . b - the right-hand-side vector 3896 - y - the vector to be added to 3897 3898 Output Parameter: 3899 . x - the result vector 3900 3901 Level: developer 3902 3903 Note: 3904 The vectors `b` and `x` cannot be the same. I.e., one cannot 3905 call `MatSolveAdd`(A,x,y,x). 3906 3907 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3908 @*/ 3909 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x) 3910 { 3911 PetscScalar one = 1.0; 3912 Vec tmp; 3913 3914 PetscFunctionBegin; 3915 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3916 PetscValidType(mat, 1); 3917 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 3918 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3919 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 3920 PetscCheckSameComm(mat, 1, b, 2); 3921 PetscCheckSameComm(mat, 1, y, 3); 3922 PetscCheckSameComm(mat, 1, x, 4); 3923 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3924 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); 3925 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); 3926 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); 3927 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); 3928 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); 3929 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3930 MatCheckPreallocated(mat, 1); 3931 3932 PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y)); 3933 if (mat->factorerrortype) { 3934 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3935 PetscCall(VecSetInf(x)); 3936 } else if (mat->ops->solveadd) { 3937 PetscUseTypeMethod(mat, solveadd, b, y, x); 3938 } else { 3939 /* do the solve then the add manually */ 3940 if (x != y) { 3941 PetscCall(MatSolve(mat, b, x)); 3942 PetscCall(VecAXPY(x, one, y)); 3943 } else { 3944 PetscCall(VecDuplicate(x, &tmp)); 3945 PetscCall(VecCopy(x, tmp)); 3946 PetscCall(MatSolve(mat, b, x)); 3947 PetscCall(VecAXPY(x, one, tmp)); 3948 PetscCall(VecDestroy(&tmp)); 3949 } 3950 } 3951 PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y)); 3952 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3953 PetscFunctionReturn(PETSC_SUCCESS); 3954 } 3955 3956 /*@ 3957 MatSolveTranspose - Solves A' x = b, given a factored matrix. 3958 3959 Neighbor-wise Collective 3960 3961 Input Parameters: 3962 + mat - the factored matrix 3963 - b - the right-hand-side vector 3964 3965 Output Parameter: 3966 . x - the result vector 3967 3968 Level: developer 3969 3970 Notes: 3971 The vectors `b` and `x` cannot be the same. I.e., one cannot 3972 call `MatSolveTranspose`(A,x,x). 3973 3974 Most users should employ the `KSP` interface for linear solvers 3975 instead of working directly with matrix algebra routines such as this. 3976 See, e.g., `KSPCreate()`. 3977 3978 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()` 3979 @*/ 3980 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x) 3981 { 3982 PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose; 3983 3984 PetscFunctionBegin; 3985 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3986 PetscValidType(mat, 1); 3987 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3988 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3989 PetscCheckSameComm(mat, 1, b, 2); 3990 PetscCheckSameComm(mat, 1, x, 3); 3991 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3992 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); 3993 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); 3994 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3995 MatCheckPreallocated(mat, 1); 3996 PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0)); 3997 if (mat->factorerrortype) { 3998 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3999 PetscCall(VecSetInf(x)); 4000 } else { 4001 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name); 4002 PetscCall((*f)(mat, b, x)); 4003 } 4004 PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0)); 4005 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4006 PetscFunctionReturn(PETSC_SUCCESS); 4007 } 4008 4009 /*@ 4010 MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a 4011 factored matrix. 4012 4013 Neighbor-wise Collective 4014 4015 Input Parameters: 4016 + mat - the factored matrix 4017 . b - the right-hand-side vector 4018 - y - the vector to be added to 4019 4020 Output Parameter: 4021 . x - the result vector 4022 4023 Level: developer 4024 4025 Note: 4026 The vectors `b` and `x` cannot be the same. I.e., one cannot 4027 call `MatSolveTransposeAdd`(A,x,y,x). 4028 4029 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()` 4030 @*/ 4031 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x) 4032 { 4033 PetscScalar one = 1.0; 4034 Vec tmp; 4035 PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd; 4036 4037 PetscFunctionBegin; 4038 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4039 PetscValidType(mat, 1); 4040 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4041 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4042 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4043 PetscCheckSameComm(mat, 1, b, 2); 4044 PetscCheckSameComm(mat, 1, y, 3); 4045 PetscCheckSameComm(mat, 1, x, 4); 4046 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4047 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); 4048 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); 4049 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); 4050 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); 4051 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4052 MatCheckPreallocated(mat, 1); 4053 4054 PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y)); 4055 if (mat->factorerrortype) { 4056 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4057 PetscCall(VecSetInf(x)); 4058 } else if (f) { 4059 PetscCall((*f)(mat, b, y, x)); 4060 } else { 4061 /* do the solve then the add manually */ 4062 if (x != y) { 4063 PetscCall(MatSolveTranspose(mat, b, x)); 4064 PetscCall(VecAXPY(x, one, y)); 4065 } else { 4066 PetscCall(VecDuplicate(x, &tmp)); 4067 PetscCall(VecCopy(x, tmp)); 4068 PetscCall(MatSolveTranspose(mat, b, x)); 4069 PetscCall(VecAXPY(x, one, tmp)); 4070 PetscCall(VecDestroy(&tmp)); 4071 } 4072 } 4073 PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y)); 4074 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4075 PetscFunctionReturn(PETSC_SUCCESS); 4076 } 4077 4078 /*@ 4079 MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps. 4080 4081 Neighbor-wise Collective 4082 4083 Input Parameters: 4084 + mat - the matrix 4085 . b - the right hand side 4086 . omega - the relaxation factor 4087 . flag - flag indicating the type of SOR (see below) 4088 . shift - diagonal shift 4089 . its - the number of iterations 4090 - lits - the number of local iterations 4091 4092 Output Parameter: 4093 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess) 4094 4095 SOR Flags: 4096 + `SOR_FORWARD_SWEEP` - forward SOR 4097 . `SOR_BACKWARD_SWEEP` - backward SOR 4098 . `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR) 4099 . `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR 4100 . `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR 4101 . `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR 4102 . `SOR_EISENSTAT` - SOR with Eisenstat trick 4103 . `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies 4104 upper/lower triangular part of matrix to 4105 vector (with omega) 4106 - `SOR_ZERO_INITIAL_GUESS` - zero initial guess 4107 4108 Level: developer 4109 4110 Notes: 4111 `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and 4112 `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings 4113 on each processor. 4114 4115 Application programmers will not generally use `MatSOR()` directly, 4116 but instead will employ the `KSP`/`PC` interface. 4117 4118 For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing 4119 4120 Most users should employ the `KSP` interface for linear solvers 4121 instead of working directly with matrix algebra routines such as this. 4122 See, e.g., `KSPCreate()`. 4123 4124 Vectors `x` and `b` CANNOT be the same 4125 4126 The flags are implemented as bitwise inclusive or operations. 4127 For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`) 4128 to specify a zero initial guess for SSOR. 4129 4130 Developer Note: 4131 We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes 4132 4133 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()` 4134 @*/ 4135 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x) 4136 { 4137 PetscFunctionBegin; 4138 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4139 PetscValidType(mat, 1); 4140 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4141 PetscValidHeaderSpecific(x, VEC_CLASSID, 8); 4142 PetscCheckSameComm(mat, 1, b, 2); 4143 PetscCheckSameComm(mat, 1, x, 8); 4144 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4145 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4146 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); 4147 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); 4148 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); 4149 PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its); 4150 PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits); 4151 PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same"); 4152 4153 MatCheckPreallocated(mat, 1); 4154 PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0)); 4155 PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x); 4156 PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0)); 4157 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4158 PetscFunctionReturn(PETSC_SUCCESS); 4159 } 4160 4161 /* 4162 Default matrix copy routine. 4163 */ 4164 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str) 4165 { 4166 PetscInt i, rstart = 0, rend = 0, nz; 4167 const PetscInt *cwork; 4168 const PetscScalar *vwork; 4169 4170 PetscFunctionBegin; 4171 if (B->assembled) PetscCall(MatZeroEntries(B)); 4172 if (str == SAME_NONZERO_PATTERN) { 4173 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 4174 for (i = rstart; i < rend; i++) { 4175 PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork)); 4176 PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES)); 4177 PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork)); 4178 } 4179 } else { 4180 PetscCall(MatAYPX(B, 0.0, A, str)); 4181 } 4182 PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 4183 PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 4184 PetscFunctionReturn(PETSC_SUCCESS); 4185 } 4186 4187 /*@ 4188 MatCopy - Copies a matrix to another matrix. 4189 4190 Collective 4191 4192 Input Parameters: 4193 + A - the matrix 4194 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN` 4195 4196 Output Parameter: 4197 . B - where the copy is put 4198 4199 Level: intermediate 4200 4201 Notes: 4202 If you use `SAME_NONZERO_PATTERN` then the two matrices must have the same nonzero pattern or the routine will crash. 4203 4204 `MatCopy()` copies the matrix entries of a matrix to another existing 4205 matrix (after first zeroing the second matrix). A related routine is 4206 `MatConvert()`, which first creates a new matrix and then copies the data. 4207 4208 .seealso: [](chapter_matrices), `Mat`, `MatConvert()`, `MatDuplicate()` 4209 @*/ 4210 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str) 4211 { 4212 PetscInt i; 4213 4214 PetscFunctionBegin; 4215 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 4216 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 4217 PetscValidType(A, 1); 4218 PetscValidType(B, 2); 4219 PetscCheckSameComm(A, 1, B, 2); 4220 MatCheckPreallocated(B, 2); 4221 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4222 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4223 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, 4224 A->cmap->N, B->cmap->N); 4225 MatCheckPreallocated(A, 1); 4226 if (A == B) PetscFunctionReturn(PETSC_SUCCESS); 4227 4228 PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0)); 4229 if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str); 4230 else PetscCall(MatCopy_Basic(A, B, str)); 4231 4232 B->stencil.dim = A->stencil.dim; 4233 B->stencil.noc = A->stencil.noc; 4234 for (i = 0; i <= A->stencil.dim; i++) { 4235 B->stencil.dims[i] = A->stencil.dims[i]; 4236 B->stencil.starts[i] = A->stencil.starts[i]; 4237 } 4238 4239 PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0)); 4240 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4241 PetscFunctionReturn(PETSC_SUCCESS); 4242 } 4243 4244 /*@C 4245 MatConvert - Converts a matrix to another matrix, either of the same 4246 or different type. 4247 4248 Collective 4249 4250 Input Parameters: 4251 + mat - the matrix 4252 . newtype - new matrix type. Use `MATSAME` to create a new matrix of the 4253 same type as the original matrix. 4254 - reuse - denotes if the destination matrix is to be created or reused. 4255 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 4256 `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). 4257 4258 Output Parameter: 4259 . M - pointer to place new matrix 4260 4261 Level: intermediate 4262 4263 Notes: 4264 `MatConvert()` first creates a new matrix and then copies the data from 4265 the first matrix. A related routine is `MatCopy()`, which copies the matrix 4266 entries of one matrix to another already existing matrix context. 4267 4268 Cannot be used to convert a sequential matrix to parallel or parallel to sequential, 4269 the MPI communicator of the generated matrix is always the same as the communicator 4270 of the input matrix. 4271 4272 .seealso: [](chapter_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 4273 @*/ 4274 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M) 4275 { 4276 PetscBool sametype, issame, flg; 4277 PetscBool3 issymmetric, ishermitian; 4278 char convname[256], mtype[256]; 4279 Mat B; 4280 4281 PetscFunctionBegin; 4282 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4283 PetscValidType(mat, 1); 4284 PetscValidPointer(M, 4); 4285 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4286 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4287 MatCheckPreallocated(mat, 1); 4288 4289 PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg)); 4290 if (flg) newtype = mtype; 4291 4292 PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype)); 4293 PetscCall(PetscStrcmp(newtype, "same", &issame)); 4294 PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix"); 4295 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"); 4296 4297 if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) { 4298 PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4299 PetscFunctionReturn(PETSC_SUCCESS); 4300 } 4301 4302 /* Cache Mat options because some converters use MatHeaderReplace */ 4303 issymmetric = mat->symmetric; 4304 ishermitian = mat->hermitian; 4305 4306 if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) { 4307 PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4308 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4309 } else { 4310 PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL; 4311 const char *prefix[3] = {"seq", "mpi", ""}; 4312 PetscInt i; 4313 /* 4314 Order of precedence: 4315 0) See if newtype is a superclass of the current matrix. 4316 1) See if a specialized converter is known to the current matrix. 4317 2) See if a specialized converter is known to the desired matrix class. 4318 3) See if a good general converter is registered for the desired class 4319 (as of 6/27/03 only MATMPIADJ falls into this category). 4320 4) See if a good general converter is known for the current matrix. 4321 5) Use a really basic converter. 4322 */ 4323 4324 /* 0) See if newtype is a superclass of the current matrix. 4325 i.e mat is mpiaij and newtype is aij */ 4326 for (i = 0; i < 2; i++) { 4327 PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname))); 4328 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4329 PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg)); 4330 PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg)); 4331 if (flg) { 4332 if (reuse == MAT_INPLACE_MATRIX) { 4333 PetscCall(PetscInfo(mat, "Early return\n")); 4334 PetscFunctionReturn(PETSC_SUCCESS); 4335 } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) { 4336 PetscCall(PetscInfo(mat, "Calling MatDuplicate\n")); 4337 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4338 PetscFunctionReturn(PETSC_SUCCESS); 4339 } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) { 4340 PetscCall(PetscInfo(mat, "Calling MatCopy\n")); 4341 PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN)); 4342 PetscFunctionReturn(PETSC_SUCCESS); 4343 } 4344 } 4345 } 4346 /* 1) See if a specialized converter is known to the current matrix and the desired class */ 4347 for (i = 0; i < 3; i++) { 4348 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4349 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4350 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4351 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4352 PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname))); 4353 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4354 PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv)); 4355 PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv)); 4356 if (conv) goto foundconv; 4357 } 4358 4359 /* 2) See if a specialized converter is known to the desired matrix class. */ 4360 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B)); 4361 PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 4362 PetscCall(MatSetType(B, newtype)); 4363 for (i = 0; i < 3; i++) { 4364 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4365 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4366 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4367 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4368 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4369 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4370 PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv)); 4371 PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv)); 4372 if (conv) { 4373 PetscCall(MatDestroy(&B)); 4374 goto foundconv; 4375 } 4376 } 4377 4378 /* 3) See if a good general converter is registered for the desired class */ 4379 conv = B->ops->convertfrom; 4380 PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv)); 4381 PetscCall(MatDestroy(&B)); 4382 if (conv) goto foundconv; 4383 4384 /* 4) See if a good general converter is known for the current matrix */ 4385 if (mat->ops->convert) conv = mat->ops->convert; 4386 PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv)); 4387 if (conv) goto foundconv; 4388 4389 /* 5) Use a really basic converter. */ 4390 PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n")); 4391 conv = MatConvert_Basic; 4392 4393 foundconv: 4394 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4395 PetscCall((*conv)(mat, newtype, reuse, M)); 4396 if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) { 4397 /* the block sizes must be same if the mappings are copied over */ 4398 (*M)->rmap->bs = mat->rmap->bs; 4399 (*M)->cmap->bs = mat->cmap->bs; 4400 PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping)); 4401 PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping)); 4402 (*M)->rmap->mapping = mat->rmap->mapping; 4403 (*M)->cmap->mapping = mat->cmap->mapping; 4404 } 4405 (*M)->stencil.dim = mat->stencil.dim; 4406 (*M)->stencil.noc = mat->stencil.noc; 4407 for (i = 0; i <= mat->stencil.dim; i++) { 4408 (*M)->stencil.dims[i] = mat->stencil.dims[i]; 4409 (*M)->stencil.starts[i] = mat->stencil.starts[i]; 4410 } 4411 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4412 } 4413 PetscCall(PetscObjectStateIncrease((PetscObject)*M)); 4414 4415 /* Copy Mat options */ 4416 if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE)); 4417 else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE)); 4418 if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE)); 4419 else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE)); 4420 PetscFunctionReturn(PETSC_SUCCESS); 4421 } 4422 4423 /*@C 4424 MatFactorGetSolverType - Returns name of the package providing the factorization routines 4425 4426 Not Collective 4427 4428 Input Parameter: 4429 . mat - the matrix, must be a factored matrix 4430 4431 Output Parameter: 4432 . type - the string name of the package (do not free this string) 4433 4434 Level: intermediate 4435 4436 Fortran Note: 4437 Pass in an empty string and the package name will be copied into it. Make sure the string is long enough. 4438 4439 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()` 4440 @*/ 4441 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type) 4442 { 4443 PetscErrorCode (*conv)(Mat, MatSolverType *); 4444 4445 PetscFunctionBegin; 4446 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4447 PetscValidType(mat, 1); 4448 PetscValidPointer(type, 2); 4449 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 4450 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv)); 4451 if (conv) PetscCall((*conv)(mat, type)); 4452 else *type = MATSOLVERPETSC; 4453 PetscFunctionReturn(PETSC_SUCCESS); 4454 } 4455 4456 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType; 4457 struct _MatSolverTypeForSpecifcType { 4458 MatType mtype; 4459 /* no entry for MAT_FACTOR_NONE */ 4460 PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *); 4461 MatSolverTypeForSpecifcType next; 4462 }; 4463 4464 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder; 4465 struct _MatSolverTypeHolder { 4466 char *name; 4467 MatSolverTypeForSpecifcType handlers; 4468 MatSolverTypeHolder next; 4469 }; 4470 4471 static MatSolverTypeHolder MatSolverTypeHolders = NULL; 4472 4473 /*@C 4474 MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type 4475 4476 Input Parameters: 4477 + package - name of the package, for example petsc or superlu 4478 . mtype - the matrix type that works with this package 4479 . ftype - the type of factorization supported by the package 4480 - createfactor - routine that will create the factored matrix ready to be used 4481 4482 Level: developer 4483 4484 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()` 4485 @*/ 4486 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *)) 4487 { 4488 MatSolverTypeHolder next = MatSolverTypeHolders, prev = NULL; 4489 PetscBool flg; 4490 MatSolverTypeForSpecifcType inext, iprev = NULL; 4491 4492 PetscFunctionBegin; 4493 PetscCall(MatInitializePackage()); 4494 if (!next) { 4495 PetscCall(PetscNew(&MatSolverTypeHolders)); 4496 PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name)); 4497 PetscCall(PetscNew(&MatSolverTypeHolders->handlers)); 4498 PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype)); 4499 MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor; 4500 PetscFunctionReturn(PETSC_SUCCESS); 4501 } 4502 while (next) { 4503 PetscCall(PetscStrcasecmp(package, next->name, &flg)); 4504 if (flg) { 4505 PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers"); 4506 inext = next->handlers; 4507 while (inext) { 4508 PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg)); 4509 if (flg) { 4510 inext->createfactor[(int)ftype - 1] = createfactor; 4511 PetscFunctionReturn(PETSC_SUCCESS); 4512 } 4513 iprev = inext; 4514 inext = inext->next; 4515 } 4516 PetscCall(PetscNew(&iprev->next)); 4517 PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype)); 4518 iprev->next->createfactor[(int)ftype - 1] = createfactor; 4519 PetscFunctionReturn(PETSC_SUCCESS); 4520 } 4521 prev = next; 4522 next = next->next; 4523 } 4524 PetscCall(PetscNew(&prev->next)); 4525 PetscCall(PetscStrallocpy(package, &prev->next->name)); 4526 PetscCall(PetscNew(&prev->next->handlers)); 4527 PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype)); 4528 prev->next->handlers->createfactor[(int)ftype - 1] = createfactor; 4529 PetscFunctionReturn(PETSC_SUCCESS); 4530 } 4531 4532 /*@C 4533 MatSolverTypeGet - Gets the function that creates the factor matrix if it exist 4534 4535 Input Parameters: 4536 + type - name of the package, for example petsc or superlu 4537 . ftype - the type of factorization supported by the type 4538 - mtype - the matrix type that works with this type 4539 4540 Output Parameters: 4541 + foundtype - `PETSC_TRUE` if the type was registered 4542 . foundmtype - `PETSC_TRUE` if the type supports the requested mtype 4543 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found 4544 4545 Level: developer 4546 4547 .seealso: [](chapter_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()` 4548 @*/ 4549 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *)) 4550 { 4551 MatSolverTypeHolder next = MatSolverTypeHolders; 4552 PetscBool flg; 4553 MatSolverTypeForSpecifcType inext; 4554 4555 PetscFunctionBegin; 4556 if (foundtype) *foundtype = PETSC_FALSE; 4557 if (foundmtype) *foundmtype = PETSC_FALSE; 4558 if (createfactor) *createfactor = NULL; 4559 4560 if (type) { 4561 while (next) { 4562 PetscCall(PetscStrcasecmp(type, next->name, &flg)); 4563 if (flg) { 4564 if (foundtype) *foundtype = PETSC_TRUE; 4565 inext = next->handlers; 4566 while (inext) { 4567 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4568 if (flg) { 4569 if (foundmtype) *foundmtype = PETSC_TRUE; 4570 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4571 PetscFunctionReturn(PETSC_SUCCESS); 4572 } 4573 inext = inext->next; 4574 } 4575 } 4576 next = next->next; 4577 } 4578 } else { 4579 while (next) { 4580 inext = next->handlers; 4581 while (inext) { 4582 PetscCall(PetscStrcmp(mtype, inext->mtype, &flg)); 4583 if (flg && inext->createfactor[(int)ftype - 1]) { 4584 if (foundtype) *foundtype = PETSC_TRUE; 4585 if (foundmtype) *foundmtype = PETSC_TRUE; 4586 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4587 PetscFunctionReturn(PETSC_SUCCESS); 4588 } 4589 inext = inext->next; 4590 } 4591 next = next->next; 4592 } 4593 /* try with base classes inext->mtype */ 4594 next = MatSolverTypeHolders; 4595 while (next) { 4596 inext = next->handlers; 4597 while (inext) { 4598 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4599 if (flg && inext->createfactor[(int)ftype - 1]) { 4600 if (foundtype) *foundtype = PETSC_TRUE; 4601 if (foundmtype) *foundmtype = PETSC_TRUE; 4602 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4603 PetscFunctionReturn(PETSC_SUCCESS); 4604 } 4605 inext = inext->next; 4606 } 4607 next = next->next; 4608 } 4609 } 4610 PetscFunctionReturn(PETSC_SUCCESS); 4611 } 4612 4613 PetscErrorCode MatSolverTypeDestroy(void) 4614 { 4615 MatSolverTypeHolder next = MatSolverTypeHolders, prev; 4616 MatSolverTypeForSpecifcType inext, iprev; 4617 4618 PetscFunctionBegin; 4619 while (next) { 4620 PetscCall(PetscFree(next->name)); 4621 inext = next->handlers; 4622 while (inext) { 4623 PetscCall(PetscFree(inext->mtype)); 4624 iprev = inext; 4625 inext = inext->next; 4626 PetscCall(PetscFree(iprev)); 4627 } 4628 prev = next; 4629 next = next->next; 4630 PetscCall(PetscFree(prev)); 4631 } 4632 MatSolverTypeHolders = NULL; 4633 PetscFunctionReturn(PETSC_SUCCESS); 4634 } 4635 4636 /*@C 4637 MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4638 4639 Logically Collective 4640 4641 Input Parameter: 4642 . mat - the matrix 4643 4644 Output Parameter: 4645 . flg - `PETSC_TRUE` if uses the ordering 4646 4647 Level: developer 4648 4649 Note: 4650 Most internal PETSc factorizations use the ordering passed to the factorization routine but external 4651 packages do not, thus we want to skip generating the ordering when it is not needed or used. 4652 4653 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4654 @*/ 4655 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg) 4656 { 4657 PetscFunctionBegin; 4658 *flg = mat->canuseordering; 4659 PetscFunctionReturn(PETSC_SUCCESS); 4660 } 4661 4662 /*@C 4663 MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object 4664 4665 Logically Collective 4666 4667 Input Parameters: 4668 + mat - the matrix obtained with `MatGetFactor()` 4669 - ftype - the factorization type to be used 4670 4671 Output Parameter: 4672 . otype - the preferred ordering type 4673 4674 Level: developer 4675 4676 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4677 @*/ 4678 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype) 4679 { 4680 PetscFunctionBegin; 4681 *otype = mat->preferredordering[ftype]; 4682 PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering"); 4683 PetscFunctionReturn(PETSC_SUCCESS); 4684 } 4685 4686 /*@C 4687 MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic() 4688 4689 Collective 4690 4691 Input Parameters: 4692 + mat - the matrix 4693 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4694 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4695 4696 Output Parameter: 4697 . f - the factor matrix used with MatXXFactorSymbolic() calls. Can be `NULL` in some cases, see notes below. 4698 4699 Options Database Key: 4700 . -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory. 4701 One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices. 4702 4703 Level: intermediate 4704 4705 Notes: 4706 The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization 4707 types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime. 4708 4709 Users usually access the factorization solvers via `KSP` 4710 4711 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4712 such as pastix, superlu, mumps etc. 4713 4714 PETSc must have been ./configure to use the external solver, using the option --download-package 4715 4716 Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption 4717 where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set 4718 call `MatSetOptionsPrefixFactor()` on the originating matrix or `MatSetOptionsPrefix()` on the resulting factor matrix. 4719 4720 Developer Note: 4721 This should actually be called `MatCreateFactor()` since it creates a new factor object 4722 4723 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, 4724 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4725 @*/ 4726 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f) 4727 { 4728 PetscBool foundtype, foundmtype; 4729 PetscErrorCode (*conv)(Mat, MatFactorType, Mat *); 4730 4731 PetscFunctionBegin; 4732 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4733 PetscValidType(mat, 1); 4734 4735 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4736 MatCheckPreallocated(mat, 1); 4737 4738 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv)); 4739 if (!foundtype) { 4740 if (type) { 4741 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], 4742 ((PetscObject)mat)->type_name, type); 4743 } else { 4744 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); 4745 } 4746 } 4747 PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name); 4748 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); 4749 4750 PetscCall((*conv)(mat, ftype, f)); 4751 if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix)); 4752 PetscFunctionReturn(PETSC_SUCCESS); 4753 } 4754 4755 /*@C 4756 MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type 4757 4758 Not Collective 4759 4760 Input Parameters: 4761 + mat - the matrix 4762 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4763 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4764 4765 Output Parameter: 4766 . flg - PETSC_TRUE if the factorization is available 4767 4768 Level: intermediate 4769 4770 Notes: 4771 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4772 such as pastix, superlu, mumps etc. 4773 4774 PETSc must have been ./configure to use the external solver, using the option --download-package 4775 4776 Developer Note: 4777 This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object 4778 4779 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactor()`, `MatSolverTypeRegister()`, 4780 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4781 @*/ 4782 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg) 4783 { 4784 PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *); 4785 4786 PetscFunctionBegin; 4787 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4788 PetscValidType(mat, 1); 4789 PetscValidBoolPointer(flg, 4); 4790 4791 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4792 MatCheckPreallocated(mat, 1); 4793 4794 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv)); 4795 *flg = gconv ? PETSC_TRUE : PETSC_FALSE; 4796 PetscFunctionReturn(PETSC_SUCCESS); 4797 } 4798 4799 /*@ 4800 MatDuplicate - Duplicates a matrix including the non-zero structure. 4801 4802 Collective 4803 4804 Input Parameters: 4805 + mat - the matrix 4806 - op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`. 4807 See the manual page for `MatDuplicateOption()` for an explanation of these options. 4808 4809 Output Parameter: 4810 . M - pointer to place new matrix 4811 4812 Level: intermediate 4813 4814 Notes: 4815 You cannot change the nonzero pattern for the parent or child matrix if you use `MAT_SHARE_NONZERO_PATTERN`. 4816 4817 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. 4818 4819 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 4820 is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated. 4821 User should not use `MatDuplicate()` to create new matrix M if M is intended to be reused as the product of matrix operation. 4822 4823 .seealso: [](chapter_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption` 4824 @*/ 4825 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M) 4826 { 4827 Mat B; 4828 VecType vtype; 4829 PetscInt i; 4830 PetscObject dm, container_h, container_d; 4831 void (*viewf)(void); 4832 4833 PetscFunctionBegin; 4834 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4835 PetscValidType(mat, 1); 4836 PetscValidPointer(M, 3); 4837 PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix"); 4838 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4839 MatCheckPreallocated(mat, 1); 4840 4841 *M = NULL; 4842 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4843 PetscUseTypeMethod(mat, duplicate, op, M); 4844 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4845 B = *M; 4846 4847 PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf)); 4848 if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf)); 4849 PetscCall(MatGetVecType(mat, &vtype)); 4850 PetscCall(MatSetVecType(B, vtype)); 4851 4852 B->stencil.dim = mat->stencil.dim; 4853 B->stencil.noc = mat->stencil.noc; 4854 for (i = 0; i <= mat->stencil.dim; i++) { 4855 B->stencil.dims[i] = mat->stencil.dims[i]; 4856 B->stencil.starts[i] = mat->stencil.starts[i]; 4857 } 4858 4859 B->nooffproczerorows = mat->nooffproczerorows; 4860 B->nooffprocentries = mat->nooffprocentries; 4861 4862 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm)); 4863 if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm)); 4864 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h)); 4865 if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h)); 4866 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d)); 4867 if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d)); 4868 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4869 PetscFunctionReturn(PETSC_SUCCESS); 4870 } 4871 4872 /*@ 4873 MatGetDiagonal - Gets the diagonal of a matrix as a `Vec` 4874 4875 Logically Collective 4876 4877 Input Parameter: 4878 . mat - the matrix 4879 4880 Output Parameter: 4881 . v - the diagonal of the matrix 4882 4883 Level: intermediate 4884 4885 Note: 4886 Currently only correct in parallel for square matrices. 4887 4888 .seealso: [](chapter_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()` 4889 @*/ 4890 PetscErrorCode MatGetDiagonal(Mat mat, Vec v) 4891 { 4892 PetscFunctionBegin; 4893 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4894 PetscValidType(mat, 1); 4895 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4896 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4897 MatCheckPreallocated(mat, 1); 4898 4899 PetscUseTypeMethod(mat, getdiagonal, v); 4900 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4901 PetscFunctionReturn(PETSC_SUCCESS); 4902 } 4903 4904 /*@C 4905 MatGetRowMin - Gets the minimum value (of the real part) of each 4906 row of the matrix 4907 4908 Logically Collective 4909 4910 Input Parameter: 4911 . mat - the matrix 4912 4913 Output Parameters: 4914 + v - the vector for storing the maximums 4915 - idx - the indices of the column found for each row (optional) 4916 4917 Level: intermediate 4918 4919 Note: 4920 The result of this call are the same as if one converted the matrix to dense format 4921 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 4922 4923 This code is only implemented for a couple of matrix formats. 4924 4925 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, 4926 `MatGetRowMax()` 4927 @*/ 4928 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[]) 4929 { 4930 PetscFunctionBegin; 4931 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4932 PetscValidType(mat, 1); 4933 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4934 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4935 4936 if (!mat->cmap->N) { 4937 PetscCall(VecSet(v, PETSC_MAX_REAL)); 4938 if (idx) { 4939 PetscInt i, m = mat->rmap->n; 4940 for (i = 0; i < m; i++) idx[i] = -1; 4941 } 4942 } else { 4943 MatCheckPreallocated(mat, 1); 4944 } 4945 PetscUseTypeMethod(mat, getrowmin, v, idx); 4946 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4947 PetscFunctionReturn(PETSC_SUCCESS); 4948 } 4949 4950 /*@C 4951 MatGetRowMinAbs - Gets the minimum value (in absolute value) of each 4952 row of the matrix 4953 4954 Logically Collective 4955 4956 Input Parameter: 4957 . mat - the matrix 4958 4959 Output Parameters: 4960 + v - the vector for storing the minimums 4961 - idx - the indices of the column found for each row (or `NULL` if not needed) 4962 4963 Level: intermediate 4964 4965 Notes: 4966 if a row is completely empty or has only 0.0 values then the idx[] value for that 4967 row is 0 (the first column). 4968 4969 This code is only implemented for a couple of matrix formats. 4970 4971 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()` 4972 @*/ 4973 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[]) 4974 { 4975 PetscFunctionBegin; 4976 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4977 PetscValidType(mat, 1); 4978 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4979 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4980 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4981 4982 if (!mat->cmap->N) { 4983 PetscCall(VecSet(v, 0.0)); 4984 if (idx) { 4985 PetscInt i, m = mat->rmap->n; 4986 for (i = 0; i < m; i++) idx[i] = -1; 4987 } 4988 } else { 4989 MatCheckPreallocated(mat, 1); 4990 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 4991 PetscUseTypeMethod(mat, getrowminabs, v, idx); 4992 } 4993 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4994 PetscFunctionReturn(PETSC_SUCCESS); 4995 } 4996 4997 /*@C 4998 MatGetRowMax - Gets the maximum value (of the real part) of each 4999 row of the matrix 5000 5001 Logically Collective 5002 5003 Input Parameter: 5004 . mat - the matrix 5005 5006 Output Parameters: 5007 + v - the vector for storing the maximums 5008 - idx - the indices of the column found for each row (optional) 5009 5010 Level: intermediate 5011 5012 Notes: 5013 The result of this call are the same as if one converted the matrix to dense format 5014 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5015 5016 This code is only implemented for a couple of matrix formats. 5017 5018 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5019 @*/ 5020 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[]) 5021 { 5022 PetscFunctionBegin; 5023 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5024 PetscValidType(mat, 1); 5025 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5026 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5027 5028 if (!mat->cmap->N) { 5029 PetscCall(VecSet(v, PETSC_MIN_REAL)); 5030 if (idx) { 5031 PetscInt i, m = mat->rmap->n; 5032 for (i = 0; i < m; i++) idx[i] = -1; 5033 } 5034 } else { 5035 MatCheckPreallocated(mat, 1); 5036 PetscUseTypeMethod(mat, getrowmax, v, idx); 5037 } 5038 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5039 PetscFunctionReturn(PETSC_SUCCESS); 5040 } 5041 5042 /*@C 5043 MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each 5044 row of the matrix 5045 5046 Logically Collective 5047 5048 Input Parameter: 5049 . mat - the matrix 5050 5051 Output Parameters: 5052 + v - the vector for storing the maximums 5053 - idx - the indices of the column found for each row (or `NULL` if not needed) 5054 5055 Level: intermediate 5056 5057 Notes: 5058 if a row is completely empty or has only 0.0 values then the idx[] value for that 5059 row is 0 (the first column). 5060 5061 This code is only implemented for a couple of matrix formats. 5062 5063 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5064 @*/ 5065 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[]) 5066 { 5067 PetscFunctionBegin; 5068 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5069 PetscValidType(mat, 1); 5070 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5071 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5072 5073 if (!mat->cmap->N) { 5074 PetscCall(VecSet(v, 0.0)); 5075 if (idx) { 5076 PetscInt i, m = mat->rmap->n; 5077 for (i = 0; i < m; i++) idx[i] = -1; 5078 } 5079 } else { 5080 MatCheckPreallocated(mat, 1); 5081 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5082 PetscUseTypeMethod(mat, getrowmaxabs, v, idx); 5083 } 5084 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5085 PetscFunctionReturn(PETSC_SUCCESS); 5086 } 5087 5088 /*@ 5089 MatGetRowSum - Gets the sum of each row of the matrix 5090 5091 Logically or Neighborhood Collective 5092 5093 Input Parameter: 5094 . mat - the matrix 5095 5096 Output Parameter: 5097 . v - the vector for storing the sum of rows 5098 5099 Level: intermediate 5100 5101 Notes: 5102 This code is slow since it is not currently specialized for different formats 5103 5104 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()` 5105 @*/ 5106 PetscErrorCode MatGetRowSum(Mat mat, Vec v) 5107 { 5108 Vec ones; 5109 5110 PetscFunctionBegin; 5111 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5112 PetscValidType(mat, 1); 5113 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5114 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5115 MatCheckPreallocated(mat, 1); 5116 PetscCall(MatCreateVecs(mat, &ones, NULL)); 5117 PetscCall(VecSet(ones, 1.)); 5118 PetscCall(MatMult(mat, ones, v)); 5119 PetscCall(VecDestroy(&ones)); 5120 PetscFunctionReturn(PETSC_SUCCESS); 5121 } 5122 5123 /*@ 5124 MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) 5125 when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B) 5126 5127 Collective 5128 5129 Input Parameter: 5130 . mat - the matrix to provide the transpose 5131 5132 Output Parameter: 5133 . 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 5134 5135 Level: advanced 5136 5137 Note: 5138 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 5139 routine allows bypassing that call. 5140 5141 .seealso: [](chapter_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5142 @*/ 5143 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B) 5144 { 5145 PetscContainer rB = NULL; 5146 MatParentState *rb = NULL; 5147 5148 PetscFunctionBegin; 5149 PetscCall(PetscNew(&rb)); 5150 rb->id = ((PetscObject)mat)->id; 5151 rb->state = 0; 5152 PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate)); 5153 PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB)); 5154 PetscCall(PetscContainerSetPointer(rB, rb)); 5155 PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault)); 5156 PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB)); 5157 PetscCall(PetscObjectDereference((PetscObject)rB)); 5158 PetscFunctionReturn(PETSC_SUCCESS); 5159 } 5160 5161 /*@ 5162 MatTranspose - Computes an in-place or out-of-place transpose of a matrix. 5163 5164 Collective 5165 5166 Input Parameters: 5167 + mat - the matrix to transpose 5168 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5169 5170 Output Parameter: 5171 . B - the transpose 5172 5173 Level: intermediate 5174 5175 Notes: 5176 If you use `MAT_INPLACE_MATRIX` then you must pass in &mat for B 5177 5178 `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 5179 transpose, call `MatTransposeSetPrecursor`(mat,B) before calling this routine. 5180 5181 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. 5182 5183 Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed. 5184 5185 If mat is unchanged from the last call this function returns immediately without recomputing the result 5186 5187 If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()` 5188 5189 .seealso: [](chapter_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`, 5190 `MatTransposeSymbolic()`, `MatCreateTranspose()` 5191 @*/ 5192 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B) 5193 { 5194 PetscContainer rB = NULL; 5195 MatParentState *rb = NULL; 5196 5197 PetscFunctionBegin; 5198 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5199 PetscValidType(mat, 1); 5200 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5201 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5202 PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first"); 5203 PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX"); 5204 MatCheckPreallocated(mat, 1); 5205 if (reuse == MAT_REUSE_MATRIX) { 5206 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5207 PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor()."); 5208 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5209 PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5210 if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS); 5211 } 5212 5213 PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0)); 5214 if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) { 5215 PetscUseTypeMethod(mat, transpose, reuse, B); 5216 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5217 } 5218 PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0)); 5219 5220 if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B)); 5221 if (reuse != MAT_INPLACE_MATRIX) { 5222 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5223 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5224 rb->state = ((PetscObject)mat)->state; 5225 rb->nonzerostate = mat->nonzerostate; 5226 } 5227 PetscFunctionReturn(PETSC_SUCCESS); 5228 } 5229 5230 /*@ 5231 MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix. 5232 5233 Collective 5234 5235 Input Parameter: 5236 . A - the matrix to transpose 5237 5238 Output Parameter: 5239 . 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 5240 numerical portion. 5241 5242 Level: intermediate 5243 5244 Note: 5245 This is not supported for many matrix types, use `MatTranspose()` in those cases 5246 5247 .seealso: [](chapter_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5248 @*/ 5249 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B) 5250 { 5251 PetscFunctionBegin; 5252 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5253 PetscValidType(A, 1); 5254 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5255 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5256 PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0)); 5257 PetscUseTypeMethod(A, transposesymbolic, B); 5258 PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0)); 5259 5260 PetscCall(MatTransposeSetPrecursor(A, *B)); 5261 PetscFunctionReturn(PETSC_SUCCESS); 5262 } 5263 5264 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B) 5265 { 5266 PetscContainer rB; 5267 MatParentState *rb; 5268 5269 PetscFunctionBegin; 5270 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5271 PetscValidType(A, 1); 5272 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5273 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5274 PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB)); 5275 PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()"); 5276 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5277 PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5278 PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure"); 5279 PetscFunctionReturn(PETSC_SUCCESS); 5280 } 5281 5282 /*@ 5283 MatIsTranspose - Test whether a matrix is another one's transpose, 5284 or its own, in which case it tests symmetry. 5285 5286 Collective 5287 5288 Input Parameters: 5289 + A - the matrix to test 5290 . B - the matrix to test against, this can equal the first parameter 5291 - tol - tolerance, differences between entries smaller than this are counted as zero 5292 5293 Output Parameter: 5294 . flg - the result 5295 5296 Level: intermediate 5297 5298 Notes: 5299 Only available for `MATAIJ` matrices. 5300 5301 The sequential algorithm has a running time of the order of the number of nonzeros; the parallel 5302 test involves parallel copies of the block-offdiagonal parts of the matrix. 5303 5304 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()` 5305 @*/ 5306 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5307 { 5308 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5309 5310 PetscFunctionBegin; 5311 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5312 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5313 PetscValidBoolPointer(flg, 4); 5314 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f)); 5315 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g)); 5316 *flg = PETSC_FALSE; 5317 if (f && g) { 5318 PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test"); 5319 PetscCall((*f)(A, B, tol, flg)); 5320 } else { 5321 MatType mattype; 5322 5323 PetscCall(MatGetType(f ? B : A, &mattype)); 5324 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype); 5325 } 5326 PetscFunctionReturn(PETSC_SUCCESS); 5327 } 5328 5329 /*@ 5330 MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate. 5331 5332 Collective 5333 5334 Input Parameters: 5335 + mat - the matrix to transpose and complex conjugate 5336 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5337 5338 Output Parameter: 5339 . B - the Hermitian transpose 5340 5341 Level: intermediate 5342 5343 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse` 5344 @*/ 5345 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B) 5346 { 5347 PetscFunctionBegin; 5348 PetscCall(MatTranspose(mat, reuse, B)); 5349 #if defined(PETSC_USE_COMPLEX) 5350 PetscCall(MatConjugate(*B)); 5351 #endif 5352 PetscFunctionReturn(PETSC_SUCCESS); 5353 } 5354 5355 /*@ 5356 MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose, 5357 5358 Collective 5359 5360 Input Parameters: 5361 + A - the matrix to test 5362 . B - the matrix to test against, this can equal the first parameter 5363 - tol - tolerance, differences between entries smaller than this are counted as zero 5364 5365 Output Parameter: 5366 . flg - the result 5367 5368 Level: intermediate 5369 5370 Notes: 5371 Only available for `MATAIJ` matrices. 5372 5373 The sequential algorithm 5374 has a running time of the order of the number of nonzeros; the parallel 5375 test involves parallel copies of the block-offdiagonal parts of the matrix. 5376 5377 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()` 5378 @*/ 5379 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5380 { 5381 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5382 5383 PetscFunctionBegin; 5384 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5385 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5386 PetscValidBoolPointer(flg, 4); 5387 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f)); 5388 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g)); 5389 if (f && g) { 5390 PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test"); 5391 PetscCall((*f)(A, B, tol, flg)); 5392 } 5393 PetscFunctionReturn(PETSC_SUCCESS); 5394 } 5395 5396 /*@ 5397 MatPermute - Creates a new matrix with rows and columns permuted from the 5398 original. 5399 5400 Collective 5401 5402 Input Parameters: 5403 + mat - the matrix to permute 5404 . row - row permutation, each processor supplies only the permutation for its rows 5405 - col - column permutation, each processor supplies only the permutation for its columns 5406 5407 Output Parameter: 5408 . B - the permuted matrix 5409 5410 Level: advanced 5411 5412 Note: 5413 The index sets map from row/col of permuted matrix to row/col of original matrix. 5414 The index sets should be on the same communicator as mat and have the same local sizes. 5415 5416 Developer Note: 5417 If you want to implement `MatPermute()` for a matrix type, and your approach doesn't 5418 exploit the fact that row and col are permutations, consider implementing the 5419 more general `MatCreateSubMatrix()` instead. 5420 5421 .seealso: [](chapter_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()` 5422 @*/ 5423 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B) 5424 { 5425 PetscFunctionBegin; 5426 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5427 PetscValidType(mat, 1); 5428 PetscValidHeaderSpecific(row, IS_CLASSID, 2); 5429 PetscValidHeaderSpecific(col, IS_CLASSID, 3); 5430 PetscValidPointer(B, 4); 5431 PetscCheckSameComm(mat, 1, row, 2); 5432 if (row != col) PetscCheckSameComm(row, 2, col, 3); 5433 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5434 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5435 PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name); 5436 MatCheckPreallocated(mat, 1); 5437 5438 if (mat->ops->permute) { 5439 PetscUseTypeMethod(mat, permute, row, col, B); 5440 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5441 } else { 5442 PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B)); 5443 } 5444 PetscFunctionReturn(PETSC_SUCCESS); 5445 } 5446 5447 /*@ 5448 MatEqual - Compares two matrices. 5449 5450 Collective 5451 5452 Input Parameters: 5453 + A - the first matrix 5454 - B - the second matrix 5455 5456 Output Parameter: 5457 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise. 5458 5459 Level: intermediate 5460 5461 .seealso: [](chapter_matrices), `Mat` 5462 @*/ 5463 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg) 5464 { 5465 PetscFunctionBegin; 5466 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5467 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5468 PetscValidType(A, 1); 5469 PetscValidType(B, 2); 5470 PetscValidBoolPointer(flg, 3); 5471 PetscCheckSameComm(A, 1, B, 2); 5472 MatCheckPreallocated(A, 1); 5473 MatCheckPreallocated(B, 2); 5474 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5475 PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5476 PetscCheck(A->rmap->N == B->rmap->N && A->cmap->N == B->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat B: global dim %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->N, B->rmap->N, A->cmap->N, 5477 B->cmap->N); 5478 if (A->ops->equal && A->ops->equal == B->ops->equal) { 5479 PetscUseTypeMethod(A, equal, B, flg); 5480 } else { 5481 PetscCall(MatMultEqual(A, B, 10, flg)); 5482 } 5483 PetscFunctionReturn(PETSC_SUCCESS); 5484 } 5485 5486 /*@ 5487 MatDiagonalScale - Scales a matrix on the left and right by diagonal 5488 matrices that are stored as vectors. Either of the two scaling 5489 matrices can be `NULL`. 5490 5491 Collective 5492 5493 Input Parameters: 5494 + mat - the matrix to be scaled 5495 . l - the left scaling vector (or `NULL`) 5496 - r - the right scaling vector (or `NULL`) 5497 5498 Level: intermediate 5499 5500 Note: 5501 `MatDiagonalScale()` computes A = LAR, where 5502 L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector) 5503 The L scales the rows of the matrix, the R scales the columns of the matrix. 5504 5505 .seealso: [](chapter_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()` 5506 @*/ 5507 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r) 5508 { 5509 PetscFunctionBegin; 5510 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5511 PetscValidType(mat, 1); 5512 if (l) { 5513 PetscValidHeaderSpecific(l, VEC_CLASSID, 2); 5514 PetscCheckSameComm(mat, 1, l, 2); 5515 } 5516 if (r) { 5517 PetscValidHeaderSpecific(r, VEC_CLASSID, 3); 5518 PetscCheckSameComm(mat, 1, r, 3); 5519 } 5520 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5521 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5522 MatCheckPreallocated(mat, 1); 5523 if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS); 5524 5525 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5526 PetscUseTypeMethod(mat, diagonalscale, l, r); 5527 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5528 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5529 if (l != r) mat->symmetric = PETSC_BOOL3_FALSE; 5530 PetscFunctionReturn(PETSC_SUCCESS); 5531 } 5532 5533 /*@ 5534 MatScale - Scales all elements of a matrix by a given number. 5535 5536 Logically Collective 5537 5538 Input Parameters: 5539 + mat - the matrix to be scaled 5540 - a - the scaling value 5541 5542 Level: intermediate 5543 5544 .seealso: [](chapter_matrices), `Mat`, `MatDiagonalScale()` 5545 @*/ 5546 PetscErrorCode MatScale(Mat mat, PetscScalar a) 5547 { 5548 PetscFunctionBegin; 5549 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5550 PetscValidType(mat, 1); 5551 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5552 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5553 PetscValidLogicalCollectiveScalar(mat, a, 2); 5554 MatCheckPreallocated(mat, 1); 5555 5556 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5557 if (a != (PetscScalar)1.0) { 5558 PetscUseTypeMethod(mat, scale, a); 5559 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5560 } 5561 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5562 PetscFunctionReturn(PETSC_SUCCESS); 5563 } 5564 5565 /*@ 5566 MatNorm - Calculates various norms of a matrix. 5567 5568 Collective 5569 5570 Input Parameters: 5571 + mat - the matrix 5572 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY` 5573 5574 Output Parameter: 5575 . nrm - the resulting norm 5576 5577 Level: intermediate 5578 5579 .seealso: [](chapter_matrices), `Mat` 5580 @*/ 5581 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm) 5582 { 5583 PetscFunctionBegin; 5584 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5585 PetscValidType(mat, 1); 5586 PetscValidRealPointer(nrm, 3); 5587 5588 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5589 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5590 MatCheckPreallocated(mat, 1); 5591 5592 PetscUseTypeMethod(mat, norm, type, nrm); 5593 PetscFunctionReturn(PETSC_SUCCESS); 5594 } 5595 5596 /* 5597 This variable is used to prevent counting of MatAssemblyBegin() that 5598 are called from within a MatAssemblyEnd(). 5599 */ 5600 static PetscInt MatAssemblyEnd_InUse = 0; 5601 /*@ 5602 MatAssemblyBegin - Begins assembling the matrix. This routine should 5603 be called after completing all calls to `MatSetValues()`. 5604 5605 Collective 5606 5607 Input Parameters: 5608 + mat - the matrix 5609 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5610 5611 Level: beginner 5612 5613 Notes: 5614 `MatSetValues()` generally caches the values that belong to other MPI processes. The matrix is ready to 5615 use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called. 5616 5617 Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES` 5618 in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before 5619 using the matrix. 5620 5621 ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the 5622 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 5623 a global collective operation requiring all processes that share the matrix. 5624 5625 Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed 5626 out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros 5627 before `MAT_FINAL_ASSEMBLY` so the space is not compressed out. 5628 5629 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()` 5630 @*/ 5631 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type) 5632 { 5633 PetscFunctionBegin; 5634 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5635 PetscValidType(mat, 1); 5636 MatCheckPreallocated(mat, 1); 5637 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?"); 5638 if (mat->assembled) { 5639 mat->was_assembled = PETSC_TRUE; 5640 mat->assembled = PETSC_FALSE; 5641 } 5642 5643 if (!MatAssemblyEnd_InUse) { 5644 PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0)); 5645 PetscTryTypeMethod(mat, assemblybegin, type); 5646 PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0)); 5647 } else PetscTryTypeMethod(mat, assemblybegin, type); 5648 PetscFunctionReturn(PETSC_SUCCESS); 5649 } 5650 5651 /*@ 5652 MatAssembled - Indicates if a matrix has been assembled and is ready for 5653 use; for example, in matrix-vector product. 5654 5655 Not Collective 5656 5657 Input Parameter: 5658 . mat - the matrix 5659 5660 Output Parameter: 5661 . assembled - `PETSC_TRUE` or `PETSC_FALSE` 5662 5663 Level: advanced 5664 5665 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()` 5666 @*/ 5667 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled) 5668 { 5669 PetscFunctionBegin; 5670 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5671 PetscValidBoolPointer(assembled, 2); 5672 *assembled = mat->assembled; 5673 PetscFunctionReturn(PETSC_SUCCESS); 5674 } 5675 5676 /*@ 5677 MatAssemblyEnd - Completes assembling the matrix. This routine should 5678 be called after `MatAssemblyBegin()`. 5679 5680 Collective 5681 5682 Input Parameters: 5683 + mat - the matrix 5684 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5685 5686 Options Database Keys: 5687 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatEndAssembly()` 5688 . -mat_view ::ascii_info_detail - Prints more detailed info 5689 . -mat_view - Prints matrix in ASCII format 5690 . -mat_view ::ascii_matlab - Prints matrix in Matlab format 5691 . -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 5692 . -display <name> - Sets display name (default is host) 5693 . -draw_pause <sec> - Sets number of seconds to pause after display 5694 . -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See [Using MATLAB with PETSc](ch_matlab)) 5695 . -viewer_socket_machine <machine> - Machine to use for socket 5696 . -viewer_socket_port <port> - Port number to use for socket 5697 - -mat_view binary:filename[:append] - Save matrix to file in binary format 5698 5699 Level: beginner 5700 5701 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()` 5702 @*/ 5703 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type) 5704 { 5705 static PetscInt inassm = 0; 5706 PetscBool flg = PETSC_FALSE; 5707 5708 PetscFunctionBegin; 5709 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5710 PetscValidType(mat, 1); 5711 5712 inassm++; 5713 MatAssemblyEnd_InUse++; 5714 if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */ 5715 PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0)); 5716 PetscTryTypeMethod(mat, assemblyend, type); 5717 PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0)); 5718 } else PetscTryTypeMethod(mat, assemblyend, type); 5719 5720 /* Flush assembly is not a true assembly */ 5721 if (type != MAT_FLUSH_ASSEMBLY) { 5722 if (mat->num_ass) { 5723 if (!mat->symmetry_eternal) { 5724 mat->symmetric = PETSC_BOOL3_UNKNOWN; 5725 mat->hermitian = PETSC_BOOL3_UNKNOWN; 5726 } 5727 if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN; 5728 if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN; 5729 } 5730 mat->num_ass++; 5731 mat->assembled = PETSC_TRUE; 5732 mat->ass_nonzerostate = mat->nonzerostate; 5733 } 5734 5735 mat->insertmode = NOT_SET_VALUES; 5736 MatAssemblyEnd_InUse--; 5737 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5738 if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) { 5739 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 5740 5741 if (mat->checksymmetryonassembly) { 5742 PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg)); 5743 if (flg) { 5744 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5745 } else { 5746 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5747 } 5748 } 5749 if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL)); 5750 } 5751 inassm--; 5752 PetscFunctionReturn(PETSC_SUCCESS); 5753 } 5754 5755 /*@ 5756 MatSetOption - Sets a parameter option for a matrix. Some options 5757 may be specific to certain storage formats. Some options 5758 determine how values will be inserted (or added). Sorted, 5759 row-oriented input will generally assemble the fastest. The default 5760 is row-oriented. 5761 5762 Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption` 5763 5764 Input Parameters: 5765 + mat - the matrix 5766 . option - the option, one of those listed below (and possibly others), 5767 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5768 5769 Options Describing Matrix Structure: 5770 + `MAT_SPD` - symmetric positive definite 5771 . `MAT_SYMMETRIC` - symmetric in terms of both structure and value 5772 . `MAT_HERMITIAN` - transpose is the complex conjugation 5773 . `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure 5774 . `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix 5775 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix 5776 - `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix 5777 5778 These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they 5779 do not need to be computed (usually at a high cost) 5780 5781 Options For Use with `MatSetValues()`: 5782 Insert a logically dense subblock, which can be 5783 . `MAT_ROW_ORIENTED` - row-oriented (default) 5784 5785 These options reflect the data you pass in with `MatSetValues()`; it has 5786 nothing to do with how the data is stored internally in the matrix 5787 data structure. 5788 5789 When (re)assembling a matrix, we can restrict the input for 5790 efficiency/debugging purposes. These options include 5791 + `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow) 5792 . `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated 5793 . `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries 5794 . `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry 5795 . `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly 5796 . `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if 5797 any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves 5798 performance for very large process counts. 5799 - `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset 5800 of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly 5801 functions, instead sending only neighbor messages. 5802 5803 Level: intermediate 5804 5805 Notes: 5806 Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg! 5807 5808 Some options are relevant only for particular matrix types and 5809 are thus ignored by others. Other options are not supported by 5810 certain matrix types and will generate an error message if set. 5811 5812 If using Fortran to compute a matrix, one may need to 5813 use the column-oriented option (or convert to the row-oriented 5814 format). 5815 5816 `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion 5817 that would generate a new entry in the nonzero structure is instead 5818 ignored. Thus, if memory has not already been allocated for this particular 5819 data, then the insertion is ignored. For dense matrices, in which 5820 the entire array is allocated, no entries are ever ignored. 5821 Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction 5822 5823 `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion 5824 that would generate a new entry in the nonzero structure instead produces 5825 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 5826 5827 `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion 5828 that would generate a new entry that has not been preallocated will 5829 instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats 5830 only.) This is a useful flag when debugging matrix memory preallocation. 5831 If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 5832 5833 `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for 5834 other processors should be dropped, rather than stashed. 5835 This is useful if you know that the "owning" processor is also 5836 always generating the correct matrix entries, so that PETSc need 5837 not transfer duplicate entries generated on another processor. 5838 5839 `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the 5840 searches during matrix assembly. When this flag is set, the hash table 5841 is created during the first matrix assembly. This hash table is 5842 used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()` 5843 to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag 5844 should be used with `MAT_USE_HASH_TABLE` flag. This option is currently 5845 supported by `MATMPIBAIJ` format only. 5846 5847 `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries 5848 are kept in the nonzero structure 5849 5850 `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating 5851 a zero location in the matrix 5852 5853 `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types 5854 5855 `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the 5856 zero row routines and thus improves performance for very large process counts. 5857 5858 `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular 5859 part of the matrix (since they should match the upper triangular part). 5860 5861 `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a 5862 single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common 5863 with finite difference schemes with non-periodic boundary conditions. 5864 5865 Developer Note: 5866 `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other 5867 places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRIC` or `MAT_SPD` would need to be changed back 5868 to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had 5869 not changed. 5870 5871 .seealso: [](chapter_matrices), `MatOption`, `Mat`, `MatGetOption()` 5872 @*/ 5873 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg) 5874 { 5875 PetscFunctionBegin; 5876 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5877 if (op > 0) { 5878 PetscValidLogicalCollectiveEnum(mat, op, 2); 5879 PetscValidLogicalCollectiveBool(mat, flg, 3); 5880 } 5881 5882 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); 5883 5884 switch (op) { 5885 case MAT_FORCE_DIAGONAL_ENTRIES: 5886 mat->force_diagonals = flg; 5887 PetscFunctionReturn(PETSC_SUCCESS); 5888 case MAT_NO_OFF_PROC_ENTRIES: 5889 mat->nooffprocentries = flg; 5890 PetscFunctionReturn(PETSC_SUCCESS); 5891 case MAT_SUBSET_OFF_PROC_ENTRIES: 5892 mat->assembly_subset = flg; 5893 if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */ 5894 #if !defined(PETSC_HAVE_MPIUNI) 5895 PetscCall(MatStashScatterDestroy_BTS(&mat->stash)); 5896 #endif 5897 mat->stash.first_assembly_done = PETSC_FALSE; 5898 } 5899 PetscFunctionReturn(PETSC_SUCCESS); 5900 case MAT_NO_OFF_PROC_ZERO_ROWS: 5901 mat->nooffproczerorows = flg; 5902 PetscFunctionReturn(PETSC_SUCCESS); 5903 case MAT_SPD: 5904 if (flg) { 5905 mat->spd = PETSC_BOOL3_TRUE; 5906 mat->symmetric = PETSC_BOOL3_TRUE; 5907 mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5908 } else { 5909 mat->spd = PETSC_BOOL3_FALSE; 5910 } 5911 break; 5912 case MAT_SYMMETRIC: 5913 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5914 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5915 #if !defined(PETSC_USE_COMPLEX) 5916 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5917 #endif 5918 break; 5919 case MAT_HERMITIAN: 5920 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5921 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5922 #if !defined(PETSC_USE_COMPLEX) 5923 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5924 #endif 5925 break; 5926 case MAT_STRUCTURALLY_SYMMETRIC: 5927 mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5928 break; 5929 case MAT_SYMMETRY_ETERNAL: 5930 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"); 5931 mat->symmetry_eternal = flg; 5932 if (flg) mat->structural_symmetry_eternal = PETSC_TRUE; 5933 break; 5934 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 5935 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"); 5936 mat->structural_symmetry_eternal = flg; 5937 break; 5938 case MAT_SPD_ETERNAL: 5939 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"); 5940 mat->spd_eternal = flg; 5941 if (flg) { 5942 mat->structural_symmetry_eternal = PETSC_TRUE; 5943 mat->symmetry_eternal = PETSC_TRUE; 5944 } 5945 break; 5946 case MAT_STRUCTURE_ONLY: 5947 mat->structure_only = flg; 5948 break; 5949 case MAT_SORTED_FULL: 5950 mat->sortedfull = flg; 5951 break; 5952 default: 5953 break; 5954 } 5955 PetscTryTypeMethod(mat, setoption, op, flg); 5956 PetscFunctionReturn(PETSC_SUCCESS); 5957 } 5958 5959 /*@ 5960 MatGetOption - Gets a parameter option that has been set for a matrix. 5961 5962 Logically Collective 5963 5964 Input Parameters: 5965 + mat - the matrix 5966 - option - the option, this only responds to certain options, check the code for which ones 5967 5968 Output Parameter: 5969 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5970 5971 Level: intermediate 5972 5973 Notes: 5974 Can only be called after `MatSetSizes()` and `MatSetType()` have been set. 5975 5976 Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or 5977 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 5978 5979 .seealso: [](chapter_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, 5980 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 5981 @*/ 5982 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg) 5983 { 5984 PetscFunctionBegin; 5985 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5986 PetscValidType(mat, 1); 5987 5988 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); 5989 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()"); 5990 5991 switch (op) { 5992 case MAT_NO_OFF_PROC_ENTRIES: 5993 *flg = mat->nooffprocentries; 5994 break; 5995 case MAT_NO_OFF_PROC_ZERO_ROWS: 5996 *flg = mat->nooffproczerorows; 5997 break; 5998 case MAT_SYMMETRIC: 5999 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()"); 6000 break; 6001 case MAT_HERMITIAN: 6002 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()"); 6003 break; 6004 case MAT_STRUCTURALLY_SYMMETRIC: 6005 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()"); 6006 break; 6007 case MAT_SPD: 6008 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()"); 6009 break; 6010 case MAT_SYMMETRY_ETERNAL: 6011 *flg = mat->symmetry_eternal; 6012 break; 6013 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6014 *flg = mat->symmetry_eternal; 6015 break; 6016 default: 6017 break; 6018 } 6019 PetscFunctionReturn(PETSC_SUCCESS); 6020 } 6021 6022 /*@ 6023 MatZeroEntries - Zeros all entries of a matrix. For sparse matrices 6024 this routine retains the old nonzero structure. 6025 6026 Logically Collective 6027 6028 Input Parameter: 6029 . mat - the matrix 6030 6031 Level: intermediate 6032 6033 Note: 6034 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. 6035 See the Performance chapter of the users manual for information on preallocating matrices. 6036 6037 .seealso: [](chapter_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()` 6038 @*/ 6039 PetscErrorCode MatZeroEntries(Mat mat) 6040 { 6041 PetscFunctionBegin; 6042 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6043 PetscValidType(mat, 1); 6044 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6045 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"); 6046 MatCheckPreallocated(mat, 1); 6047 6048 PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0)); 6049 PetscUseTypeMethod(mat, zeroentries); 6050 PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0)); 6051 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6052 PetscFunctionReturn(PETSC_SUCCESS); 6053 } 6054 6055 /*@ 6056 MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal) 6057 of a set of rows and columns of a matrix. 6058 6059 Collective 6060 6061 Input Parameters: 6062 + mat - the matrix 6063 . numRows - the number of rows/columns to zero 6064 . rows - the global row indices 6065 . diag - value put in the diagonal of the eliminated rows 6066 . x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call 6067 - b - optional vector of the right hand side, that will be adjusted by provided solution entries 6068 6069 Level: intermediate 6070 6071 Notes: 6072 This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6073 6074 For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`. 6075 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 6076 6077 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6078 Krylov method to take advantage of the known solution on the zeroed rows. 6079 6080 For the parallel case, all processes that share the matrix (i.e., 6081 those in the communicator used for matrix creation) MUST call this 6082 routine, regardless of whether any rows being zeroed are owned by 6083 them. 6084 6085 Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix. 6086 6087 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6088 list only rows local to itself). 6089 6090 The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine. 6091 6092 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6093 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6094 @*/ 6095 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6096 { 6097 PetscFunctionBegin; 6098 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6099 PetscValidType(mat, 1); 6100 if (numRows) PetscValidIntPointer(rows, 3); 6101 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6102 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6103 MatCheckPreallocated(mat, 1); 6104 6105 PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b); 6106 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6107 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6108 PetscFunctionReturn(PETSC_SUCCESS); 6109 } 6110 6111 /*@ 6112 MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal) 6113 of a set of rows and columns of a matrix. 6114 6115 Collective 6116 6117 Input Parameters: 6118 + mat - the matrix 6119 . is - the rows to zero 6120 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6121 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6122 - b - optional vector of right hand side, that will be adjusted by provided solution 6123 6124 Level: intermediate 6125 6126 Note: 6127 See `MatZeroRowsColumns()` for details on how this routine operates. 6128 6129 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6130 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()` 6131 @*/ 6132 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6133 { 6134 PetscInt numRows; 6135 const PetscInt *rows; 6136 6137 PetscFunctionBegin; 6138 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6139 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6140 PetscValidType(mat, 1); 6141 PetscValidType(is, 2); 6142 PetscCall(ISGetLocalSize(is, &numRows)); 6143 PetscCall(ISGetIndices(is, &rows)); 6144 PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b)); 6145 PetscCall(ISRestoreIndices(is, &rows)); 6146 PetscFunctionReturn(PETSC_SUCCESS); 6147 } 6148 6149 /*@ 6150 MatZeroRows - Zeros all entries (except possibly the main diagonal) 6151 of a set of rows of a matrix. 6152 6153 Collective 6154 6155 Input Parameters: 6156 + mat - the matrix 6157 . numRows - the number of rows to zero 6158 . rows - the global row indices 6159 . diag - value put in the diagonal of the zeroed rows 6160 . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call 6161 - b - optional vector of right hand side, that will be adjusted by provided solution entries 6162 6163 Level: intermediate 6164 6165 Notes: 6166 This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6167 6168 For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`. 6169 6170 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6171 Krylov method to take advantage of the known solution on the zeroed rows. 6172 6173 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) 6174 from the matrix. 6175 6176 Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix 6177 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 6178 formats this does not alter the nonzero structure. 6179 6180 If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure 6181 of the matrix is not changed the values are 6182 merely zeroed. 6183 6184 The user can set a value in the diagonal entry (or for the `MATAIJ` format 6185 formats can optionally remove the main diagonal entry from the 6186 nonzero structure as well, by passing 0.0 as the final argument). 6187 6188 For the parallel case, all processes that share the matrix (i.e., 6189 those in the communicator used for matrix creation) MUST call this 6190 routine, regardless of whether any rows being zeroed are owned by 6191 them. 6192 6193 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6194 list only rows local to itself). 6195 6196 You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it 6197 owns that are to be zeroed. This saves a global synchronization in the implementation. 6198 6199 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6200 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE` 6201 @*/ 6202 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6203 { 6204 PetscFunctionBegin; 6205 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6206 PetscValidType(mat, 1); 6207 if (numRows) PetscValidIntPointer(rows, 3); 6208 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6209 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6210 MatCheckPreallocated(mat, 1); 6211 6212 PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b); 6213 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6214 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6215 PetscFunctionReturn(PETSC_SUCCESS); 6216 } 6217 6218 /*@ 6219 MatZeroRowsIS - Zeros all entries (except possibly the main diagonal) 6220 of a set of rows of a matrix. 6221 6222 Collective 6223 6224 Input Parameters: 6225 + mat - the matrix 6226 . is - index set of rows to remove (if `NULL` then no row is removed) 6227 . diag - value put in all diagonals of eliminated rows 6228 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6229 - b - optional vector of right hand side, that will be adjusted by provided solution 6230 6231 Level: intermediate 6232 6233 Note: 6234 See `MatZeroRows()` for details on how this routine operates. 6235 6236 .seealso: [](chapter_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6237 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6238 @*/ 6239 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6240 { 6241 PetscInt numRows = 0; 6242 const PetscInt *rows = NULL; 6243 6244 PetscFunctionBegin; 6245 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6246 PetscValidType(mat, 1); 6247 if (is) { 6248 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6249 PetscCall(ISGetLocalSize(is, &numRows)); 6250 PetscCall(ISGetIndices(is, &rows)); 6251 } 6252 PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b)); 6253 if (is) PetscCall(ISRestoreIndices(is, &rows)); 6254 PetscFunctionReturn(PETSC_SUCCESS); 6255 } 6256 6257 /*@ 6258 MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal) 6259 of a set of rows of a matrix. These rows must be local to the process. 6260 6261 Collective 6262 6263 Input Parameters: 6264 + mat - the matrix 6265 . numRows - the number of rows to remove 6266 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6267 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 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 Notes: 6274 See `MatZeroRows()` for details on how this routine operates. 6275 6276 The grid coordinates are across the entire grid, not just the local portion 6277 6278 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6279 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6280 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6281 `DM_BOUNDARY_PERIODIC` boundary type. 6282 6283 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 6284 a single value per point) you can skip filling those indices. 6285 6286 Fortran Note: 6287 `idxm` and `idxn` should be declared as 6288 $ MatStencil idxm(4, m) 6289 and the values inserted using 6290 .vb 6291 idxm(MatStencil_i, 1) = i 6292 idxm(MatStencil_j, 1) = j 6293 idxm(MatStencil_k, 1) = k 6294 idxm(MatStencil_c, 1) = c 6295 etc 6296 .ve 6297 6298 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6299 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6300 @*/ 6301 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6302 { 6303 PetscInt dim = mat->stencil.dim; 6304 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6305 PetscInt *dims = mat->stencil.dims + 1; 6306 PetscInt *starts = mat->stencil.starts; 6307 PetscInt *dxm = (PetscInt *)rows; 6308 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6309 6310 PetscFunctionBegin; 6311 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6312 PetscValidType(mat, 1); 6313 if (numRows) PetscValidPointer(rows, 3); 6314 6315 PetscCall(PetscMalloc1(numRows, &jdxm)); 6316 for (i = 0; i < numRows; ++i) { 6317 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6318 for (j = 0; j < 3 - sdim; ++j) dxm++; 6319 /* Local index in X dir */ 6320 tmp = *dxm++ - starts[0]; 6321 /* Loop over remaining dimensions */ 6322 for (j = 0; j < dim - 1; ++j) { 6323 /* If nonlocal, set index to be negative */ 6324 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6325 /* Update local index */ 6326 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6327 } 6328 /* Skip component slot if necessary */ 6329 if (mat->stencil.noc) dxm++; 6330 /* Local row number */ 6331 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6332 } 6333 PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b)); 6334 PetscCall(PetscFree(jdxm)); 6335 PetscFunctionReturn(PETSC_SUCCESS); 6336 } 6337 6338 /*@ 6339 MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal) 6340 of a set of rows and columns of a matrix. 6341 6342 Collective 6343 6344 Input Parameters: 6345 + mat - the matrix 6346 . numRows - the number of rows/columns to remove 6347 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6348 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6349 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6350 - b - optional vector of right hand side, that will be adjusted by provided solution 6351 6352 Level: intermediate 6353 6354 Notes: 6355 See `MatZeroRowsColumns()` for details on how this routine operates. 6356 6357 The grid coordinates are across the entire grid, not just the local portion 6358 6359 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6360 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6361 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6362 `DM_BOUNDARY_PERIODIC` boundary type. 6363 6364 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 6365 a single value per point) you can skip filling those indices. 6366 6367 Fortran Note: 6368 `idxm` and `idxn` should be declared as 6369 $ MatStencil idxm(4, m) 6370 and the values inserted using 6371 .vb 6372 idxm(MatStencil_i, 1) = i 6373 idxm(MatStencil_j, 1) = j 6374 idxm(MatStencil_k, 1) = k 6375 idxm(MatStencil_c, 1) = c 6376 etc 6377 .ve 6378 6379 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6380 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()` 6381 @*/ 6382 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6383 { 6384 PetscInt dim = mat->stencil.dim; 6385 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6386 PetscInt *dims = mat->stencil.dims + 1; 6387 PetscInt *starts = mat->stencil.starts; 6388 PetscInt *dxm = (PetscInt *)rows; 6389 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6390 6391 PetscFunctionBegin; 6392 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6393 PetscValidType(mat, 1); 6394 if (numRows) PetscValidPointer(rows, 3); 6395 6396 PetscCall(PetscMalloc1(numRows, &jdxm)); 6397 for (i = 0; i < numRows; ++i) { 6398 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6399 for (j = 0; j < 3 - sdim; ++j) dxm++; 6400 /* Local index in X dir */ 6401 tmp = *dxm++ - starts[0]; 6402 /* Loop over remaining dimensions */ 6403 for (j = 0; j < dim - 1; ++j) { 6404 /* If nonlocal, set index to be negative */ 6405 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6406 /* Update local index */ 6407 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6408 } 6409 /* Skip component slot if necessary */ 6410 if (mat->stencil.noc) dxm++; 6411 /* Local row number */ 6412 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6413 } 6414 PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b)); 6415 PetscCall(PetscFree(jdxm)); 6416 PetscFunctionReturn(PETSC_SUCCESS); 6417 } 6418 6419 /*@C 6420 MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal) 6421 of a set of rows of a matrix; using local numbering of rows. 6422 6423 Collective 6424 6425 Input Parameters: 6426 + mat - the matrix 6427 . numRows - the number of rows to remove 6428 . rows - the local row indices 6429 . diag - value put in all diagonals of eliminated rows 6430 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6431 - b - optional vector of right hand side, that will be adjusted by provided solution 6432 6433 Level: intermediate 6434 6435 Notes: 6436 Before calling `MatZeroRowsLocal()`, the user must first set the 6437 local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`. 6438 6439 See `MatZeroRows()` for details on how this routine operates. 6440 6441 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`, 6442 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6443 @*/ 6444 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6445 { 6446 PetscFunctionBegin; 6447 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6448 PetscValidType(mat, 1); 6449 if (numRows) PetscValidIntPointer(rows, 3); 6450 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6451 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6452 MatCheckPreallocated(mat, 1); 6453 6454 if (mat->ops->zerorowslocal) { 6455 PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b); 6456 } else { 6457 IS is, newis; 6458 const PetscInt *newRows; 6459 6460 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6461 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6462 PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis)); 6463 PetscCall(ISGetIndices(newis, &newRows)); 6464 PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b); 6465 PetscCall(ISRestoreIndices(newis, &newRows)); 6466 PetscCall(ISDestroy(&newis)); 6467 PetscCall(ISDestroy(&is)); 6468 } 6469 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6470 PetscFunctionReturn(PETSC_SUCCESS); 6471 } 6472 6473 /*@ 6474 MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal) 6475 of a set of rows of a matrix; using local numbering of rows. 6476 6477 Collective 6478 6479 Input Parameters: 6480 + mat - the matrix 6481 . is - index set of rows to remove 6482 . diag - value put in all diagonals of eliminated rows 6483 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6484 - b - optional vector of right hand side, that will be adjusted by provided solution 6485 6486 Level: intermediate 6487 6488 Notes: 6489 Before calling `MatZeroRowsLocalIS()`, the user must first set the 6490 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6491 6492 See `MatZeroRows()` for details on how this routine operates. 6493 6494 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6495 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6496 @*/ 6497 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6498 { 6499 PetscInt numRows; 6500 const PetscInt *rows; 6501 6502 PetscFunctionBegin; 6503 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6504 PetscValidType(mat, 1); 6505 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6506 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6507 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6508 MatCheckPreallocated(mat, 1); 6509 6510 PetscCall(ISGetLocalSize(is, &numRows)); 6511 PetscCall(ISGetIndices(is, &rows)); 6512 PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b)); 6513 PetscCall(ISRestoreIndices(is, &rows)); 6514 PetscFunctionReturn(PETSC_SUCCESS); 6515 } 6516 6517 /*@ 6518 MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal) 6519 of a set of rows and columns of a matrix; using local numbering of rows. 6520 6521 Collective 6522 6523 Input Parameters: 6524 + mat - the matrix 6525 . numRows - the number of rows to remove 6526 . rows - the global row indices 6527 . diag - value put in all diagonals of eliminated rows 6528 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6529 - b - optional vector of right hand side, that will be adjusted by provided solution 6530 6531 Level: intermediate 6532 6533 Notes: 6534 Before calling `MatZeroRowsColumnsLocal()`, the user must first set the 6535 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6536 6537 See `MatZeroRowsColumns()` for details on how this routine operates. 6538 6539 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6540 `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6541 @*/ 6542 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6543 { 6544 IS is, newis; 6545 const PetscInt *newRows; 6546 6547 PetscFunctionBegin; 6548 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6549 PetscValidType(mat, 1); 6550 if (numRows) PetscValidIntPointer(rows, 3); 6551 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6552 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6553 MatCheckPreallocated(mat, 1); 6554 6555 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6556 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6557 PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis)); 6558 PetscCall(ISGetIndices(newis, &newRows)); 6559 PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b); 6560 PetscCall(ISRestoreIndices(newis, &newRows)); 6561 PetscCall(ISDestroy(&newis)); 6562 PetscCall(ISDestroy(&is)); 6563 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6564 PetscFunctionReturn(PETSC_SUCCESS); 6565 } 6566 6567 /*@ 6568 MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal) 6569 of a set of rows and columns of a matrix; using local numbering of rows. 6570 6571 Collective 6572 6573 Input Parameters: 6574 + mat - the matrix 6575 . is - index set of rows to remove 6576 . diag - value put in all diagonals of eliminated rows 6577 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6578 - b - optional vector of right hand side, that will be adjusted by provided solution 6579 6580 Level: intermediate 6581 6582 Notes: 6583 Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the 6584 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6585 6586 See `MatZeroRowsColumns()` for details on how this routine operates. 6587 6588 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6589 `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6590 @*/ 6591 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6592 { 6593 PetscInt numRows; 6594 const PetscInt *rows; 6595 6596 PetscFunctionBegin; 6597 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6598 PetscValidType(mat, 1); 6599 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6600 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6601 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6602 MatCheckPreallocated(mat, 1); 6603 6604 PetscCall(ISGetLocalSize(is, &numRows)); 6605 PetscCall(ISGetIndices(is, &rows)); 6606 PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b)); 6607 PetscCall(ISRestoreIndices(is, &rows)); 6608 PetscFunctionReturn(PETSC_SUCCESS); 6609 } 6610 6611 /*@C 6612 MatGetSize - Returns the numbers of rows and columns in a matrix. 6613 6614 Not Collective 6615 6616 Input Parameter: 6617 . mat - the matrix 6618 6619 Output Parameters: 6620 + m - the number of global rows 6621 - n - the number of global columns 6622 6623 Level: beginner 6624 6625 Note: 6626 Both output parameters can be `NULL` on input. 6627 6628 .seealso: [](chapter_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()` 6629 @*/ 6630 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n) 6631 { 6632 PetscFunctionBegin; 6633 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6634 if (m) *m = mat->rmap->N; 6635 if (n) *n = mat->cmap->N; 6636 PetscFunctionReturn(PETSC_SUCCESS); 6637 } 6638 6639 /*@C 6640 MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns 6641 of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`. 6642 6643 Not Collective 6644 6645 Input Parameter: 6646 . mat - the matrix 6647 6648 Output Parameters: 6649 + m - the number of local rows, use `NULL` to not obtain this value 6650 - n - the number of local columns, use `NULL` to not obtain this value 6651 6652 Level: beginner 6653 6654 .seealso: [](chapter_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()` 6655 @*/ 6656 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n) 6657 { 6658 PetscFunctionBegin; 6659 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6660 if (m) PetscValidIntPointer(m, 2); 6661 if (n) PetscValidIntPointer(n, 3); 6662 if (m) *m = mat->rmap->n; 6663 if (n) *n = mat->cmap->n; 6664 PetscFunctionReturn(PETSC_SUCCESS); 6665 } 6666 6667 /*@C 6668 MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by 6669 this processor. (The columns of the "diagonal block" for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts. 6670 6671 Not Collective, unless matrix has not been allocated, then collective 6672 6673 Input Parameter: 6674 . mat - the matrix 6675 6676 Output Parameters: 6677 + m - the global index of the first local column, use `NULL` to not obtain this value 6678 - n - one more than the global index of the last local column, use `NULL` to not obtain this value 6679 6680 Level: developer 6681 6682 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout` 6683 @*/ 6684 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n) 6685 { 6686 PetscFunctionBegin; 6687 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6688 PetscValidType(mat, 1); 6689 if (m) PetscValidIntPointer(m, 2); 6690 if (n) PetscValidIntPointer(n, 3); 6691 MatCheckPreallocated(mat, 1); 6692 if (m) *m = mat->cmap->rstart; 6693 if (n) *n = mat->cmap->rend; 6694 PetscFunctionReturn(PETSC_SUCCESS); 6695 } 6696 6697 /*@C 6698 MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6699 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 6700 vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts 6701 6702 Not Collective 6703 6704 Input Parameter: 6705 . mat - the matrix 6706 6707 Output Parameters: 6708 + m - the global index of the first local row, use `NULL` to not obtain this value 6709 - n - one more than the global index of the last local row, use `NULL` to not obtain this value 6710 6711 Level: beginner 6712 6713 Note: 6714 This function requires that the matrix be preallocated. If you have not preallocated, consider using 6715 `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N) 6716 and then `MPI_Scan()` to calculate prefix sums of the local sizes. 6717 6718 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, 6719 `PetscLayout` 6720 @*/ 6721 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n) 6722 { 6723 PetscFunctionBegin; 6724 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6725 PetscValidType(mat, 1); 6726 if (m) PetscValidIntPointer(m, 2); 6727 if (n) PetscValidIntPointer(n, 3); 6728 MatCheckPreallocated(mat, 1); 6729 if (m) *m = mat->rmap->rstart; 6730 if (n) *n = mat->rmap->rend; 6731 PetscFunctionReturn(PETSC_SUCCESS); 6732 } 6733 6734 /*@C 6735 MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6736 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 6737 vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts 6738 6739 Not Collective, unless matrix has not been allocated 6740 6741 Input Parameter: 6742 . mat - the matrix 6743 6744 Output Parameter: 6745 . ranges - start of each processors portion plus one more than the total length at the end 6746 6747 Level: beginner 6748 6749 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout` 6750 @*/ 6751 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges) 6752 { 6753 PetscFunctionBegin; 6754 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6755 PetscValidType(mat, 1); 6756 MatCheckPreallocated(mat, 1); 6757 PetscCall(PetscLayoutGetRanges(mat->rmap, ranges)); 6758 PetscFunctionReturn(PETSC_SUCCESS); 6759 } 6760 6761 /*@C 6762 MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by 6763 each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts. 6764 6765 Not Collective, unless matrix has not been allocated 6766 6767 Input Parameter: 6768 . mat - the matrix 6769 6770 Output Parameter: 6771 . ranges - start of each processors portion plus one more then the total length at the end 6772 6773 Level: beginner 6774 6775 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()` 6776 @*/ 6777 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges) 6778 { 6779 PetscFunctionBegin; 6780 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6781 PetscValidType(mat, 1); 6782 MatCheckPreallocated(mat, 1); 6783 PetscCall(PetscLayoutGetRanges(mat->cmap, ranges)); 6784 PetscFunctionReturn(PETSC_SUCCESS); 6785 } 6786 6787 /*@C 6788 MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this 6789 corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership 6790 is more complicated. See :any:`<sec_matlayout>` for details on matrix layouts. 6791 6792 Not Collective 6793 6794 Input Parameter: 6795 . A - matrix 6796 6797 Output Parameters: 6798 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value 6799 - cols - columns in which this process owns elements, use `NULL` to not obtain this value 6800 6801 Level: intermediate 6802 6803 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK`` 6804 @*/ 6805 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols) 6806 { 6807 PetscErrorCode (*f)(Mat, IS *, IS *); 6808 6809 PetscFunctionBegin; 6810 MatCheckPreallocated(A, 1); 6811 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f)); 6812 if (f) { 6813 PetscCall((*f)(A, rows, cols)); 6814 } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */ 6815 if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows)); 6816 if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols)); 6817 } 6818 PetscFunctionReturn(PETSC_SUCCESS); 6819 } 6820 6821 /*@C 6822 MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()` 6823 Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()` 6824 to complete the factorization. 6825 6826 Collective 6827 6828 Input Parameters: 6829 + fact - the factorized matrix obtained with `MatGetFactor()` 6830 . mat - the matrix 6831 . row - row permutation 6832 . col - column permutation 6833 - info - structure containing 6834 .vb 6835 levels - number of levels of fill. 6836 expected fill - as ratio of original fill. 6837 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 6838 missing diagonal entries) 6839 .ve 6840 6841 Level: developer 6842 6843 Notes: 6844 See [Matrix Factorization](sec_matfactor) for additional information. 6845 6846 Most users should employ the `KSP` interface for linear solvers 6847 instead of working directly with matrix algebra routines such as this. 6848 See, e.g., `KSPCreate()`. 6849 6850 Uses the definition of level of fill as in Y. Saad, 2003 6851 6852 Developer Note: 6853 The Fortran interface is not autogenerated as the 6854 interface definition cannot be generated correctly [due to `MatFactorInfo`] 6855 6856 References: 6857 . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003 6858 6859 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 6860 `MatGetOrdering()`, `MatFactorInfo` 6861 @*/ 6862 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 6863 { 6864 PetscFunctionBegin; 6865 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 6866 PetscValidType(mat, 2); 6867 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 6868 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 6869 PetscValidPointer(info, 5); 6870 PetscValidPointer(fact, 1); 6871 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels); 6872 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 6873 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6874 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6875 MatCheckPreallocated(mat, 2); 6876 6877 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0)); 6878 PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info); 6879 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0)); 6880 PetscFunctionReturn(PETSC_SUCCESS); 6881 } 6882 6883 /*@C 6884 MatICCFactorSymbolic - Performs symbolic incomplete 6885 Cholesky factorization for a symmetric matrix. Use 6886 `MatCholeskyFactorNumeric()` to complete the factorization. 6887 6888 Collective 6889 6890 Input Parameters: 6891 + fact - the factorized matrix obtained with `MatGetFactor()` 6892 . mat - the matrix to be factored 6893 . perm - row and column permutation 6894 - info - structure containing 6895 .vb 6896 levels - number of levels of fill. 6897 expected fill - as ratio of original fill. 6898 .ve 6899 6900 Level: developer 6901 6902 Notes: 6903 Most users should employ the `KSP` interface for linear solvers 6904 instead of working directly with matrix algebra routines such as this. 6905 See, e.g., `KSPCreate()`. 6906 6907 This uses the definition of level of fill as in Y. Saad, 2003 6908 6909 Developer Note: 6910 The Fortran interface is not autogenerated as the 6911 interface definition cannot be generated correctly [due to `MatFactorInfo`] 6912 6913 References: 6914 . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003 6915 6916 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 6917 @*/ 6918 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 6919 { 6920 PetscFunctionBegin; 6921 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 6922 PetscValidType(mat, 2); 6923 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 6924 PetscValidPointer(info, 4); 6925 PetscValidPointer(fact, 1); 6926 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6927 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels); 6928 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 6929 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6930 MatCheckPreallocated(mat, 2); 6931 6932 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 6933 PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info); 6934 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 6935 PetscFunctionReturn(PETSC_SUCCESS); 6936 } 6937 6938 /*@C 6939 MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat 6940 points to an array of valid matrices, they may be reused to store the new 6941 submatrices. 6942 6943 Collective 6944 6945 Input Parameters: 6946 + mat - the matrix 6947 . n - the number of submatrixes to be extracted (on this processor, may be zero) 6948 . irow - index set of rows to extract 6949 . icol - index set of columns to extract 6950 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 6951 6952 Output Parameter: 6953 . submat - the array of submatrices 6954 6955 Level: advanced 6956 6957 Notes: 6958 `MatCreateSubMatrices()` can extract ONLY sequential submatrices 6959 (from both sequential and parallel matrices). Use `MatCreateSubMatrix()` 6960 to extract a parallel submatrix. 6961 6962 Some matrix types place restrictions on the row and column 6963 indices, such as that they be sorted or that they be equal to each other. 6964 6965 The index sets may not have duplicate entries. 6966 6967 When extracting submatrices from a parallel matrix, each processor can 6968 form a different submatrix by setting the rows and columns of its 6969 individual index sets according to the local submatrix desired. 6970 6971 When finished using the submatrices, the user should destroy 6972 them with `MatDestroySubMatrices()`. 6973 6974 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 6975 original matrix has not changed from that last call to `MatCreateSubMatrices()`. 6976 6977 This routine creates the matrices in submat; you should NOT create them before 6978 calling it. It also allocates the array of matrix pointers submat. 6979 6980 For `MATBAIJ` matrices the index sets must respect the block structure, that is if they 6981 request one row/column in a block, they must request all rows/columns that are in 6982 that block. For example, if the block size is 2 you cannot request just row 0 and 6983 column 0. 6984 6985 Fortran Note: 6986 The Fortran interface is slightly different from that given below; it 6987 requires one to pass in as `submat` a `Mat` (integer) array of size at least n+1. 6988 6989 .seealso: [](chapter_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 6990 @*/ 6991 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 6992 { 6993 PetscInt i; 6994 PetscBool eq; 6995 6996 PetscFunctionBegin; 6997 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6998 PetscValidType(mat, 1); 6999 if (n) { 7000 PetscValidPointer(irow, 3); 7001 for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3); 7002 PetscValidPointer(icol, 4); 7003 for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4); 7004 } 7005 PetscValidPointer(submat, 6); 7006 if (n && scall == MAT_REUSE_MATRIX) { 7007 PetscValidPointer(*submat, 6); 7008 for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6); 7009 } 7010 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7011 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7012 MatCheckPreallocated(mat, 1); 7013 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7014 PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat); 7015 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7016 for (i = 0; i < n; i++) { 7017 (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */ 7018 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7019 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7020 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 7021 if (mat->boundtocpu && mat->bindingpropagates) { 7022 PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE)); 7023 PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE)); 7024 } 7025 #endif 7026 } 7027 PetscFunctionReturn(PETSC_SUCCESS); 7028 } 7029 7030 /*@C 7031 MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms). 7032 7033 Collective 7034 7035 Input Parameters: 7036 + mat - the matrix 7037 . n - the number of submatrixes to be extracted 7038 . irow - index set of rows to extract 7039 . icol - index set of columns to extract 7040 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7041 7042 Output Parameter: 7043 . submat - the array of submatrices 7044 7045 Level: advanced 7046 7047 Note: 7048 This is used by `PCGASM` 7049 7050 .seealso: [](chapter_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7051 @*/ 7052 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7053 { 7054 PetscInt i; 7055 PetscBool eq; 7056 7057 PetscFunctionBegin; 7058 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7059 PetscValidType(mat, 1); 7060 if (n) { 7061 PetscValidPointer(irow, 3); 7062 PetscValidHeaderSpecific(*irow, IS_CLASSID, 3); 7063 PetscValidPointer(icol, 4); 7064 PetscValidHeaderSpecific(*icol, IS_CLASSID, 4); 7065 } 7066 PetscValidPointer(submat, 6); 7067 if (n && scall == MAT_REUSE_MATRIX) { 7068 PetscValidPointer(*submat, 6); 7069 PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6); 7070 } 7071 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7072 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7073 MatCheckPreallocated(mat, 1); 7074 7075 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7076 PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat); 7077 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7078 for (i = 0; i < n; i++) { 7079 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7080 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7081 } 7082 PetscFunctionReturn(PETSC_SUCCESS); 7083 } 7084 7085 /*@C 7086 MatDestroyMatrices - Destroys an array of matrices. 7087 7088 Collective 7089 7090 Input Parameters: 7091 + n - the number of local matrices 7092 - mat - the matrices (this is a pointer to the array of matrices) 7093 7094 Level: advanced 7095 7096 Note: 7097 Frees not only the matrices, but also the array that contains the matrices 7098 7099 Fortran Note: 7100 This does not free the array. 7101 7102 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()` 7103 @*/ 7104 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[]) 7105 { 7106 PetscInt i; 7107 7108 PetscFunctionBegin; 7109 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7110 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7111 PetscValidPointer(mat, 2); 7112 7113 for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i])); 7114 7115 /* memory is allocated even if n = 0 */ 7116 PetscCall(PetscFree(*mat)); 7117 PetscFunctionReturn(PETSC_SUCCESS); 7118 } 7119 7120 /*@C 7121 MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`. 7122 7123 Collective 7124 7125 Input Parameters: 7126 + n - the number of local matrices 7127 - mat - the matrices (this is a pointer to the array of matrices, just to match the calling 7128 sequence of `MatCreateSubMatrices()`) 7129 7130 Level: advanced 7131 7132 Note: 7133 Frees not only the matrices, but also the array that contains the matrices 7134 7135 Fortran Note: 7136 This does not free the array. 7137 7138 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7139 @*/ 7140 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[]) 7141 { 7142 Mat mat0; 7143 7144 PetscFunctionBegin; 7145 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7146 /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */ 7147 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7148 PetscValidPointer(mat, 2); 7149 7150 mat0 = (*mat)[0]; 7151 if (mat0 && mat0->ops->destroysubmatrices) { 7152 PetscCall((*mat0->ops->destroysubmatrices)(n, mat)); 7153 } else { 7154 PetscCall(MatDestroyMatrices(n, mat)); 7155 } 7156 PetscFunctionReturn(PETSC_SUCCESS); 7157 } 7158 7159 /*@C 7160 MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process 7161 7162 Collective 7163 7164 Input Parameter: 7165 . mat - the matrix 7166 7167 Output Parameter: 7168 . matstruct - the sequential matrix with the nonzero structure of mat 7169 7170 Level: developer 7171 7172 .seealso: [](chapter_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7173 @*/ 7174 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct) 7175 { 7176 PetscFunctionBegin; 7177 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7178 PetscValidPointer(matstruct, 2); 7179 7180 PetscValidType(mat, 1); 7181 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7182 MatCheckPreallocated(mat, 1); 7183 7184 PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7185 PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct); 7186 PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7187 PetscFunctionReturn(PETSC_SUCCESS); 7188 } 7189 7190 /*@C 7191 MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`. 7192 7193 Collective 7194 7195 Input Parameter: 7196 . mat - the matrix (this is a pointer to the array of matrices, just to match the calling 7197 sequence of `MatGetSeqNonzeroStructure()`) 7198 7199 Level: advanced 7200 7201 Note: 7202 Frees not only the matrices, but also the array that contains the matrices 7203 7204 .seealso: [](chapter_matrices), `Mat`, `MatGetSeqNonzeroStructure()` 7205 @*/ 7206 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat) 7207 { 7208 PetscFunctionBegin; 7209 PetscValidPointer(mat, 1); 7210 PetscCall(MatDestroy(mat)); 7211 PetscFunctionReturn(PETSC_SUCCESS); 7212 } 7213 7214 /*@ 7215 MatIncreaseOverlap - Given a set of submatrices indicated by index sets, 7216 replaces the index sets by larger ones that represent submatrices with 7217 additional overlap. 7218 7219 Collective 7220 7221 Input Parameters: 7222 + mat - the matrix 7223 . n - the number of index sets 7224 . is - the array of index sets (these index sets will changed during the call) 7225 - ov - the additional overlap requested 7226 7227 Options Database Key: 7228 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7229 7230 Level: developer 7231 7232 Note: 7233 The computed overlap preserves the matrix block sizes when the blocks are square. 7234 That is: if a matrix nonzero for a given block would increase the overlap all columns associated with 7235 that block are included in the overlap regardless of whether each specific column would increase the overlap. 7236 7237 .seealso: [](chapter_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()` 7238 @*/ 7239 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov) 7240 { 7241 PetscInt i, bs, cbs; 7242 7243 PetscFunctionBegin; 7244 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7245 PetscValidType(mat, 1); 7246 PetscValidLogicalCollectiveInt(mat, n, 2); 7247 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7248 if (n) { 7249 PetscValidPointer(is, 3); 7250 for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3); 7251 } 7252 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7253 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7254 MatCheckPreallocated(mat, 1); 7255 7256 if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS); 7257 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7258 PetscUseTypeMethod(mat, increaseoverlap, n, is, ov); 7259 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7260 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 7261 if (bs == cbs) { 7262 for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs)); 7263 } 7264 PetscFunctionReturn(PETSC_SUCCESS); 7265 } 7266 7267 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt); 7268 7269 /*@ 7270 MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across 7271 a sub communicator, replaces the index sets by larger ones that represent submatrices with 7272 additional overlap. 7273 7274 Collective 7275 7276 Input Parameters: 7277 + mat - the matrix 7278 . n - the number of index sets 7279 . is - the array of index sets (these index sets will changed during the call) 7280 - ov - the additional overlap requested 7281 7282 ` Options Database Key: 7283 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7284 7285 Level: developer 7286 7287 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()` 7288 @*/ 7289 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov) 7290 { 7291 PetscInt i; 7292 7293 PetscFunctionBegin; 7294 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7295 PetscValidType(mat, 1); 7296 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7297 if (n) { 7298 PetscValidPointer(is, 3); 7299 PetscValidHeaderSpecific(*is, IS_CLASSID, 3); 7300 } 7301 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7302 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7303 MatCheckPreallocated(mat, 1); 7304 if (!ov) PetscFunctionReturn(PETSC_SUCCESS); 7305 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7306 for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov)); 7307 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7308 PetscFunctionReturn(PETSC_SUCCESS); 7309 } 7310 7311 /*@ 7312 MatGetBlockSize - Returns the matrix block size. 7313 7314 Not Collective 7315 7316 Input Parameter: 7317 . mat - the matrix 7318 7319 Output Parameter: 7320 . bs - block size 7321 7322 Level: intermediate 7323 7324 Notes: 7325 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7326 7327 If the block size has not been set yet this routine returns 1. 7328 7329 .seealso: [](chapter_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()` 7330 @*/ 7331 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs) 7332 { 7333 PetscFunctionBegin; 7334 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7335 PetscValidIntPointer(bs, 2); 7336 *bs = PetscAbs(mat->rmap->bs); 7337 PetscFunctionReturn(PETSC_SUCCESS); 7338 } 7339 7340 /*@ 7341 MatGetBlockSizes - Returns the matrix block row and column sizes. 7342 7343 Not Collective 7344 7345 Input Parameter: 7346 . mat - the matrix 7347 7348 Output Parameters: 7349 + rbs - row block size 7350 - cbs - column block size 7351 7352 Level: intermediate 7353 7354 Notes: 7355 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7356 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7357 7358 If a block size has not been set yet this routine returns 1. 7359 7360 .seealso: [](chapter_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()` 7361 @*/ 7362 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs) 7363 { 7364 PetscFunctionBegin; 7365 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7366 if (rbs) PetscValidIntPointer(rbs, 2); 7367 if (cbs) PetscValidIntPointer(cbs, 3); 7368 if (rbs) *rbs = PetscAbs(mat->rmap->bs); 7369 if (cbs) *cbs = PetscAbs(mat->cmap->bs); 7370 PetscFunctionReturn(PETSC_SUCCESS); 7371 } 7372 7373 /*@ 7374 MatSetBlockSize - Sets the matrix block size. 7375 7376 Logically Collective 7377 7378 Input Parameters: 7379 + mat - the matrix 7380 - bs - block size 7381 7382 Level: intermediate 7383 7384 Notes: 7385 Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix. 7386 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7387 7388 For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size 7389 is compatible with the matrix local sizes. 7390 7391 .seealso: [](chapter_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()` 7392 @*/ 7393 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs) 7394 { 7395 PetscFunctionBegin; 7396 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7397 PetscValidLogicalCollectiveInt(mat, bs, 2); 7398 PetscCall(MatSetBlockSizes(mat, bs, bs)); 7399 PetscFunctionReturn(PETSC_SUCCESS); 7400 } 7401 7402 typedef struct { 7403 PetscInt n; 7404 IS *is; 7405 Mat *mat; 7406 PetscObjectState nonzerostate; 7407 Mat C; 7408 } EnvelopeData; 7409 7410 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata) 7411 { 7412 for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i])); 7413 PetscCall(PetscFree(edata->is)); 7414 PetscCall(PetscFree(edata)); 7415 return PETSC_SUCCESS; 7416 } 7417 7418 /* 7419 MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores 7420 the sizes of these blocks in the matrix. An individual block may lie over several processes. 7421 7422 Collective 7423 7424 Input Parameter: 7425 . mat - the matrix 7426 7427 Notes: 7428 There can be zeros within the blocks 7429 7430 The blocks can overlap between processes, including laying on more than two processes 7431 7432 .seealso: [](chapter_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()` 7433 */ 7434 static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat) 7435 { 7436 PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend; 7437 PetscInt *diag, *odiag, sc; 7438 VecScatter scatter; 7439 PetscScalar *seqv; 7440 const PetscScalar *parv; 7441 const PetscInt *ia, *ja; 7442 PetscBool set, flag, done; 7443 Mat AA = mat, A; 7444 MPI_Comm comm; 7445 PetscMPIInt rank, size, tag; 7446 MPI_Status status; 7447 PetscContainer container; 7448 EnvelopeData *edata; 7449 Vec seq, par; 7450 IS isglobal; 7451 7452 PetscFunctionBegin; 7453 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7454 PetscCall(MatIsSymmetricKnown(mat, &set, &flag)); 7455 if (!set || !flag) { 7456 /* TOO: only needs nonzero structure of transpose */ 7457 PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA)); 7458 PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN)); 7459 } 7460 PetscCall(MatAIJGetLocalMat(AA, &A)); 7461 PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7462 PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix"); 7463 7464 PetscCall(MatGetLocalSize(mat, &n, NULL)); 7465 PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag)); 7466 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 7467 PetscCallMPI(MPI_Comm_size(comm, &size)); 7468 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7469 7470 PetscCall(PetscMalloc2(n, &sizes, n, &starts)); 7471 7472 if (rank > 0) { 7473 PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7474 PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7475 } 7476 PetscCall(MatGetOwnershipRange(mat, &rstart, NULL)); 7477 for (i = 0; i < n; i++) { 7478 env = PetscMax(env, ja[ia[i + 1] - 1]); 7479 II = rstart + i; 7480 if (env == II) { 7481 starts[lblocks] = tbs; 7482 sizes[lblocks++] = 1 + II - tbs; 7483 tbs = 1 + II; 7484 } 7485 } 7486 if (rank < size - 1) { 7487 PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm)); 7488 PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm)); 7489 } 7490 7491 PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7492 if (!set || !flag) PetscCall(MatDestroy(&AA)); 7493 PetscCall(MatDestroy(&A)); 7494 7495 PetscCall(PetscNew(&edata)); 7496 PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate)); 7497 edata->n = lblocks; 7498 /* create IS needed for extracting blocks from the original matrix */ 7499 PetscCall(PetscMalloc1(lblocks, &edata->is)); 7500 for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i])); 7501 7502 /* Create the resulting inverse matrix structure with preallocation information */ 7503 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C)); 7504 PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 7505 PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat)); 7506 PetscCall(MatSetType(edata->C, MATAIJ)); 7507 7508 /* Communicate the start and end of each row, from each block to the correct rank */ 7509 /* TODO: Use PetscSF instead of VecScatter */ 7510 for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i]; 7511 PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq)); 7512 PetscCall(VecGetArrayWrite(seq, &seqv)); 7513 for (PetscInt i = 0; i < lblocks; i++) { 7514 for (PetscInt j = 0; j < sizes[i]; j++) { 7515 seqv[cnt] = starts[i]; 7516 seqv[cnt + 1] = starts[i] + sizes[i]; 7517 cnt += 2; 7518 } 7519 } 7520 PetscCall(VecRestoreArrayWrite(seq, &seqv)); 7521 PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 7522 sc -= cnt; 7523 PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par)); 7524 PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal)); 7525 PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter)); 7526 PetscCall(ISDestroy(&isglobal)); 7527 PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7528 PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7529 PetscCall(VecScatterDestroy(&scatter)); 7530 PetscCall(VecDestroy(&seq)); 7531 PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend)); 7532 PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag)); 7533 PetscCall(VecGetArrayRead(par, &parv)); 7534 cnt = 0; 7535 PetscCall(MatGetSize(mat, NULL, &n)); 7536 for (PetscInt i = 0; i < mat->rmap->n; i++) { 7537 PetscInt start, end, d = 0, od = 0; 7538 7539 start = (PetscInt)PetscRealPart(parv[cnt]); 7540 end = (PetscInt)PetscRealPart(parv[cnt + 1]); 7541 cnt += 2; 7542 7543 if (start < cstart) { 7544 od += cstart - start + n - cend; 7545 d += cend - cstart; 7546 } else if (start < cend) { 7547 od += n - cend; 7548 d += cend - start; 7549 } else od += n - start; 7550 if (end <= cstart) { 7551 od -= cstart - end + n - cend; 7552 d -= cend - cstart; 7553 } else if (end < cend) { 7554 od -= n - cend; 7555 d -= cend - end; 7556 } else od -= n - end; 7557 7558 odiag[i] = od; 7559 diag[i] = d; 7560 } 7561 PetscCall(VecRestoreArrayRead(par, &parv)); 7562 PetscCall(VecDestroy(&par)); 7563 PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL)); 7564 PetscCall(PetscFree2(diag, odiag)); 7565 PetscCall(PetscFree2(sizes, starts)); 7566 7567 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container)); 7568 PetscCall(PetscContainerSetPointer(container, edata)); 7569 PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy)); 7570 PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container)); 7571 PetscCall(PetscObjectDereference((PetscObject)container)); 7572 PetscFunctionReturn(PETSC_SUCCESS); 7573 } 7574 7575 /*@ 7576 MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A 7577 7578 Collective 7579 7580 Input Parameters: 7581 + A - the matrix 7582 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine 7583 7584 Output Parameter: 7585 . C - matrix with inverted block diagonal of `A` 7586 7587 Level: advanced 7588 7589 Note: 7590 For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal. 7591 7592 .seealso: [](chapter_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()` 7593 @*/ 7594 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C) 7595 { 7596 PetscContainer container; 7597 EnvelopeData *edata; 7598 PetscObjectState nonzerostate; 7599 7600 PetscFunctionBegin; 7601 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7602 if (!container) { 7603 PetscCall(MatComputeVariableBlockEnvelope(A)); 7604 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7605 } 7606 PetscCall(PetscContainerGetPointer(container, (void **)&edata)); 7607 PetscCall(MatGetNonzeroState(A, &nonzerostate)); 7608 PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure"); 7609 PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output"); 7610 7611 PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat)); 7612 *C = edata->C; 7613 7614 for (PetscInt i = 0; i < edata->n; i++) { 7615 Mat D; 7616 PetscScalar *dvalues; 7617 7618 PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D)); 7619 PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE)); 7620 PetscCall(MatSeqDenseInvert(D)); 7621 PetscCall(MatDenseGetArray(D, &dvalues)); 7622 PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES)); 7623 PetscCall(MatDestroy(&D)); 7624 } 7625 PetscCall(MatDestroySubMatrices(edata->n, &edata->mat)); 7626 PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY)); 7627 PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY)); 7628 PetscFunctionReturn(PETSC_SUCCESS); 7629 } 7630 7631 /*@ 7632 MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size 7633 7634 Logically Collective 7635 7636 Input Parameters: 7637 + mat - the matrix 7638 . nblocks - the number of blocks on this process, each block can only exist on a single process 7639 - bsizes - the block sizes 7640 7641 Level: intermediate 7642 7643 Notes: 7644 Currently used by `PCVPBJACOBI` for `MATAIJ` matrices 7645 7646 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. 7647 7648 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, 7649 `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI` 7650 @*/ 7651 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes) 7652 { 7653 PetscInt i, ncnt = 0, nlocal; 7654 7655 PetscFunctionBegin; 7656 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7657 PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero"); 7658 PetscCall(MatGetLocalSize(mat, &nlocal, NULL)); 7659 for (i = 0; i < nblocks; i++) ncnt += bsizes[i]; 7660 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); 7661 PetscCall(PetscFree(mat->bsizes)); 7662 mat->nblocks = nblocks; 7663 PetscCall(PetscMalloc1(nblocks, &mat->bsizes)); 7664 PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks)); 7665 PetscFunctionReturn(PETSC_SUCCESS); 7666 } 7667 7668 /*@C 7669 MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size 7670 7671 Logically Collective; No Fortran Support 7672 7673 Input Parameter: 7674 . mat - the matrix 7675 7676 Output Parameters: 7677 + nblocks - the number of blocks on this process 7678 - bsizes - the block sizes 7679 7680 Level: intermediate 7681 7682 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()` 7683 @*/ 7684 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes) 7685 { 7686 PetscFunctionBegin; 7687 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7688 *nblocks = mat->nblocks; 7689 *bsizes = mat->bsizes; 7690 PetscFunctionReturn(PETSC_SUCCESS); 7691 } 7692 7693 /*@ 7694 MatSetBlockSizes - Sets the matrix block row and column sizes. 7695 7696 Logically Collective 7697 7698 Input Parameters: 7699 + mat - the matrix 7700 . rbs - row block size 7701 - cbs - column block size 7702 7703 Level: intermediate 7704 7705 Notes: 7706 Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix. 7707 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7708 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7709 7710 For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes 7711 are compatible with the matrix local sizes. 7712 7713 The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`. 7714 7715 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()` 7716 @*/ 7717 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs) 7718 { 7719 PetscFunctionBegin; 7720 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7721 PetscValidLogicalCollectiveInt(mat, rbs, 2); 7722 PetscValidLogicalCollectiveInt(mat, cbs, 3); 7723 PetscTryTypeMethod(mat, setblocksizes, rbs, cbs); 7724 if (mat->rmap->refcnt) { 7725 ISLocalToGlobalMapping l2g = NULL; 7726 PetscLayout nmap = NULL; 7727 7728 PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap)); 7729 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g)); 7730 PetscCall(PetscLayoutDestroy(&mat->rmap)); 7731 mat->rmap = nmap; 7732 mat->rmap->mapping = l2g; 7733 } 7734 if (mat->cmap->refcnt) { 7735 ISLocalToGlobalMapping l2g = NULL; 7736 PetscLayout nmap = NULL; 7737 7738 PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap)); 7739 if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g)); 7740 PetscCall(PetscLayoutDestroy(&mat->cmap)); 7741 mat->cmap = nmap; 7742 mat->cmap->mapping = l2g; 7743 } 7744 PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs)); 7745 PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs)); 7746 PetscFunctionReturn(PETSC_SUCCESS); 7747 } 7748 7749 /*@ 7750 MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices 7751 7752 Logically Collective 7753 7754 Input Parameters: 7755 + mat - the matrix 7756 . fromRow - matrix from which to copy row block size 7757 - fromCol - matrix from which to copy column block size (can be same as fromRow) 7758 7759 Level: developer 7760 7761 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()` 7762 @*/ 7763 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol) 7764 { 7765 PetscFunctionBegin; 7766 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7767 PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2); 7768 PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3); 7769 if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs)); 7770 if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs)); 7771 PetscFunctionReturn(PETSC_SUCCESS); 7772 } 7773 7774 /*@ 7775 MatResidual - Default routine to calculate the residual r = b - Ax 7776 7777 Collective 7778 7779 Input Parameters: 7780 + mat - the matrix 7781 . b - the right-hand-side 7782 - x - the approximate solution 7783 7784 Output Parameter: 7785 . r - location to store the residual 7786 7787 Level: developer 7788 7789 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()` 7790 @*/ 7791 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r) 7792 { 7793 PetscFunctionBegin; 7794 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7795 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 7796 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 7797 PetscValidHeaderSpecific(r, VEC_CLASSID, 4); 7798 PetscValidType(mat, 1); 7799 MatCheckPreallocated(mat, 1); 7800 PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0)); 7801 if (!mat->ops->residual) { 7802 PetscCall(MatMult(mat, x, r)); 7803 PetscCall(VecAYPX(r, -1.0, b)); 7804 } else { 7805 PetscUseTypeMethod(mat, residual, b, x, r); 7806 } 7807 PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0)); 7808 PetscFunctionReturn(PETSC_SUCCESS); 7809 } 7810 7811 /*MC 7812 MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix 7813 7814 Synopsis: 7815 MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 7816 7817 Not Collective 7818 7819 Input Parameters: 7820 + A - the matrix 7821 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7822 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7823 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7824 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7825 always used. 7826 7827 Output Parameters: 7828 + n - number of local rows in the (possibly compressed) matrix 7829 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 7830 . ja - the column indices 7831 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7832 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7833 7834 Level: developer 7835 7836 Note: 7837 Use `MatRestoreRowIJF90()` when you no longer need access to the data 7838 7839 .seealso: [](chapter_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()` 7840 M*/ 7841 7842 /*MC 7843 MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()` 7844 7845 Synopsis: 7846 MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 7847 7848 Not Collective 7849 7850 Input Parameters: 7851 + A - the matrix 7852 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7853 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7854 inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7855 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7856 always used. 7857 . n - number of local rows in the (possibly compressed) matrix 7858 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 7859 . ja - the column indices 7860 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7861 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7862 7863 Level: developer 7864 7865 .seealso: [](chapter_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()` 7866 M*/ 7867 7868 /*@C 7869 MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix 7870 7871 Collective 7872 7873 Input Parameters: 7874 + mat - the matrix 7875 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7876 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7877 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7878 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7879 always used. 7880 7881 Output Parameters: 7882 + n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed 7883 . 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 7884 . ja - the column indices, use `NULL` if not needed 7885 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7886 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7887 7888 Level: developer 7889 7890 Notes: 7891 You CANNOT change any of the ia[] or ja[] values. 7892 7893 Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values. 7894 7895 Fortran Notes: 7896 Use 7897 .vb 7898 PetscInt, pointer :: ia(:),ja(:) 7899 call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr) 7900 ! Access the ith and jth entries via ia(i) and ja(j) 7901 .ve 7902 `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()` 7903 7904 .seealso: [](chapter_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()` 7905 @*/ 7906 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7907 { 7908 PetscFunctionBegin; 7909 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7910 PetscValidType(mat, 1); 7911 if (n) PetscValidIntPointer(n, 5); 7912 if (ia) PetscValidPointer(ia, 6); 7913 if (ja) PetscValidPointer(ja, 7); 7914 if (done) PetscValidBoolPointer(done, 8); 7915 MatCheckPreallocated(mat, 1); 7916 if (!mat->ops->getrowij && done) *done = PETSC_FALSE; 7917 else { 7918 if (done) *done = PETSC_TRUE; 7919 PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0)); 7920 PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done); 7921 PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0)); 7922 } 7923 PetscFunctionReturn(PETSC_SUCCESS); 7924 } 7925 7926 /*@C 7927 MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices. 7928 7929 Collective 7930 7931 Input Parameters: 7932 + mat - the matrix 7933 . shift - 1 or zero indicating we want the indices starting at 0 or 1 7934 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be 7935 symmetrized 7936 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7937 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7938 always used. 7939 . n - number of columns in the (possibly compressed) matrix 7940 . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix 7941 - ja - the row indices 7942 7943 Output Parameter: 7944 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned 7945 7946 Level: developer 7947 7948 .seealso: [](chapter_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 7949 @*/ 7950 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7951 { 7952 PetscFunctionBegin; 7953 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7954 PetscValidType(mat, 1); 7955 PetscValidIntPointer(n, 5); 7956 if (ia) PetscValidPointer(ia, 6); 7957 if (ja) PetscValidPointer(ja, 7); 7958 PetscValidBoolPointer(done, 8); 7959 MatCheckPreallocated(mat, 1); 7960 if (!mat->ops->getcolumnij) *done = PETSC_FALSE; 7961 else { 7962 *done = PETSC_TRUE; 7963 PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 7964 } 7965 PetscFunctionReturn(PETSC_SUCCESS); 7966 } 7967 7968 /*@C 7969 MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`. 7970 7971 Collective 7972 7973 Input Parameters: 7974 + mat - the matrix 7975 . shift - 1 or zero indicating we want the indices starting at 0 or 1 7976 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7977 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7978 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7979 always used. 7980 . n - size of (possibly compressed) matrix 7981 . ia - the row pointers 7982 - ja - the column indices 7983 7984 Output Parameter: 7985 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 7986 7987 Level: developer 7988 7989 Note: 7990 This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental 7991 us of the array after it has been restored. If you pass `NULL`, it will 7992 not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid. 7993 7994 Fortran Note: 7995 `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()` 7996 7997 .seealso: [](chapter_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()` 7998 @*/ 7999 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8000 { 8001 PetscFunctionBegin; 8002 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8003 PetscValidType(mat, 1); 8004 if (ia) PetscValidPointer(ia, 6); 8005 if (ja) PetscValidPointer(ja, 7); 8006 if (done) PetscValidBoolPointer(done, 8); 8007 MatCheckPreallocated(mat, 1); 8008 8009 if (!mat->ops->restorerowij && done) *done = PETSC_FALSE; 8010 else { 8011 if (done) *done = PETSC_TRUE; 8012 PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8013 if (n) *n = 0; 8014 if (ia) *ia = NULL; 8015 if (ja) *ja = NULL; 8016 } 8017 PetscFunctionReturn(PETSC_SUCCESS); 8018 } 8019 8020 /*@C 8021 MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`. 8022 8023 Collective 8024 8025 Input Parameters: 8026 + mat - the matrix 8027 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8028 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8029 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8030 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8031 always used. 8032 8033 Output Parameters: 8034 + n - size of (possibly compressed) matrix 8035 . ia - the column pointers 8036 . ja - the row indices 8037 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8038 8039 Level: developer 8040 8041 .seealso: [](chapter_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()` 8042 @*/ 8043 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8044 { 8045 PetscFunctionBegin; 8046 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8047 PetscValidType(mat, 1); 8048 if (ia) PetscValidPointer(ia, 6); 8049 if (ja) PetscValidPointer(ja, 7); 8050 PetscValidBoolPointer(done, 8); 8051 MatCheckPreallocated(mat, 1); 8052 8053 if (!mat->ops->restorecolumnij) *done = PETSC_FALSE; 8054 else { 8055 *done = PETSC_TRUE; 8056 PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8057 if (n) *n = 0; 8058 if (ia) *ia = NULL; 8059 if (ja) *ja = NULL; 8060 } 8061 PetscFunctionReturn(PETSC_SUCCESS); 8062 } 8063 8064 /*@C 8065 MatColoringPatch -Used inside matrix coloring routines that use `MatGetRowIJ()` and/or `MatGetColumnIJ()`. 8066 8067 Collective 8068 8069 Input Parameters: 8070 + mat - the matrix 8071 . ncolors - maximum color value 8072 . n - number of entries in colorarray 8073 - colorarray - array indicating color for each column 8074 8075 Output Parameter: 8076 . iscoloring - coloring generated using colorarray information 8077 8078 Level: developer 8079 8080 .seealso: [](chapter_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()` 8081 @*/ 8082 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring) 8083 { 8084 PetscFunctionBegin; 8085 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8086 PetscValidType(mat, 1); 8087 PetscValidIntPointer(colorarray, 4); 8088 PetscValidPointer(iscoloring, 5); 8089 MatCheckPreallocated(mat, 1); 8090 8091 if (!mat->ops->coloringpatch) { 8092 PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring)); 8093 } else { 8094 PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring); 8095 } 8096 PetscFunctionReturn(PETSC_SUCCESS); 8097 } 8098 8099 /*@ 8100 MatSetUnfactored - Resets a factored matrix to be treated as unfactored. 8101 8102 Logically Collective 8103 8104 Input Parameter: 8105 . mat - the factored matrix to be reset 8106 8107 Level: developer 8108 8109 Notes: 8110 This routine should be used only with factored matrices formed by in-place 8111 factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE` 8112 format). This option can save memory, for example, when solving nonlinear 8113 systems with a matrix-free Newton-Krylov method and a matrix-based, in-place 8114 ILU(0) preconditioner. 8115 8116 One can specify in-place ILU(0) factorization by calling 8117 .vb 8118 PCType(pc,PCILU); 8119 PCFactorSeUseInPlace(pc); 8120 .ve 8121 or by using the options -pc_type ilu -pc_factor_in_place 8122 8123 In-place factorization ILU(0) can also be used as a local 8124 solver for the blocks within the block Jacobi or additive Schwarz 8125 methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc 8126 for details on setting local solver options. 8127 8128 Most users should employ the `KSP` interface for linear solvers 8129 instead of working directly with matrix algebra routines such as this. 8130 See, e.g., `KSPCreate()`. 8131 8132 .seealso: [](chapter_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()` 8133 @*/ 8134 PetscErrorCode MatSetUnfactored(Mat mat) 8135 { 8136 PetscFunctionBegin; 8137 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8138 PetscValidType(mat, 1); 8139 MatCheckPreallocated(mat, 1); 8140 mat->factortype = MAT_FACTOR_NONE; 8141 if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS); 8142 PetscUseTypeMethod(mat, setunfactored); 8143 PetscFunctionReturn(PETSC_SUCCESS); 8144 } 8145 8146 /*MC 8147 MatDenseGetArrayF90 - Accesses a matrix array from Fortran 8148 8149 Synopsis: 8150 MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8151 8152 Not Collective 8153 8154 Input Parameter: 8155 . x - matrix 8156 8157 Output Parameters: 8158 + xx_v - the Fortran pointer to the array 8159 - ierr - error code 8160 8161 Example of Usage: 8162 .vb 8163 PetscScalar, pointer xx_v(:,:) 8164 .... 8165 call MatDenseGetArrayF90(x,xx_v,ierr) 8166 a = xx_v(3) 8167 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8168 .ve 8169 8170 Level: advanced 8171 8172 .seealso: [](chapter_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()` 8173 M*/ 8174 8175 /*MC 8176 MatDenseRestoreArrayF90 - Restores a matrix array that has been 8177 accessed with `MatDenseGetArrayF90()`. 8178 8179 Synopsis: 8180 MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8181 8182 Not Collective 8183 8184 Input Parameters: 8185 + x - matrix 8186 - xx_v - the Fortran90 pointer to the array 8187 8188 Output Parameter: 8189 . ierr - error code 8190 8191 Example of Usage: 8192 .vb 8193 PetscScalar, pointer xx_v(:,:) 8194 .... 8195 call MatDenseGetArrayF90(x,xx_v,ierr) 8196 a = xx_v(3) 8197 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8198 .ve 8199 8200 Level: advanced 8201 8202 .seealso: [](chapter_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()` 8203 M*/ 8204 8205 /*MC 8206 MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran. 8207 8208 Synopsis: 8209 MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8210 8211 Not Collective 8212 8213 Input Parameter: 8214 . x - matrix 8215 8216 Output Parameters: 8217 + xx_v - the Fortran pointer to the array 8218 - ierr - error code 8219 8220 Example of Usage: 8221 .vb 8222 PetscScalar, pointer xx_v(:) 8223 .... 8224 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8225 a = xx_v(3) 8226 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8227 .ve 8228 8229 Level: advanced 8230 8231 .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()` 8232 M*/ 8233 8234 /*MC 8235 MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been 8236 accessed with `MatSeqAIJGetArrayF90()`. 8237 8238 Synopsis: 8239 MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8240 8241 Not Collective 8242 8243 Input Parameters: 8244 + x - matrix 8245 - xx_v - the Fortran90 pointer to the array 8246 8247 Output Parameter: 8248 . ierr - error code 8249 8250 Example of Usage: 8251 .vb 8252 PetscScalar, pointer xx_v(:) 8253 .... 8254 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8255 a = xx_v(3) 8256 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8257 .ve 8258 8259 Level: advanced 8260 8261 .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()` 8262 M*/ 8263 8264 /*@ 8265 MatCreateSubMatrix - Gets a single submatrix on the same number of processors 8266 as the original matrix. 8267 8268 Collective 8269 8270 Input Parameters: 8271 + mat - the original matrix 8272 . isrow - parallel `IS` containing the rows this processor should obtain 8273 . 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. 8274 - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 8275 8276 Output Parameter: 8277 . newmat - the new submatrix, of the same type as the original matrix 8278 8279 Level: advanced 8280 8281 Notes: 8282 The submatrix will be able to be multiplied with vectors using the same layout as `iscol`. 8283 8284 Some matrix types place restrictions on the row and column indices, such 8285 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; 8286 for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row. 8287 8288 The index sets may not have duplicate entries. 8289 8290 The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`, 8291 the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls 8292 to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX` 8293 will reuse the matrix generated the first time. You should call `MatDestroy()` on `newmat` when 8294 you are finished using it. 8295 8296 The communicator of the newly obtained matrix is ALWAYS the same as the communicator of 8297 the input matrix. 8298 8299 If `iscol` is `NULL` then all columns are obtained (not supported in Fortran). 8300 8301 Example usage: 8302 Consider the following 8x8 matrix with 34 non-zero values, that is 8303 assembled across 3 processors. Let's assume that proc0 owns 3 rows, 8304 proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 8305 as follows 8306 .vb 8307 1 2 0 | 0 3 0 | 0 4 8308 Proc0 0 5 6 | 7 0 0 | 8 0 8309 9 0 10 | 11 0 0 | 12 0 8310 ------------------------------------- 8311 13 0 14 | 15 16 17 | 0 0 8312 Proc1 0 18 0 | 19 20 21 | 0 0 8313 0 0 0 | 22 23 0 | 24 0 8314 ------------------------------------- 8315 Proc2 25 26 27 | 0 0 28 | 29 0 8316 30 0 0 | 31 32 33 | 0 34 8317 .ve 8318 8319 Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6]. The resulting submatrix is 8320 8321 .vb 8322 2 0 | 0 3 0 | 0 8323 Proc0 5 6 | 7 0 0 | 8 8324 ------------------------------- 8325 Proc1 18 0 | 19 20 21 | 0 8326 ------------------------------- 8327 Proc2 26 27 | 0 0 28 | 29 8328 0 0 | 31 32 33 | 0 8329 .ve 8330 8331 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()` 8332 @*/ 8333 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat) 8334 { 8335 PetscMPIInt size; 8336 Mat *local; 8337 IS iscoltmp; 8338 PetscBool flg; 8339 8340 PetscFunctionBegin; 8341 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8342 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 8343 if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 8344 PetscValidPointer(newmat, 5); 8345 if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5); 8346 PetscValidType(mat, 1); 8347 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8348 PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX"); 8349 8350 MatCheckPreallocated(mat, 1); 8351 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8352 8353 if (!iscol || isrow == iscol) { 8354 PetscBool stride; 8355 PetscMPIInt grabentirematrix = 0, grab; 8356 PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride)); 8357 if (stride) { 8358 PetscInt first, step, n, rstart, rend; 8359 PetscCall(ISStrideGetInfo(isrow, &first, &step)); 8360 if (step == 1) { 8361 PetscCall(MatGetOwnershipRange(mat, &rstart, &rend)); 8362 if (rstart == first) { 8363 PetscCall(ISGetLocalSize(isrow, &n)); 8364 if (n == rend - rstart) grabentirematrix = 1; 8365 } 8366 } 8367 } 8368 PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat))); 8369 if (grab) { 8370 PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n")); 8371 if (cll == MAT_INITIAL_MATRIX) { 8372 *newmat = mat; 8373 PetscCall(PetscObjectReference((PetscObject)mat)); 8374 } 8375 PetscFunctionReturn(PETSC_SUCCESS); 8376 } 8377 } 8378 8379 if (!iscol) { 8380 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp)); 8381 } else { 8382 iscoltmp = iscol; 8383 } 8384 8385 /* if original matrix is on just one processor then use submatrix generated */ 8386 if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) { 8387 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat)); 8388 goto setproperties; 8389 } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) { 8390 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local)); 8391 *newmat = *local; 8392 PetscCall(PetscFree(local)); 8393 goto setproperties; 8394 } else if (!mat->ops->createsubmatrix) { 8395 /* Create a new matrix type that implements the operation using the full matrix */ 8396 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8397 switch (cll) { 8398 case MAT_INITIAL_MATRIX: 8399 PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat)); 8400 break; 8401 case MAT_REUSE_MATRIX: 8402 PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp)); 8403 break; 8404 default: 8405 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX"); 8406 } 8407 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8408 goto setproperties; 8409 } 8410 8411 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8412 PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat); 8413 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8414 8415 setproperties: 8416 PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg)); 8417 if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat)); 8418 if (!iscol) PetscCall(ISDestroy(&iscoltmp)); 8419 if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat)); 8420 PetscFunctionReturn(PETSC_SUCCESS); 8421 } 8422 8423 /*@ 8424 MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix 8425 8426 Not Collective 8427 8428 Input Parameters: 8429 + A - the matrix we wish to propagate options from 8430 - B - the matrix we wish to propagate options to 8431 8432 Level: beginner 8433 8434 Note: 8435 Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL` 8436 8437 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, MatIsStructurallySymmetricKnown()` 8438 @*/ 8439 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B) 8440 { 8441 PetscFunctionBegin; 8442 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8443 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 8444 B->symmetry_eternal = A->symmetry_eternal; 8445 B->structural_symmetry_eternal = A->structural_symmetry_eternal; 8446 B->symmetric = A->symmetric; 8447 B->structurally_symmetric = A->structurally_symmetric; 8448 B->spd = A->spd; 8449 B->hermitian = A->hermitian; 8450 PetscFunctionReturn(PETSC_SUCCESS); 8451 } 8452 8453 /*@ 8454 MatStashSetInitialSize - sets the sizes of the matrix stash, that is 8455 used during the assembly process to store values that belong to 8456 other processors. 8457 8458 Not Collective 8459 8460 Input Parameters: 8461 + mat - the matrix 8462 . size - the initial size of the stash. 8463 - bsize - the initial size of the block-stash(if used). 8464 8465 Options Database Keys: 8466 + -matstash_initial_size <size> or <size0,size1,...sizep-1> 8467 - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1> 8468 8469 Level: intermediate 8470 8471 Notes: 8472 The block-stash is used for values set with `MatSetValuesBlocked()` while 8473 the stash is used for values set with `MatSetValues()` 8474 8475 Run with the option -info and look for output of the form 8476 MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs. 8477 to determine the appropriate value, MM, to use for size and 8478 MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs. 8479 to determine the value, BMM to use for bsize 8480 8481 .seealso: [](chapter_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()` 8482 @*/ 8483 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize) 8484 { 8485 PetscFunctionBegin; 8486 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8487 PetscValidType(mat, 1); 8488 PetscCall(MatStashSetInitialSize_Private(&mat->stash, size)); 8489 PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize)); 8490 PetscFunctionReturn(PETSC_SUCCESS); 8491 } 8492 8493 /*@ 8494 MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of 8495 the matrix 8496 8497 Neighbor-wise Collective 8498 8499 Input Parameters: 8500 + mat - the matrix 8501 . x - the vector to be multiplied by the interpolation operator 8502 - y - the vector to be added to the result 8503 8504 Output Parameter: 8505 . w - the resulting vector 8506 8507 Level: intermediate 8508 8509 Notes: 8510 `w` may be the same vector as `y`. 8511 8512 This allows one to use either the restriction or interpolation (its transpose) 8513 matrix to do the interpolation 8514 8515 .seealso: [](chapter_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8516 @*/ 8517 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w) 8518 { 8519 PetscInt M, N, Ny; 8520 8521 PetscFunctionBegin; 8522 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8523 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8524 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8525 PetscValidHeaderSpecific(w, VEC_CLASSID, 4); 8526 PetscCall(MatGetSize(A, &M, &N)); 8527 PetscCall(VecGetSize(y, &Ny)); 8528 if (M == Ny) { 8529 PetscCall(MatMultAdd(A, x, y, w)); 8530 } else { 8531 PetscCall(MatMultTransposeAdd(A, x, y, w)); 8532 } 8533 PetscFunctionReturn(PETSC_SUCCESS); 8534 } 8535 8536 /*@ 8537 MatInterpolate - y = A*x or A'*x depending on the shape of 8538 the matrix 8539 8540 Neighbor-wise Collective 8541 8542 Input Parameters: 8543 + mat - the matrix 8544 - x - the vector to be interpolated 8545 8546 Output Parameter: 8547 . y - the resulting vector 8548 8549 Level: intermediate 8550 8551 Note: 8552 This allows one to use either the restriction or interpolation (its transpose) 8553 matrix to do the interpolation 8554 8555 .seealso: [](chapter_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8556 @*/ 8557 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y) 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 PetscCall(MatGetSize(A, &M, &N)); 8566 PetscCall(VecGetSize(y, &Ny)); 8567 if (M == Ny) { 8568 PetscCall(MatMult(A, x, y)); 8569 } else { 8570 PetscCall(MatMultTranspose(A, x, y)); 8571 } 8572 PetscFunctionReturn(PETSC_SUCCESS); 8573 } 8574 8575 /*@ 8576 MatRestrict - y = A*x or A'*x 8577 8578 Neighbor-wise Collective 8579 8580 Input Parameters: 8581 + mat - the matrix 8582 - x - the vector to be restricted 8583 8584 Output Parameter: 8585 . y - the resulting vector 8586 8587 Level: intermediate 8588 8589 Note: 8590 This allows one to use either the restriction or interpolation (its transpose) 8591 matrix to do the restriction 8592 8593 .seealso: [](chapter_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG` 8594 @*/ 8595 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y) 8596 { 8597 PetscInt M, N, Ny; 8598 8599 PetscFunctionBegin; 8600 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8601 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8602 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8603 PetscCall(MatGetSize(A, &M, &N)); 8604 PetscCall(VecGetSize(y, &Ny)); 8605 if (M == Ny) { 8606 PetscCall(MatMult(A, x, y)); 8607 } else { 8608 PetscCall(MatMultTranspose(A, x, y)); 8609 } 8610 PetscFunctionReturn(PETSC_SUCCESS); 8611 } 8612 8613 /*@ 8614 MatMatInterpolateAdd - Y = W + A*X or W + A'*X 8615 8616 Neighbor-wise Collective 8617 8618 Input Parameters: 8619 + mat - the matrix 8620 . x - the input dense matrix to be multiplied 8621 - w - the input dense matrix to be added to the result 8622 8623 Output Parameter: 8624 . y - the output dense matrix 8625 8626 Level: intermediate 8627 8628 Note: 8629 This allows one to use either the restriction or interpolation (its transpose) 8630 matrix to do the interpolation. y matrix can be reused if already created with the proper sizes, 8631 otherwise it will be recreated. y must be initialized to `NULL` if not supplied. 8632 8633 .seealso: [](chapter_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG` 8634 @*/ 8635 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y) 8636 { 8637 PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0; 8638 PetscBool trans = PETSC_TRUE; 8639 MatReuse reuse = MAT_INITIAL_MATRIX; 8640 8641 PetscFunctionBegin; 8642 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8643 PetscValidHeaderSpecific(x, MAT_CLASSID, 2); 8644 PetscValidType(x, 2); 8645 if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3); 8646 if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4); 8647 PetscCall(MatGetSize(A, &M, &N)); 8648 PetscCall(MatGetSize(x, &Mx, &Nx)); 8649 if (N == Mx) trans = PETSC_FALSE; 8650 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); 8651 Mo = trans ? N : M; 8652 if (*y) { 8653 PetscCall(MatGetSize(*y, &My, &Ny)); 8654 if (Mo == My && Nx == Ny) { 8655 reuse = MAT_REUSE_MATRIX; 8656 } else { 8657 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); 8658 PetscCall(MatDestroy(y)); 8659 } 8660 } 8661 8662 if (w && *y == w) { /* this is to minimize changes in PCMG */ 8663 PetscBool flg; 8664 8665 PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w)); 8666 if (w) { 8667 PetscInt My, Ny, Mw, Nw; 8668 8669 PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg)); 8670 PetscCall(MatGetSize(*y, &My, &Ny)); 8671 PetscCall(MatGetSize(w, &Mw, &Nw)); 8672 if (!flg || My != Mw || Ny != Nw) w = NULL; 8673 } 8674 if (!w) { 8675 PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w)); 8676 PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w)); 8677 PetscCall(PetscObjectDereference((PetscObject)w)); 8678 } else { 8679 PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN)); 8680 } 8681 } 8682 if (!trans) { 8683 PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8684 } else { 8685 PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8686 } 8687 if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN)); 8688 PetscFunctionReturn(PETSC_SUCCESS); 8689 } 8690 8691 /*@ 8692 MatMatInterpolate - Y = A*X or A'*X 8693 8694 Neighbor-wise Collective 8695 8696 Input Parameters: 8697 + mat - the matrix 8698 - x - the input dense matrix 8699 8700 Output Parameter: 8701 . y - the output dense matrix 8702 8703 Level: intermediate 8704 8705 Note: 8706 This allows one to use either the restriction or interpolation (its transpose) 8707 matrix to do the interpolation. y matrix can be reused if already created with the proper sizes, 8708 otherwise it will be recreated. y must be initialized to `NULL` if not supplied. 8709 8710 .seealso: [](chapter_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG` 8711 @*/ 8712 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y) 8713 { 8714 PetscFunctionBegin; 8715 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8716 PetscFunctionReturn(PETSC_SUCCESS); 8717 } 8718 8719 /*@ 8720 MatMatRestrict - Y = A*X or A'*X 8721 8722 Neighbor-wise Collective 8723 8724 Input Parameters: 8725 + mat - the matrix 8726 - x - the input dense matrix 8727 8728 Output Parameter: 8729 . y - the output dense matrix 8730 8731 Level: intermediate 8732 8733 Note: 8734 This allows one to use either the restriction or interpolation (its transpose) 8735 matrix to do the restriction. y matrix can be reused if already created with the proper sizes, 8736 otherwise it will be recreated. y must be initialized to `NULL` if not supplied. 8737 8738 .seealso: [](chapter_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG` 8739 @*/ 8740 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y) 8741 { 8742 PetscFunctionBegin; 8743 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8744 PetscFunctionReturn(PETSC_SUCCESS); 8745 } 8746 8747 /*@ 8748 MatGetNullSpace - retrieves the null space of a matrix. 8749 8750 Logically Collective 8751 8752 Input Parameters: 8753 + mat - the matrix 8754 - nullsp - the null space object 8755 8756 Level: developer 8757 8758 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace` 8759 @*/ 8760 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp) 8761 { 8762 PetscFunctionBegin; 8763 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8764 PetscValidPointer(nullsp, 2); 8765 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp; 8766 PetscFunctionReturn(PETSC_SUCCESS); 8767 } 8768 8769 /*@ 8770 MatSetNullSpace - attaches a null space to a matrix. 8771 8772 Logically Collective 8773 8774 Input Parameters: 8775 + mat - the matrix 8776 - nullsp - the null space object 8777 8778 Level: advanced 8779 8780 Notes: 8781 This null space is used by the `KSP` linear solvers to solve singular systems. 8782 8783 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` 8784 8785 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 8786 to zero but the linear system will still be solved in a least squares sense. 8787 8788 The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that 8789 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). 8790 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 8791 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 8792 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). 8793 This \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix. 8794 8795 If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called 8796 `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this 8797 routine also automatically calls `MatSetTransposeNullSpace()`. 8798 8799 The user should call `MatNullSpaceDestroy()`. 8800 8801 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, 8802 `KSPSetPCSide()` 8803 @*/ 8804 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp) 8805 { 8806 PetscFunctionBegin; 8807 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8808 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8809 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8810 PetscCall(MatNullSpaceDestroy(&mat->nullsp)); 8811 mat->nullsp = nullsp; 8812 if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp)); 8813 PetscFunctionReturn(PETSC_SUCCESS); 8814 } 8815 8816 /*@ 8817 MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix. 8818 8819 Logically Collective 8820 8821 Input Parameters: 8822 + mat - the matrix 8823 - nullsp - the null space object 8824 8825 Level: developer 8826 8827 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()` 8828 @*/ 8829 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp) 8830 { 8831 PetscFunctionBegin; 8832 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8833 PetscValidType(mat, 1); 8834 PetscValidPointer(nullsp, 2); 8835 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp; 8836 PetscFunctionReturn(PETSC_SUCCESS); 8837 } 8838 8839 /*@ 8840 MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix 8841 8842 Logically Collective 8843 8844 Input Parameters: 8845 + mat - the matrix 8846 - nullsp - the null space object 8847 8848 Level: advanced 8849 8850 Notes: 8851 This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning. 8852 8853 See `MatSetNullSpace()` 8854 8855 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()` 8856 @*/ 8857 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp) 8858 { 8859 PetscFunctionBegin; 8860 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8861 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8862 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8863 PetscCall(MatNullSpaceDestroy(&mat->transnullsp)); 8864 mat->transnullsp = nullsp; 8865 PetscFunctionReturn(PETSC_SUCCESS); 8866 } 8867 8868 /*@ 8869 MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions 8870 This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix. 8871 8872 Logically Collective 8873 8874 Input Parameters: 8875 + mat - the matrix 8876 - nullsp - the null space object 8877 8878 Level: advanced 8879 8880 Notes: 8881 Overwrites any previous near null space that may have been attached 8882 8883 You can remove the null space by calling this routine with an nullsp of `NULL` 8884 8885 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()` 8886 @*/ 8887 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp) 8888 { 8889 PetscFunctionBegin; 8890 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8891 PetscValidType(mat, 1); 8892 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8893 MatCheckPreallocated(mat, 1); 8894 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8895 PetscCall(MatNullSpaceDestroy(&mat->nearnullsp)); 8896 mat->nearnullsp = nullsp; 8897 PetscFunctionReturn(PETSC_SUCCESS); 8898 } 8899 8900 /*@ 8901 MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()` 8902 8903 Not Collective 8904 8905 Input Parameter: 8906 . mat - the matrix 8907 8908 Output Parameter: 8909 . nullsp - the null space object, `NULL` if not set 8910 8911 Level: advanced 8912 8913 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()` 8914 @*/ 8915 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp) 8916 { 8917 PetscFunctionBegin; 8918 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8919 PetscValidType(mat, 1); 8920 PetscValidPointer(nullsp, 2); 8921 MatCheckPreallocated(mat, 1); 8922 *nullsp = mat->nearnullsp; 8923 PetscFunctionReturn(PETSC_SUCCESS); 8924 } 8925 8926 /*@C 8927 MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix. 8928 8929 Collective 8930 8931 Input Parameters: 8932 + mat - the matrix 8933 . row - row/column permutation 8934 - info - information on desired factorization process 8935 8936 Level: developer 8937 8938 Notes: 8939 Probably really in-place only when level of fill is zero, otherwise allocates 8940 new space to store factored matrix and deletes previous memory. 8941 8942 Most users should employ the `KSP` interface for linear solvers 8943 instead of working directly with matrix algebra routines such as this. 8944 See, e.g., `KSPCreate()`. 8945 8946 Developer Note: 8947 The Fortran interface is not autogenerated as the 8948 interface definition cannot be generated correctly [due to `MatFactorInfo`] 8949 8950 .seealso: [](chapter_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 8951 @*/ 8952 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info) 8953 { 8954 PetscFunctionBegin; 8955 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8956 PetscValidType(mat, 1); 8957 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 8958 PetscValidPointer(info, 3); 8959 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 8960 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 8961 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8962 MatCheckPreallocated(mat, 1); 8963 PetscUseTypeMethod(mat, iccfactor, row, info); 8964 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 8965 PetscFunctionReturn(PETSC_SUCCESS); 8966 } 8967 8968 /*@ 8969 MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the 8970 ghosted ones. 8971 8972 Not Collective 8973 8974 Input Parameters: 8975 + mat - the matrix 8976 - diag - the diagonal values, including ghost ones 8977 8978 Level: developer 8979 8980 Notes: 8981 Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices 8982 8983 This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()` 8984 8985 .seealso: [](chapter_matrices), `Mat`, `MatDiagonalScale()` 8986 @*/ 8987 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag) 8988 { 8989 PetscMPIInt size; 8990 8991 PetscFunctionBegin; 8992 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8993 PetscValidHeaderSpecific(diag, VEC_CLASSID, 2); 8994 PetscValidType(mat, 1); 8995 8996 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled"); 8997 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 8998 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8999 if (size == 1) { 9000 PetscInt n, m; 9001 PetscCall(VecGetSize(diag, &n)); 9002 PetscCall(MatGetSize(mat, NULL, &m)); 9003 PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions"); 9004 PetscCall(MatDiagonalScale(mat, NULL, diag)); 9005 } else { 9006 PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag)); 9007 } 9008 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 9009 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9010 PetscFunctionReturn(PETSC_SUCCESS); 9011 } 9012 9013 /*@ 9014 MatGetInertia - Gets the inertia from a factored matrix 9015 9016 Collective 9017 9018 Input Parameter: 9019 . mat - the matrix 9020 9021 Output Parameters: 9022 + nneg - number of negative eigenvalues 9023 . nzero - number of zero eigenvalues 9024 - npos - number of positive eigenvalues 9025 9026 Level: advanced 9027 9028 Note: 9029 Matrix must have been factored by `MatCholeskyFactor()` 9030 9031 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()` 9032 @*/ 9033 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos) 9034 { 9035 PetscFunctionBegin; 9036 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9037 PetscValidType(mat, 1); 9038 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9039 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled"); 9040 PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos); 9041 PetscFunctionReturn(PETSC_SUCCESS); 9042 } 9043 9044 /*@C 9045 MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors 9046 9047 Neighbor-wise Collective 9048 9049 Input Parameters: 9050 + mat - the factored matrix obtained with `MatGetFactor()` 9051 - b - the right-hand-side vectors 9052 9053 Output Parameter: 9054 . x - the result vectors 9055 9056 Level: developer 9057 9058 Note: 9059 The vectors `b` and `x` cannot be the same. I.e., one cannot 9060 call `MatSolves`(A,x,x). 9061 9062 .seealso: [](chapter_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()` 9063 @*/ 9064 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x) 9065 { 9066 PetscFunctionBegin; 9067 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9068 PetscValidType(mat, 1); 9069 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 9070 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9071 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 9072 9073 MatCheckPreallocated(mat, 1); 9074 PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0)); 9075 PetscUseTypeMethod(mat, solves, b, x); 9076 PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0)); 9077 PetscFunctionReturn(PETSC_SUCCESS); 9078 } 9079 9080 /*@ 9081 MatIsSymmetric - Test whether a matrix is symmetric 9082 9083 Collective 9084 9085 Input Parameters: 9086 + A - the matrix to test 9087 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose) 9088 9089 Output Parameter: 9090 . flg - the result 9091 9092 Level: intermediate 9093 9094 Notes: 9095 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9096 9097 If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()` 9098 9099 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9100 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9101 9102 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`, 9103 `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()` 9104 @*/ 9105 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg) 9106 { 9107 PetscFunctionBegin; 9108 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9109 PetscValidBoolPointer(flg, 3); 9110 9111 if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE; 9112 else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE; 9113 else { 9114 PetscUseTypeMethod(A, issymmetric, tol, flg); 9115 if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg)); 9116 } 9117 PetscFunctionReturn(PETSC_SUCCESS); 9118 } 9119 9120 /*@ 9121 MatIsHermitian - Test whether a matrix is Hermitian 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 Hermitian) 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 Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()` 9138 9139 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9140 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`) 9141 9142 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, 9143 `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()` 9144 @*/ 9145 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg) 9146 { 9147 PetscFunctionBegin; 9148 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9149 PetscValidBoolPointer(flg, 3); 9150 9151 if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE; 9152 else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE; 9153 else { 9154 PetscUseTypeMethod(A, ishermitian, tol, flg); 9155 if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg)); 9156 } 9157 PetscFunctionReturn(PETSC_SUCCESS); 9158 } 9159 9160 /*@ 9161 MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state 9162 9163 Not Collective 9164 9165 Input Parameter: 9166 . A - the matrix to check 9167 9168 Output Parameters: 9169 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid) 9170 - flg - the result (only valid if set is `PETSC_TRUE`) 9171 9172 Level: advanced 9173 9174 Notes: 9175 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()` 9176 if you want it explicitly checked 9177 9178 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9179 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9180 9181 .seealso: [](chapter_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9182 @*/ 9183 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9184 { 9185 PetscFunctionBegin; 9186 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9187 PetscValidBoolPointer(set, 2); 9188 PetscValidBoolPointer(flg, 3); 9189 if (A->symmetric != PETSC_BOOL3_UNKNOWN) { 9190 *set = PETSC_TRUE; 9191 *flg = PetscBool3ToBool(A->symmetric); 9192 } else { 9193 *set = PETSC_FALSE; 9194 } 9195 PetscFunctionReturn(PETSC_SUCCESS); 9196 } 9197 9198 /*@ 9199 MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state 9200 9201 Not Collective 9202 9203 Input Parameter: 9204 . A - the matrix to check 9205 9206 Output Parameters: 9207 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid) 9208 - flg - the result (only valid if set is `PETSC_TRUE`) 9209 9210 Level: advanced 9211 9212 Notes: 9213 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). 9214 9215 One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD 9216 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`) 9217 9218 .seealso: [](chapter_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9219 @*/ 9220 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg) 9221 { 9222 PetscFunctionBegin; 9223 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9224 PetscValidBoolPointer(set, 2); 9225 PetscValidBoolPointer(flg, 3); 9226 if (A->spd != PETSC_BOOL3_UNKNOWN) { 9227 *set = PETSC_TRUE; 9228 *flg = PetscBool3ToBool(A->spd); 9229 } else { 9230 *set = PETSC_FALSE; 9231 } 9232 PetscFunctionReturn(PETSC_SUCCESS); 9233 } 9234 9235 /*@ 9236 MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state 9237 9238 Not Collective 9239 9240 Input Parameter: 9241 . A - the matrix to check 9242 9243 Output Parameters: 9244 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid) 9245 - flg - the result (only valid if set is `PETSC_TRUE`) 9246 9247 Level: advanced 9248 9249 Notes: 9250 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()` 9251 if you want it explicitly checked 9252 9253 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9254 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9255 9256 .seealso: [](chapter_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()` 9257 @*/ 9258 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg) 9259 { 9260 PetscFunctionBegin; 9261 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9262 PetscValidBoolPointer(set, 2); 9263 PetscValidBoolPointer(flg, 3); 9264 if (A->hermitian != PETSC_BOOL3_UNKNOWN) { 9265 *set = PETSC_TRUE; 9266 *flg = PetscBool3ToBool(A->hermitian); 9267 } else { 9268 *set = PETSC_FALSE; 9269 } 9270 PetscFunctionReturn(PETSC_SUCCESS); 9271 } 9272 9273 /*@ 9274 MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric 9275 9276 Collective 9277 9278 Input Parameter: 9279 . A - the matrix to test 9280 9281 Output Parameter: 9282 . flg - the result 9283 9284 Level: intermediate 9285 9286 Notes: 9287 If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()` 9288 9289 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 9290 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9291 9292 .seealso: [](chapter_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()` 9293 @*/ 9294 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg) 9295 { 9296 PetscFunctionBegin; 9297 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9298 PetscValidBoolPointer(flg, 2); 9299 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9300 *flg = PetscBool3ToBool(A->structurally_symmetric); 9301 } else { 9302 PetscUseTypeMethod(A, isstructurallysymmetric, flg); 9303 PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg)); 9304 } 9305 PetscFunctionReturn(PETSC_SUCCESS); 9306 } 9307 9308 /*@ 9309 MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state 9310 9311 Not Collective 9312 9313 Input Parameter: 9314 . A - the matrix to check 9315 9316 Output Parameters: 9317 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid) 9318 - flg - the result (only valid if set is PETSC_TRUE) 9319 9320 Level: advanced 9321 9322 Notes: 9323 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 9324 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9325 9326 Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation) 9327 9328 .seealso: [](chapter_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9329 @*/ 9330 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9331 { 9332 PetscFunctionBegin; 9333 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9334 PetscValidBoolPointer(set, 2); 9335 PetscValidBoolPointer(flg, 3); 9336 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9337 *set = PETSC_TRUE; 9338 *flg = PetscBool3ToBool(A->structurally_symmetric); 9339 } else { 9340 *set = PETSC_FALSE; 9341 } 9342 PetscFunctionReturn(PETSC_SUCCESS); 9343 } 9344 9345 /*@ 9346 MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need 9347 to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process 9348 9349 Not Collective 9350 9351 Input Parameter: 9352 . mat - the matrix 9353 9354 Output Parameters: 9355 + nstash - the size of the stash 9356 . reallocs - the number of additional mallocs incurred. 9357 . bnstash - the size of the block stash 9358 - breallocs - the number of additional mallocs incurred.in the block stash 9359 9360 Level: advanced 9361 9362 .seealso: [](chapter_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()` 9363 @*/ 9364 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs) 9365 { 9366 PetscFunctionBegin; 9367 PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs)); 9368 PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs)); 9369 PetscFunctionReturn(PETSC_SUCCESS); 9370 } 9371 9372 /*@C 9373 MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same 9374 parallel layout, `PetscLayout` for rows and columns 9375 9376 Collective 9377 9378 Input Parameter: 9379 . mat - the matrix 9380 9381 Output Parameters: 9382 + right - (optional) vector that the matrix can be multiplied against 9383 - left - (optional) vector that the matrix vector product can be stored in 9384 9385 Level: advanced 9386 9387 Notes: 9388 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()`. 9389 9390 These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed 9391 9392 .seealso: [](chapter_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()` 9393 @*/ 9394 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left) 9395 { 9396 PetscFunctionBegin; 9397 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9398 PetscValidType(mat, 1); 9399 if (mat->ops->getvecs) { 9400 PetscUseTypeMethod(mat, getvecs, right, left); 9401 } else { 9402 PetscInt rbs, cbs; 9403 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 9404 if (right) { 9405 PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup"); 9406 PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), right)); 9407 PetscCall(VecSetSizes(*right, mat->cmap->n, PETSC_DETERMINE)); 9408 PetscCall(VecSetBlockSize(*right, cbs)); 9409 PetscCall(VecSetType(*right, mat->defaultvectype)); 9410 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9411 if (mat->boundtocpu && mat->bindingpropagates) { 9412 PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE)); 9413 PetscCall(VecBindToCPU(*right, PETSC_TRUE)); 9414 } 9415 #endif 9416 PetscCall(PetscLayoutReference(mat->cmap, &(*right)->map)); 9417 } 9418 if (left) { 9419 PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup"); 9420 PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), left)); 9421 PetscCall(VecSetSizes(*left, mat->rmap->n, PETSC_DETERMINE)); 9422 PetscCall(VecSetBlockSize(*left, rbs)); 9423 PetscCall(VecSetType(*left, mat->defaultvectype)); 9424 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9425 if (mat->boundtocpu && mat->bindingpropagates) { 9426 PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE)); 9427 PetscCall(VecBindToCPU(*left, PETSC_TRUE)); 9428 } 9429 #endif 9430 PetscCall(PetscLayoutReference(mat->rmap, &(*left)->map)); 9431 } 9432 } 9433 PetscFunctionReturn(PETSC_SUCCESS); 9434 } 9435 9436 /*@C 9437 MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure 9438 with default values. 9439 9440 Not Collective 9441 9442 Input Parameter: 9443 . info - the `MatFactorInfo` data structure 9444 9445 Level: developer 9446 9447 Notes: 9448 The solvers are generally used through the `KSP` and `PC` objects, for example 9449 `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC` 9450 9451 Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed 9452 9453 Developer Note: 9454 The Fortran interface is not autogenerated as the 9455 interface definition cannot be generated correctly [due to `MatFactorInfo`] 9456 9457 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo` 9458 @*/ 9459 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info) 9460 { 9461 PetscFunctionBegin; 9462 PetscCall(PetscMemzero(info, sizeof(MatFactorInfo))); 9463 PetscFunctionReturn(PETSC_SUCCESS); 9464 } 9465 9466 /*@ 9467 MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed 9468 9469 Collective 9470 9471 Input Parameters: 9472 + mat - the factored matrix 9473 - is - the index set defining the Schur indices (0-based) 9474 9475 Level: advanced 9476 9477 Notes: 9478 Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system. 9479 9480 You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call. 9481 9482 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9483 9484 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`, 9485 `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9486 @*/ 9487 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is) 9488 { 9489 PetscErrorCode (*f)(Mat, IS); 9490 9491 PetscFunctionBegin; 9492 PetscValidType(mat, 1); 9493 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9494 PetscValidType(is, 2); 9495 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 9496 PetscCheckSameComm(mat, 1, is, 2); 9497 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 9498 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f)); 9499 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO"); 9500 PetscCall(MatDestroy(&mat->schur)); 9501 PetscCall((*f)(mat, is)); 9502 PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created"); 9503 PetscFunctionReturn(PETSC_SUCCESS); 9504 } 9505 9506 /*@ 9507 MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step 9508 9509 Logically Collective 9510 9511 Input Parameters: 9512 + F - the factored matrix obtained by calling `MatGetFactor()` 9513 . S - location where to return the Schur complement, can be `NULL` 9514 - status - the status of the Schur complement matrix, can be `NULL` 9515 9516 Level: advanced 9517 9518 Notes: 9519 You must call `MatFactorSetSchurIS()` before calling this routine. 9520 9521 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9522 9523 The routine provides a copy of the Schur matrix stored within the solver data structures. 9524 The caller must destroy the object when it is no longer needed. 9525 If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse. 9526 9527 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) 9528 9529 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9530 9531 Developer Note: 9532 The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc 9533 matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix. 9534 9535 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9536 @*/ 9537 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9538 { 9539 PetscFunctionBegin; 9540 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9541 if (S) PetscValidPointer(S, 2); 9542 if (status) PetscValidPointer(status, 3); 9543 if (S) { 9544 PetscErrorCode (*f)(Mat, Mat *); 9545 9546 PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f)); 9547 if (f) { 9548 PetscCall((*f)(F, S)); 9549 } else { 9550 PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S)); 9551 } 9552 } 9553 if (status) *status = F->schur_status; 9554 PetscFunctionReturn(PETSC_SUCCESS); 9555 } 9556 9557 /*@ 9558 MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix 9559 9560 Logically Collective 9561 9562 Input Parameters: 9563 + F - the factored matrix obtained by calling `MatGetFactor()` 9564 . *S - location where to return the Schur complement, can be `NULL` 9565 - status - the status of the Schur complement matrix, can be `NULL` 9566 9567 Level: advanced 9568 9569 Notes: 9570 You must call `MatFactorSetSchurIS()` before calling this routine. 9571 9572 Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS` 9573 9574 The routine returns a the Schur Complement stored within the data structures of the solver. 9575 9576 If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement. 9577 9578 The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed. 9579 9580 Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix 9581 9582 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9583 9584 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9585 @*/ 9586 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9587 { 9588 PetscFunctionBegin; 9589 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9590 if (S) PetscValidPointer(S, 2); 9591 if (status) PetscValidPointer(status, 3); 9592 if (S) *S = F->schur; 9593 if (status) *status = F->schur_status; 9594 PetscFunctionReturn(PETSC_SUCCESS); 9595 } 9596 9597 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F) 9598 { 9599 Mat S = F->schur; 9600 9601 PetscFunctionBegin; 9602 switch (F->schur_status) { 9603 case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through 9604 case MAT_FACTOR_SCHUR_INVERTED: 9605 if (S) { 9606 S->ops->solve = NULL; 9607 S->ops->matsolve = NULL; 9608 S->ops->solvetranspose = NULL; 9609 S->ops->matsolvetranspose = NULL; 9610 S->ops->solveadd = NULL; 9611 S->ops->solvetransposeadd = NULL; 9612 S->factortype = MAT_FACTOR_NONE; 9613 PetscCall(PetscFree(S->solvertype)); 9614 } 9615 case MAT_FACTOR_SCHUR_FACTORED: // fall-through 9616 break; 9617 default: 9618 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9619 } 9620 PetscFunctionReturn(PETSC_SUCCESS); 9621 } 9622 9623 /*@ 9624 MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()` 9625 9626 Logically Collective 9627 9628 Input Parameters: 9629 + F - the factored matrix obtained by calling `MatGetFactor()` 9630 . *S - location where the Schur complement is stored 9631 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`) 9632 9633 Level: advanced 9634 9635 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9636 @*/ 9637 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status) 9638 { 9639 PetscFunctionBegin; 9640 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9641 if (S) { 9642 PetscValidHeaderSpecific(*S, MAT_CLASSID, 2); 9643 *S = NULL; 9644 } 9645 F->schur_status = status; 9646 PetscCall(MatFactorUpdateSchurStatus_Private(F)); 9647 PetscFunctionReturn(PETSC_SUCCESS); 9648 } 9649 9650 /*@ 9651 MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step 9652 9653 Logically Collective 9654 9655 Input Parameters: 9656 + F - the factored matrix obtained by calling `MatGetFactor()` 9657 . rhs - location where the right hand side of the Schur complement system is stored 9658 - sol - location where the solution of the Schur complement system has to be returned 9659 9660 Level: advanced 9661 9662 Notes: 9663 The sizes of the vectors should match the size of the Schur complement 9664 9665 Must be called after `MatFactorSetSchurIS()` 9666 9667 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()` 9668 @*/ 9669 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol) 9670 { 9671 PetscFunctionBegin; 9672 PetscValidType(F, 1); 9673 PetscValidType(rhs, 2); 9674 PetscValidType(sol, 3); 9675 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9676 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9677 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9678 PetscCheckSameComm(F, 1, rhs, 2); 9679 PetscCheckSameComm(F, 1, sol, 3); 9680 PetscCall(MatFactorFactorizeSchurComplement(F)); 9681 switch (F->schur_status) { 9682 case MAT_FACTOR_SCHUR_FACTORED: 9683 PetscCall(MatSolveTranspose(F->schur, rhs, sol)); 9684 break; 9685 case MAT_FACTOR_SCHUR_INVERTED: 9686 PetscCall(MatMultTranspose(F->schur, rhs, sol)); 9687 break; 9688 default: 9689 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9690 } 9691 PetscFunctionReturn(PETSC_SUCCESS); 9692 } 9693 9694 /*@ 9695 MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step 9696 9697 Logically Collective 9698 9699 Input Parameters: 9700 + F - the factored matrix obtained by calling `MatGetFactor()` 9701 . rhs - location where the right hand side of the Schur complement system is stored 9702 - sol - location where the solution of the Schur complement system has to be returned 9703 9704 Level: advanced 9705 9706 Notes: 9707 The sizes of the vectors should match the size of the Schur complement 9708 9709 Must be called after `MatFactorSetSchurIS()` 9710 9711 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()` 9712 @*/ 9713 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol) 9714 { 9715 PetscFunctionBegin; 9716 PetscValidType(F, 1); 9717 PetscValidType(rhs, 2); 9718 PetscValidType(sol, 3); 9719 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9720 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9721 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9722 PetscCheckSameComm(F, 1, rhs, 2); 9723 PetscCheckSameComm(F, 1, sol, 3); 9724 PetscCall(MatFactorFactorizeSchurComplement(F)); 9725 switch (F->schur_status) { 9726 case MAT_FACTOR_SCHUR_FACTORED: 9727 PetscCall(MatSolve(F->schur, rhs, sol)); 9728 break; 9729 case MAT_FACTOR_SCHUR_INVERTED: 9730 PetscCall(MatMult(F->schur, rhs, sol)); 9731 break; 9732 default: 9733 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9734 } 9735 PetscFunctionReturn(PETSC_SUCCESS); 9736 } 9737 9738 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat); 9739 #if PetscDefined(HAVE_CUDA) 9740 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat); 9741 #endif 9742 9743 /* Schur status updated in the interface */ 9744 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F) 9745 { 9746 Mat S = F->schur; 9747 9748 PetscFunctionBegin; 9749 if (S) { 9750 PetscMPIInt size; 9751 PetscBool isdense, isdensecuda; 9752 9753 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size)); 9754 PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented"); 9755 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense)); 9756 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda)); 9757 PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name); 9758 PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0)); 9759 if (isdense) { 9760 PetscCall(MatSeqDenseInvertFactors_Private(S)); 9761 } else if (isdensecuda) { 9762 #if defined(PETSC_HAVE_CUDA) 9763 PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S)); 9764 #endif 9765 } 9766 // HIP?????????????? 9767 PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0)); 9768 } 9769 PetscFunctionReturn(PETSC_SUCCESS); 9770 } 9771 9772 /*@ 9773 MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step 9774 9775 Logically Collective 9776 9777 Input Parameter: 9778 . F - the factored matrix obtained by calling `MatGetFactor()` 9779 9780 Level: advanced 9781 9782 Notes: 9783 Must be called after `MatFactorSetSchurIS()`. 9784 9785 Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it. 9786 9787 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()` 9788 @*/ 9789 PetscErrorCode MatFactorInvertSchurComplement(Mat F) 9790 { 9791 PetscFunctionBegin; 9792 PetscValidType(F, 1); 9793 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9794 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS); 9795 PetscCall(MatFactorFactorizeSchurComplement(F)); 9796 PetscCall(MatFactorInvertSchurComplement_Private(F)); 9797 F->schur_status = MAT_FACTOR_SCHUR_INVERTED; 9798 PetscFunctionReturn(PETSC_SUCCESS); 9799 } 9800 9801 /*@ 9802 MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step 9803 9804 Logically Collective 9805 9806 Input Parameter: 9807 . F - the factored matrix obtained by calling `MatGetFactor()` 9808 9809 Level: advanced 9810 9811 Note: 9812 Must be called after `MatFactorSetSchurIS()` 9813 9814 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()` 9815 @*/ 9816 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F) 9817 { 9818 MatFactorInfo info; 9819 9820 PetscFunctionBegin; 9821 PetscValidType(F, 1); 9822 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9823 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS); 9824 PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0)); 9825 PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo))); 9826 if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */ 9827 PetscCall(MatCholeskyFactor(F->schur, NULL, &info)); 9828 } else { 9829 PetscCall(MatLUFactor(F->schur, NULL, NULL, &info)); 9830 } 9831 PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0)); 9832 F->schur_status = MAT_FACTOR_SCHUR_FACTORED; 9833 PetscFunctionReturn(PETSC_SUCCESS); 9834 } 9835 9836 /*@ 9837 MatPtAP - Creates the matrix product C = P^T * A * P 9838 9839 Neighbor-wise Collective 9840 9841 Input Parameters: 9842 + A - the matrix 9843 . P - the projection matrix 9844 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9845 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate 9846 if the result is a dense matrix this is irrelevant 9847 9848 Output Parameter: 9849 . C - the product matrix 9850 9851 Level: intermediate 9852 9853 Notes: 9854 C will be created and must be destroyed by the user with `MatDestroy()`. 9855 9856 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9857 9858 Developer Note: 9859 For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`. 9860 9861 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()` 9862 @*/ 9863 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C) 9864 { 9865 PetscFunctionBegin; 9866 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 9867 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9868 9869 if (scall == MAT_INITIAL_MATRIX) { 9870 PetscCall(MatProductCreate(A, P, NULL, C)); 9871 PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP)); 9872 PetscCall(MatProductSetAlgorithm(*C, "default")); 9873 PetscCall(MatProductSetFill(*C, fill)); 9874 9875 (*C)->product->api_user = PETSC_TRUE; 9876 PetscCall(MatProductSetFromOptions(*C)); 9877 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); 9878 PetscCall(MatProductSymbolic(*C)); 9879 } else { /* scall == MAT_REUSE_MATRIX */ 9880 PetscCall(MatProductReplaceMats(A, P, NULL, *C)); 9881 } 9882 9883 PetscCall(MatProductNumeric(*C)); 9884 (*C)->symmetric = A->symmetric; 9885 (*C)->spd = A->spd; 9886 PetscFunctionReturn(PETSC_SUCCESS); 9887 } 9888 9889 /*@ 9890 MatRARt - Creates the matrix product C = R * A * R^T 9891 9892 Neighbor-wise Collective 9893 9894 Input Parameters: 9895 + A - the matrix 9896 . R - the projection matrix 9897 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9898 - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate 9899 if the result is a dense matrix this is irrelevant 9900 9901 Output Parameter: 9902 . C - the product matrix 9903 9904 Level: intermediate 9905 9906 Notes: 9907 C will be created and must be destroyed by the user with `MatDestroy()`. 9908 9909 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9910 9911 This routine is currently only implemented for pairs of `MATAIJ` matrices and classes 9912 which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes, 9913 parallel MatRARt is implemented via explicit transpose of R, which could be very expensive. 9914 We recommend using MatPtAP(). 9915 9916 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()` 9917 @*/ 9918 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C) 9919 { 9920 PetscFunctionBegin; 9921 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 9922 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9923 9924 if (scall == MAT_INITIAL_MATRIX) { 9925 PetscCall(MatProductCreate(A, R, NULL, C)); 9926 PetscCall(MatProductSetType(*C, MATPRODUCT_RARt)); 9927 PetscCall(MatProductSetAlgorithm(*C, "default")); 9928 PetscCall(MatProductSetFill(*C, fill)); 9929 9930 (*C)->product->api_user = PETSC_TRUE; 9931 PetscCall(MatProductSetFromOptions(*C)); 9932 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); 9933 PetscCall(MatProductSymbolic(*C)); 9934 } else { /* scall == MAT_REUSE_MATRIX */ 9935 PetscCall(MatProductReplaceMats(A, R, NULL, *C)); 9936 } 9937 9938 PetscCall(MatProductNumeric(*C)); 9939 if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 9940 PetscFunctionReturn(PETSC_SUCCESS); 9941 } 9942 9943 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C) 9944 { 9945 PetscFunctionBegin; 9946 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9947 9948 if (scall == MAT_INITIAL_MATRIX) { 9949 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype])); 9950 PetscCall(MatProductCreate(A, B, NULL, C)); 9951 PetscCall(MatProductSetType(*C, ptype)); 9952 PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT)); 9953 PetscCall(MatProductSetFill(*C, fill)); 9954 9955 (*C)->product->api_user = PETSC_TRUE; 9956 PetscCall(MatProductSetFromOptions(*C)); 9957 PetscCall(MatProductSymbolic(*C)); 9958 } else { /* scall == MAT_REUSE_MATRIX */ 9959 Mat_Product *product = (*C)->product; 9960 PetscBool isdense; 9961 9962 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, "")); 9963 if (isdense && product && product->type != ptype) { 9964 PetscCall(MatProductClear(*C)); 9965 product = NULL; 9966 } 9967 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype])); 9968 if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */ 9969 PetscCheck(isdense, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first"); 9970 PetscCall(MatProductCreate_Private(A, B, NULL, *C)); 9971 product = (*C)->product; 9972 product->fill = fill; 9973 product->api_user = PETSC_TRUE; 9974 product->clear = PETSC_TRUE; 9975 9976 PetscCall(MatProductSetType(*C, ptype)); 9977 PetscCall(MatProductSetFromOptions(*C)); 9978 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); 9979 PetscCall(MatProductSymbolic(*C)); 9980 } else { /* user may change input matrices A or B when REUSE */ 9981 PetscCall(MatProductReplaceMats(A, B, NULL, *C)); 9982 } 9983 } 9984 PetscCall(MatProductNumeric(*C)); 9985 PetscFunctionReturn(PETSC_SUCCESS); 9986 } 9987 9988 /*@ 9989 MatMatMult - Performs matrix-matrix multiplication C=A*B. 9990 9991 Neighbor-wise Collective 9992 9993 Input Parameters: 9994 + A - the left matrix 9995 . B - the right matrix 9996 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9997 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate 9998 if the result is a dense matrix this is irrelevant 9999 10000 Output Parameter: 10001 . C - the product matrix 10002 10003 Notes: 10004 Unless scall is `MAT_REUSE_MATRIX` C will be created. 10005 10006 `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 10007 call to this function with `MAT_INITIAL_MATRIX`. 10008 10009 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed. 10010 10011 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`, 10012 rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse. 10013 10014 Example of Usage: 10015 .vb 10016 MatProductCreate(A,B,NULL,&C); 10017 MatProductSetType(C,MATPRODUCT_AB); 10018 MatProductSymbolic(C); 10019 MatProductNumeric(C); // compute C=A * B 10020 MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1 10021 MatProductNumeric(C); 10022 MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1 10023 MatProductNumeric(C); 10024 .ve 10025 10026 Level: intermediate 10027 10028 .seealso: [](chapter_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()` 10029 @*/ 10030 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10031 { 10032 PetscFunctionBegin; 10033 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C)); 10034 PetscFunctionReturn(PETSC_SUCCESS); 10035 } 10036 10037 /*@ 10038 MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T. 10039 10040 Neighbor-wise Collective 10041 10042 Input Parameters: 10043 + A - the left matrix 10044 . B - the right matrix 10045 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10046 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 10047 10048 Output Parameter: 10049 . C - the product matrix 10050 10051 Level: intermediate 10052 10053 Notes: 10054 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10055 10056 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call 10057 10058 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10059 actually needed. 10060 10061 This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class, 10062 and for pairs of `MATMPIDENSE` matrices. 10063 10064 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt` 10065 10066 Options Database Keys: 10067 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the 10068 first redundantly copies the transposed B matrix on each process and requiers O(log P) communication complexity; 10069 the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity. 10070 10071 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductCreate()`, `MatProductAlgorithm`, `MatProductType`, `MATPRODUCT_ABt` 10072 @*/ 10073 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10074 { 10075 PetscFunctionBegin; 10076 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C)); 10077 if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10078 PetscFunctionReturn(PETSC_SUCCESS); 10079 } 10080 10081 /*@ 10082 MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B. 10083 10084 Neighbor-wise Collective 10085 10086 Input Parameters: 10087 + A - the left matrix 10088 . B - the right matrix 10089 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10090 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 10091 10092 Output Parameter: 10093 . C - the product matrix 10094 10095 Level: intermediate 10096 10097 Notes: 10098 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10099 10100 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call. 10101 10102 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB` 10103 10104 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10105 actually needed. 10106 10107 This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes 10108 which inherit from `MATSEQAIJ`. C will be of the same type as the input matrices. 10109 10110 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()` 10111 @*/ 10112 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10113 { 10114 PetscFunctionBegin; 10115 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C)); 10116 PetscFunctionReturn(PETSC_SUCCESS); 10117 } 10118 10119 /*@ 10120 MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C. 10121 10122 Neighbor-wise Collective 10123 10124 Input Parameters: 10125 + A - the left matrix 10126 . B - the middle matrix 10127 . C - the right matrix 10128 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10129 - 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 10130 if the result is a dense matrix this is irrelevant 10131 10132 Output Parameter: 10133 . D - the product matrix 10134 10135 Level: intermediate 10136 10137 Notes: 10138 Unless scall is `MAT_REUSE_MATRIX` D will be created. 10139 10140 `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call 10141 10142 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC` 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 If you have many matrices with the same non-zero structure to multiply, you 10148 should use `MAT_REUSE_MATRIX` in all calls but the first 10149 10150 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()` 10151 @*/ 10152 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D) 10153 { 10154 PetscFunctionBegin; 10155 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6); 10156 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10157 10158 if (scall == MAT_INITIAL_MATRIX) { 10159 PetscCall(MatProductCreate(A, B, C, D)); 10160 PetscCall(MatProductSetType(*D, MATPRODUCT_ABC)); 10161 PetscCall(MatProductSetAlgorithm(*D, "default")); 10162 PetscCall(MatProductSetFill(*D, fill)); 10163 10164 (*D)->product->api_user = PETSC_TRUE; 10165 PetscCall(MatProductSetFromOptions(*D)); 10166 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, 10167 ((PetscObject)C)->type_name); 10168 PetscCall(MatProductSymbolic(*D)); 10169 } else { /* user may change input matrices when REUSE */ 10170 PetscCall(MatProductReplaceMats(A, B, C, *D)); 10171 } 10172 PetscCall(MatProductNumeric(*D)); 10173 PetscFunctionReturn(PETSC_SUCCESS); 10174 } 10175 10176 /*@ 10177 MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators. 10178 10179 Collective 10180 10181 Input Parameters: 10182 + mat - the matrix 10183 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices) 10184 . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used) 10185 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10186 10187 Output Parameter: 10188 . matredundant - redundant matrix 10189 10190 Level: advanced 10191 10192 Notes: 10193 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 10194 original matrix has not changed from that last call to MatCreateRedundantMatrix(). 10195 10196 This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before 10197 calling it. 10198 10199 `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be. 10200 10201 .seealso: [](chapter_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubComm` 10202 @*/ 10203 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant) 10204 { 10205 MPI_Comm comm; 10206 PetscMPIInt size; 10207 PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs; 10208 Mat_Redundant *redund = NULL; 10209 PetscSubcomm psubcomm = NULL; 10210 MPI_Comm subcomm_in = subcomm; 10211 Mat *matseq; 10212 IS isrow, iscol; 10213 PetscBool newsubcomm = PETSC_FALSE; 10214 10215 PetscFunctionBegin; 10216 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10217 if (nsubcomm && reuse == MAT_REUSE_MATRIX) { 10218 PetscValidPointer(*matredundant, 5); 10219 PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5); 10220 } 10221 10222 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10223 if (size == 1 || nsubcomm == 1) { 10224 if (reuse == MAT_INITIAL_MATRIX) { 10225 PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant)); 10226 } else { 10227 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"); 10228 PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN)); 10229 } 10230 PetscFunctionReturn(PETSC_SUCCESS); 10231 } 10232 10233 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10234 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10235 MatCheckPreallocated(mat, 1); 10236 10237 PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0)); 10238 if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */ 10239 /* create psubcomm, then get subcomm */ 10240 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10241 PetscCallMPI(MPI_Comm_size(comm, &size)); 10242 PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size); 10243 10244 PetscCall(PetscSubcommCreate(comm, &psubcomm)); 10245 PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm)); 10246 PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS)); 10247 PetscCall(PetscSubcommSetFromOptions(psubcomm)); 10248 PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL)); 10249 newsubcomm = PETSC_TRUE; 10250 PetscCall(PetscSubcommDestroy(&psubcomm)); 10251 } 10252 10253 /* get isrow, iscol and a local sequential matrix matseq[0] */ 10254 if (reuse == MAT_INITIAL_MATRIX) { 10255 mloc_sub = PETSC_DECIDE; 10256 nloc_sub = PETSC_DECIDE; 10257 if (bs < 1) { 10258 PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M)); 10259 PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N)); 10260 } else { 10261 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M)); 10262 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N)); 10263 } 10264 PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm)); 10265 rstart = rend - mloc_sub; 10266 PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow)); 10267 PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol)); 10268 } else { /* reuse == MAT_REUSE_MATRIX */ 10269 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"); 10270 /* retrieve subcomm */ 10271 PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm)); 10272 redund = (*matredundant)->redundant; 10273 isrow = redund->isrow; 10274 iscol = redund->iscol; 10275 matseq = redund->matseq; 10276 } 10277 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq)); 10278 10279 /* get matredundant over subcomm */ 10280 if (reuse == MAT_INITIAL_MATRIX) { 10281 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant)); 10282 10283 /* create a supporting struct and attach it to C for reuse */ 10284 PetscCall(PetscNew(&redund)); 10285 (*matredundant)->redundant = redund; 10286 redund->isrow = isrow; 10287 redund->iscol = iscol; 10288 redund->matseq = matseq; 10289 if (newsubcomm) { 10290 redund->subcomm = subcomm; 10291 } else { 10292 redund->subcomm = MPI_COMM_NULL; 10293 } 10294 } else { 10295 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant)); 10296 } 10297 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 10298 if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) { 10299 PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE)); 10300 PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE)); 10301 } 10302 #endif 10303 PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0)); 10304 PetscFunctionReturn(PETSC_SUCCESS); 10305 } 10306 10307 /*@C 10308 MatGetMultiProcBlock - Create multiple 'parallel submatrices' from 10309 a given `Mat`. Each submatrix can span multiple procs. 10310 10311 Collective 10312 10313 Input Parameters: 10314 + mat - the matrix 10315 . subcomm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))` 10316 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10317 10318 Output Parameter: 10319 . subMat - parallel sub-matrices each spanning a given `subcomm` 10320 10321 Level: advanced 10322 10323 Notes: 10324 The submatrix partition across processors is dictated by `subComm` a 10325 communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm` 10326 is not restricted to be grouped with consecutive original ranks. 10327 10328 Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices 10329 map directly to the layout of the original matrix [wrt the local 10330 row,col partitioning]. So the original 'DiagonalMat' naturally maps 10331 into the 'DiagonalMat' of the `subMat`, hence it is used directly from 10332 the `subMat`. However the offDiagMat looses some columns - and this is 10333 reconstructed with `MatSetValues()` 10334 10335 This is used by `PCBJACOBI` when a single block spans multiple MPI processes. 10336 10337 .seealso: [](chapter_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI` 10338 @*/ 10339 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) 10340 { 10341 PetscMPIInt commsize, subCommSize; 10342 10343 PetscFunctionBegin; 10344 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize)); 10345 PetscCallMPI(MPI_Comm_size(subComm, &subCommSize)); 10346 PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize); 10347 10348 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"); 10349 PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10350 PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat); 10351 PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10352 PetscFunctionReturn(PETSC_SUCCESS); 10353 } 10354 10355 /*@ 10356 MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering 10357 10358 Not Collective 10359 10360 Input Parameters: 10361 + mat - matrix to extract local submatrix from 10362 . isrow - local row indices for submatrix 10363 - iscol - local column indices for submatrix 10364 10365 Output Parameter: 10366 . submat - the submatrix 10367 10368 Level: intermediate 10369 10370 Notes: 10371 `submat` should be disposed of with `MatRestoreLocalSubMatrix()`. 10372 10373 Depending on the format of `mat`, the returned submat may not implement `MatMult()`. Its communicator may be 10374 the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of `mat`'s. 10375 10376 `submat` always implements `MatSetValuesLocal()`. If `isrow` and `iscol` have the same block size, then 10377 `MatSetValuesBlockedLocal()` will also be implemented. 10378 10379 `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`. 10380 Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided. 10381 10382 .seealso: [](chapter_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()` 10383 @*/ 10384 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10385 { 10386 PetscFunctionBegin; 10387 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10388 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10389 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10390 PetscCheckSameComm(isrow, 2, iscol, 3); 10391 PetscValidPointer(submat, 4); 10392 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call"); 10393 10394 if (mat->ops->getlocalsubmatrix) { 10395 PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat); 10396 } else { 10397 PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat)); 10398 } 10399 PetscFunctionReturn(PETSC_SUCCESS); 10400 } 10401 10402 /*@ 10403 MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()` 10404 10405 Not Collective 10406 10407 Input Parameters: 10408 + mat - matrix to extract local submatrix from 10409 . isrow - local row indices for submatrix 10410 . iscol - local column indices for submatrix 10411 - submat - the submatrix 10412 10413 Level: intermediate 10414 10415 .seealso: [](chapter_matrices), `Mat`, `MatGetLocalSubMatrix()` 10416 @*/ 10417 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10418 { 10419 PetscFunctionBegin; 10420 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10421 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10422 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10423 PetscCheckSameComm(isrow, 2, iscol, 3); 10424 PetscValidPointer(submat, 4); 10425 if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4); 10426 10427 if (mat->ops->restorelocalsubmatrix) { 10428 PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat); 10429 } else { 10430 PetscCall(MatDestroy(submat)); 10431 } 10432 *submat = NULL; 10433 PetscFunctionReturn(PETSC_SUCCESS); 10434 } 10435 10436 /*@ 10437 MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix 10438 10439 Collective 10440 10441 Input Parameter: 10442 . mat - the matrix 10443 10444 Output Parameter: 10445 . is - if any rows have zero diagonals this contains the list of them 10446 10447 Level: developer 10448 10449 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10450 @*/ 10451 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is) 10452 { 10453 PetscFunctionBegin; 10454 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10455 PetscValidType(mat, 1); 10456 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10457 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10458 10459 if (!mat->ops->findzerodiagonals) { 10460 Vec diag; 10461 const PetscScalar *a; 10462 PetscInt *rows; 10463 PetscInt rStart, rEnd, r, nrow = 0; 10464 10465 PetscCall(MatCreateVecs(mat, &diag, NULL)); 10466 PetscCall(MatGetDiagonal(mat, diag)); 10467 PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd)); 10468 PetscCall(VecGetArrayRead(diag, &a)); 10469 for (r = 0; r < rEnd - rStart; ++r) 10470 if (a[r] == 0.0) ++nrow; 10471 PetscCall(PetscMalloc1(nrow, &rows)); 10472 nrow = 0; 10473 for (r = 0; r < rEnd - rStart; ++r) 10474 if (a[r] == 0.0) rows[nrow++] = r + rStart; 10475 PetscCall(VecRestoreArrayRead(diag, &a)); 10476 PetscCall(VecDestroy(&diag)); 10477 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is)); 10478 } else { 10479 PetscUseTypeMethod(mat, findzerodiagonals, is); 10480 } 10481 PetscFunctionReturn(PETSC_SUCCESS); 10482 } 10483 10484 /*@ 10485 MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size) 10486 10487 Collective 10488 10489 Input Parameter: 10490 . mat - the matrix 10491 10492 Output Parameter: 10493 . is - contains the list of rows with off block diagonal entries 10494 10495 Level: developer 10496 10497 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10498 @*/ 10499 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is) 10500 { 10501 PetscFunctionBegin; 10502 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10503 PetscValidType(mat, 1); 10504 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10505 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10506 10507 PetscUseTypeMethod(mat, findoffblockdiagonalentries, is); 10508 PetscFunctionReturn(PETSC_SUCCESS); 10509 } 10510 10511 /*@C 10512 MatInvertBlockDiagonal - Inverts the block diagonal entries. 10513 10514 Collective; No Fortran Support 10515 10516 Input Parameter: 10517 . mat - the matrix 10518 10519 Output Parameter: 10520 . values - the block inverses in column major order (FORTRAN-like) 10521 10522 Level: advanced 10523 10524 Notes: 10525 The size of the blocks is determined by the block size of the matrix. 10526 10527 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10528 10529 The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size 10530 10531 .seealso: [](chapter_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()` 10532 @*/ 10533 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values) 10534 { 10535 PetscFunctionBegin; 10536 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10537 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10538 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10539 PetscUseTypeMethod(mat, invertblockdiagonal, values); 10540 PetscFunctionReturn(PETSC_SUCCESS); 10541 } 10542 10543 /*@C 10544 MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries. 10545 10546 Collective; No Fortran Support 10547 10548 Input Parameters: 10549 + mat - the matrix 10550 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()` 10551 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()` 10552 10553 Output Parameter: 10554 . values - the block inverses in column major order (FORTRAN-like) 10555 10556 Level: advanced 10557 10558 Notes: 10559 Use `MatInvertBlockDiagonal()` if all blocks have the same size 10560 10561 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10562 10563 .seealso: [](chapter_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()` 10564 @*/ 10565 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values) 10566 { 10567 PetscFunctionBegin; 10568 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10569 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10570 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10571 PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values); 10572 PetscFunctionReturn(PETSC_SUCCESS); 10573 } 10574 10575 /*@ 10576 MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A 10577 10578 Collective 10579 10580 Input Parameters: 10581 + A - the matrix 10582 - C - matrix with inverted block diagonal of `A`. This matrix should be created and may have its type set. 10583 10584 Level: advanced 10585 10586 Note: 10587 The blocksize of the matrix is used to determine the blocks on the diagonal of `C` 10588 10589 .seealso: [](chapter_matrices), `Mat`, `MatInvertBlockDiagonal()` 10590 @*/ 10591 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C) 10592 { 10593 const PetscScalar *vals; 10594 PetscInt *dnnz; 10595 PetscInt m, rstart, rend, bs, i, j; 10596 10597 PetscFunctionBegin; 10598 PetscCall(MatInvertBlockDiagonal(A, &vals)); 10599 PetscCall(MatGetBlockSize(A, &bs)); 10600 PetscCall(MatGetLocalSize(A, &m, NULL)); 10601 PetscCall(MatSetLayouts(C, A->rmap, A->cmap)); 10602 PetscCall(PetscMalloc1(m / bs, &dnnz)); 10603 for (j = 0; j < m / bs; j++) dnnz[j] = 1; 10604 PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL)); 10605 PetscCall(PetscFree(dnnz)); 10606 PetscCall(MatGetOwnershipRange(C, &rstart, &rend)); 10607 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE)); 10608 for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES)); 10609 PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 10610 PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 10611 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE)); 10612 PetscFunctionReturn(PETSC_SUCCESS); 10613 } 10614 10615 /*@C 10616 MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created 10617 via `MatTransposeColoringCreate()`. 10618 10619 Collective 10620 10621 Input Parameter: 10622 . c - coloring context 10623 10624 Level: intermediate 10625 10626 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringCreate()` 10627 @*/ 10628 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c) 10629 { 10630 MatTransposeColoring matcolor = *c; 10631 10632 PetscFunctionBegin; 10633 if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS); 10634 if (--((PetscObject)matcolor)->refct > 0) { 10635 matcolor = NULL; 10636 PetscFunctionReturn(PETSC_SUCCESS); 10637 } 10638 10639 PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow)); 10640 PetscCall(PetscFree(matcolor->rows)); 10641 PetscCall(PetscFree(matcolor->den2sp)); 10642 PetscCall(PetscFree(matcolor->colorforcol)); 10643 PetscCall(PetscFree(matcolor->columns)); 10644 if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart)); 10645 PetscCall(PetscHeaderDestroy(c)); 10646 PetscFunctionReturn(PETSC_SUCCESS); 10647 } 10648 10649 /*@C 10650 MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which 10651 a `MatTransposeColoring` context has been created, computes a dense B^T by applying 10652 `MatTransposeColoring` to sparse B. 10653 10654 Collective 10655 10656 Input Parameters: 10657 + coloring - coloring context created with `MatTransposeColoringCreate()` 10658 - B - sparse matrix 10659 10660 Output Parameter: 10661 . Btdense - dense matrix B^T 10662 10663 Level: developer 10664 10665 Note: 10666 These are used internally for some implementations of `MatRARt()` 10667 10668 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()` 10669 @*/ 10670 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense) 10671 { 10672 PetscFunctionBegin; 10673 PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10674 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 10675 PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3); 10676 10677 PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense)); 10678 PetscFunctionReturn(PETSC_SUCCESS); 10679 } 10680 10681 /*@C 10682 MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which 10683 a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense 10684 in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix 10685 `Csp` from `Cden`. 10686 10687 Collective 10688 10689 Input Parameters: 10690 + matcoloring - coloring context created with `MatTransposeColoringCreate()` 10691 - Cden - matrix product of a sparse matrix and a dense matrix Btdense 10692 10693 Output Parameter: 10694 . Csp - sparse matrix 10695 10696 Level: developer 10697 10698 Note: 10699 These are used internally for some implementations of `MatRARt()` 10700 10701 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()` 10702 @*/ 10703 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp) 10704 { 10705 PetscFunctionBegin; 10706 PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10707 PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2); 10708 PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3); 10709 10710 PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp)); 10711 PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY)); 10712 PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY)); 10713 PetscFunctionReturn(PETSC_SUCCESS); 10714 } 10715 10716 /*@C 10717 MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T. 10718 10719 Collective 10720 10721 Input Parameters: 10722 + mat - the matrix product C 10723 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()` 10724 10725 Output Parameter: 10726 . color - the new coloring context 10727 10728 Level: intermediate 10729 10730 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`, 10731 `MatTransColoringApplyDenToSp()` 10732 @*/ 10733 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color) 10734 { 10735 MatTransposeColoring c; 10736 MPI_Comm comm; 10737 10738 PetscFunctionBegin; 10739 PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10740 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10741 PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL)); 10742 10743 c->ctype = iscoloring->ctype; 10744 PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c); 10745 10746 *color = c; 10747 PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10748 PetscFunctionReturn(PETSC_SUCCESS); 10749 } 10750 10751 /*@ 10752 MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the 10753 matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the 10754 same, otherwise it will be larger 10755 10756 Not Collective 10757 10758 Input Parameter: 10759 . A - the matrix 10760 10761 Output Parameter: 10762 . state - the current state 10763 10764 Level: intermediate 10765 10766 Notes: 10767 You can only compare states from two different calls to the SAME matrix, you cannot compare calls between 10768 different matrices 10769 10770 Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix 10771 10772 Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers. 10773 10774 .seealso: [](chapter_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()` 10775 @*/ 10776 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state) 10777 { 10778 PetscFunctionBegin; 10779 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10780 *state = mat->nonzerostate; 10781 PetscFunctionReturn(PETSC_SUCCESS); 10782 } 10783 10784 /*@ 10785 MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential 10786 matrices from each processor 10787 10788 Collective 10789 10790 Input Parameters: 10791 + comm - the communicators the parallel matrix will live on 10792 . seqmat - the input sequential matrices 10793 . n - number of local columns (or `PETSC_DECIDE`) 10794 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10795 10796 Output Parameter: 10797 . mpimat - the parallel matrix generated 10798 10799 Level: developer 10800 10801 Note: 10802 The number of columns of the matrix in EACH processor MUST be the same. 10803 10804 .seealso: [](chapter_matrices), `Mat` 10805 @*/ 10806 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat) 10807 { 10808 PetscMPIInt size; 10809 10810 PetscFunctionBegin; 10811 PetscCallMPI(MPI_Comm_size(comm, &size)); 10812 if (size == 1) { 10813 if (reuse == MAT_INITIAL_MATRIX) { 10814 PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat)); 10815 } else { 10816 PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN)); 10817 } 10818 PetscFunctionReturn(PETSC_SUCCESS); 10819 } 10820 10821 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"); 10822 10823 PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0)); 10824 PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat)); 10825 PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0)); 10826 PetscFunctionReturn(PETSC_SUCCESS); 10827 } 10828 10829 /*@ 10830 MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI ranks' ownership ranges. 10831 10832 Collective 10833 10834 Input Parameters: 10835 + A - the matrix to create subdomains from 10836 - N - requested number of subdomains 10837 10838 Output Parameters: 10839 + n - number of subdomains resulting on this MPI process 10840 - iss - `IS` list with indices of subdomains on this MPI process 10841 10842 Level: advanced 10843 10844 Note: 10845 The number of subdomains must be smaller than the communicator size 10846 10847 .seealso: [](chapter_matrices), `Mat`, `IS` 10848 @*/ 10849 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[]) 10850 { 10851 MPI_Comm comm, subcomm; 10852 PetscMPIInt size, rank, color; 10853 PetscInt rstart, rend, k; 10854 10855 PetscFunctionBegin; 10856 PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 10857 PetscCallMPI(MPI_Comm_size(comm, &size)); 10858 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 10859 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); 10860 *n = 1; 10861 k = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */ 10862 color = rank / k; 10863 PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm)); 10864 PetscCall(PetscMalloc1(1, iss)); 10865 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 10866 PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0])); 10867 PetscCallMPI(MPI_Comm_free(&subcomm)); 10868 PetscFunctionReturn(PETSC_SUCCESS); 10869 } 10870 10871 /*@ 10872 MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection. 10873 10874 If the interpolation and restriction operators are the same, uses `MatPtAP()`. 10875 If they are not the same, uses `MatMatMatMult()`. 10876 10877 Once the coarse grid problem is constructed, correct for interpolation operators 10878 that are not of full rank, which can legitimately happen in the case of non-nested 10879 geometric multigrid. 10880 10881 Input Parameters: 10882 + restrct - restriction operator 10883 . dA - fine grid matrix 10884 . interpolate - interpolation operator 10885 . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10886 - fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate 10887 10888 Output Parameter: 10889 . A - the Galerkin coarse matrix 10890 10891 Options Database Key: 10892 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used 10893 10894 Level: developer 10895 10896 .seealso: [](chapter_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()` 10897 @*/ 10898 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A) 10899 { 10900 IS zerorows; 10901 Vec diag; 10902 10903 PetscFunctionBegin; 10904 PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10905 /* Construct the coarse grid matrix */ 10906 if (interpolate == restrct) { 10907 PetscCall(MatPtAP(dA, interpolate, reuse, fill, A)); 10908 } else { 10909 PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A)); 10910 } 10911 10912 /* If the interpolation matrix is not of full rank, A will have zero rows. 10913 This can legitimately happen in the case of non-nested geometric multigrid. 10914 In that event, we set the rows of the matrix to the rows of the identity, 10915 ignoring the equations (as the RHS will also be zero). */ 10916 10917 PetscCall(MatFindZeroRows(*A, &zerorows)); 10918 10919 if (zerorows != NULL) { /* if there are any zero rows */ 10920 PetscCall(MatCreateVecs(*A, &diag, NULL)); 10921 PetscCall(MatGetDiagonal(*A, diag)); 10922 PetscCall(VecISSet(diag, zerorows, 1.0)); 10923 PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES)); 10924 PetscCall(VecDestroy(&diag)); 10925 PetscCall(ISDestroy(&zerorows)); 10926 } 10927 PetscFunctionReturn(PETSC_SUCCESS); 10928 } 10929 10930 /*@C 10931 MatSetOperation - Allows user to set a matrix operation for any matrix type 10932 10933 Logically Collective 10934 10935 Input Parameters: 10936 + mat - the matrix 10937 . op - the name of the operation 10938 - f - the function that provides the operation 10939 10940 Level: developer 10941 10942 Usage: 10943 .vb 10944 extern PetscErrorCode usermult(Mat, Vec, Vec); 10945 10946 PetscCall(MatCreateXXX(comm, ..., &A)); 10947 PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFunction)usermult)); 10948 .ve 10949 10950 Notes: 10951 See the file `include/petscmat.h` for a complete list of matrix 10952 operations, which all have the form MATOP_<OPERATION>, where 10953 <OPERATION> is the name (in all capital letters) of the 10954 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 10955 10956 All user-provided functions (except for `MATOP_DESTROY`) should have the same calling 10957 sequence as the usual matrix interface routines, since they 10958 are intended to be accessed via the usual matrix interface 10959 routines, e.g., 10960 .vb 10961 MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec) 10962 .ve 10963 10964 In particular each function MUST return `PETSC_SUCCESS` on success and 10965 nonzero on failure. 10966 10967 This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type. 10968 10969 .seealso: [](chapter_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()` 10970 @*/ 10971 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void)) 10972 { 10973 PetscFunctionBegin; 10974 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10975 if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view; 10976 (((void (**)(void))mat->ops)[op]) = f; 10977 PetscFunctionReturn(PETSC_SUCCESS); 10978 } 10979 10980 /*@C 10981 MatGetOperation - Gets a matrix operation for any matrix type. 10982 10983 Not Collective 10984 10985 Input Parameters: 10986 + mat - the matrix 10987 - op - the name of the operation 10988 10989 Output Parameter: 10990 . f - the function that provides the operation 10991 10992 Level: developer 10993 10994 Usage: 10995 .vb 10996 PetscErrorCode (*usermult)(Mat, Vec, Vec); 10997 MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult); 10998 .ve 10999 11000 Notes: 11001 See the file include/petscmat.h for a complete list of matrix 11002 operations, which all have the form MATOP_<OPERATION>, where 11003 <OPERATION> is the name (in all capital letters) of the 11004 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11005 11006 This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type. 11007 11008 .seealso: [](chapter_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()` 11009 @*/ 11010 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void)) 11011 { 11012 PetscFunctionBegin; 11013 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11014 *f = (((void (**)(void))mat->ops)[op]); 11015 PetscFunctionReturn(PETSC_SUCCESS); 11016 } 11017 11018 /*@ 11019 MatHasOperation - Determines whether the given matrix supports the particular operation. 11020 11021 Not Collective 11022 11023 Input Parameters: 11024 + mat - the matrix 11025 - op - the operation, for example, `MATOP_GET_DIAGONAL` 11026 11027 Output Parameter: 11028 . has - either `PETSC_TRUE` or `PETSC_FALSE` 11029 11030 Level: advanced 11031 11032 Note: 11033 See `MatSetOperation()` for additional discussion on naming convention and usage of `op`. 11034 11035 .seealso: [](chapter_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()` 11036 @*/ 11037 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has) 11038 { 11039 PetscFunctionBegin; 11040 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11041 PetscValidBoolPointer(has, 3); 11042 if (mat->ops->hasoperation) { 11043 PetscUseTypeMethod(mat, hasoperation, op, has); 11044 } else { 11045 if (((void **)mat->ops)[op]) *has = PETSC_TRUE; 11046 else { 11047 *has = PETSC_FALSE; 11048 if (op == MATOP_CREATE_SUBMATRIX) { 11049 PetscMPIInt size; 11050 11051 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 11052 if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has)); 11053 } 11054 } 11055 } 11056 PetscFunctionReturn(PETSC_SUCCESS); 11057 } 11058 11059 /*@ 11060 MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent 11061 11062 Collective 11063 11064 Input Parameter: 11065 . mat - the matrix 11066 11067 Output Parameter: 11068 . cong - either `PETSC_TRUE` or `PETSC_FALSE` 11069 11070 Level: beginner 11071 11072 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout` 11073 @*/ 11074 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong) 11075 { 11076 PetscFunctionBegin; 11077 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11078 PetscValidType(mat, 1); 11079 PetscValidBoolPointer(cong, 2); 11080 if (!mat->rmap || !mat->cmap) { 11081 *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE; 11082 PetscFunctionReturn(PETSC_SUCCESS); 11083 } 11084 if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */ 11085 PetscCall(PetscLayoutSetUp(mat->rmap)); 11086 PetscCall(PetscLayoutSetUp(mat->cmap)); 11087 PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong)); 11088 if (*cong) mat->congruentlayouts = 1; 11089 else mat->congruentlayouts = 0; 11090 } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE; 11091 PetscFunctionReturn(PETSC_SUCCESS); 11092 } 11093 11094 PetscErrorCode MatSetInf(Mat A) 11095 { 11096 PetscFunctionBegin; 11097 PetscUseTypeMethod(A, setinf); 11098 PetscFunctionReturn(PETSC_SUCCESS); 11099 } 11100 11101 /*@C 11102 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 11103 and possibly removes small values from the graph structure. 11104 11105 Collective 11106 11107 Input Parameters: 11108 + A - the matrix 11109 . sym - `PETSC_TRUE` indicates that the graph should be symmetrized 11110 . scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry 11111 - filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value 11112 11113 Output Parameter: 11114 . graph - the resulting graph 11115 11116 Level: advanced 11117 11118 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `PCGAMG` 11119 @*/ 11120 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph) 11121 { 11122 PetscFunctionBegin; 11123 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11124 PetscValidType(A, 1); 11125 PetscValidLogicalCollectiveBool(A, scale, 3); 11126 PetscValidPointer(graph, 5); 11127 PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph); 11128 PetscFunctionReturn(PETSC_SUCCESS); 11129 } 11130 11131 /*@ 11132 MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place, 11133 meaning the same memory is used for the matrix, and no new memory is allocated. 11134 11135 Collective 11136 11137 Input Parameter: 11138 . A - the matrix 11139 11140 Level: intermediate 11141 11142 Developer Note: 11143 The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end 11144 of the arrays in the data structure are unneeded. 11145 11146 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatChop()` 11147 @*/ 11148 PetscErrorCode MatEliminateZeros(Mat A) 11149 { 11150 PetscFunctionBegin; 11151 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11152 PetscUseTypeMethod(A, eliminatezeros); 11153 PetscFunctionReturn(PETSC_SUCCESS); 11154 } 11155