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 sequential dense and AIJ 1020 matrix types support the Socket viewer. 1021 1022 The user can call `PetscViewerPushFormat()` to specify the output 1023 format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`, 1024 `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`). Available formats include 1025 + `PETSC_VIEWER_DEFAULT` - default, prints matrix contents 1026 . `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in Matlab format 1027 . `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros 1028 . `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse 1029 format common among all matrix types 1030 . `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific 1031 format (which is in many cases the same as the default) 1032 . `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix 1033 size and structure (not the matrix entries) 1034 - `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about 1035 the matrix structure 1036 1037 The ASCII viewers are only recommended for small matrices on at most a moderate number of processes, 1038 the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format. 1039 1040 In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer). 1041 1042 See the manual page for `MatLoad()` for the exact format of the binary file when the binary 1043 viewer is used. 1044 1045 See share/petsc/matlab/PetscBinaryRead.m for a Matlab code that can read in the binary file when the binary 1046 viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python. 1047 1048 One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure, 1049 and then use the following mouse functions. 1050 .vb 1051 left mouse: zoom in 1052 middle mouse: zoom out 1053 right mouse: continue with the simulation 1054 .ve 1055 1056 .seealso: [](chapter_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`, 1057 `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()` 1058 @*/ 1059 PetscErrorCode MatView(Mat mat, PetscViewer viewer) 1060 { 1061 PetscInt rows, cols, rbs, cbs; 1062 PetscBool isascii, isstring, issaws; 1063 PetscViewerFormat format; 1064 PetscMPIInt size; 1065 1066 PetscFunctionBegin; 1067 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1068 PetscValidType(mat, 1); 1069 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer)); 1070 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1071 PetscCheckSameComm(mat, 1, viewer, 2); 1072 1073 PetscCall(PetscViewerGetFormat(viewer, &format)); 1074 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 1075 if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS); 1076 1077 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 1078 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 1079 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws)); 1080 PetscCheck((isascii && (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL)) || !mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "No viewers for factored matrix except ASCII, info, or info_detail"); 1081 1082 PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0)); 1083 if (isascii) { 1084 if (!mat->preallocated) { 1085 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n")); 1086 PetscFunctionReturn(PETSC_SUCCESS); 1087 } 1088 if (!mat->assembled) { 1089 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n")); 1090 PetscFunctionReturn(PETSC_SUCCESS); 1091 } 1092 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer)); 1093 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1094 MatNullSpace nullsp, transnullsp; 1095 1096 PetscCall(PetscViewerASCIIPushTab(viewer)); 1097 PetscCall(MatGetSize(mat, &rows, &cols)); 1098 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1099 if (rbs != 1 || cbs != 1) { 1100 if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs)); 1101 else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs)); 1102 } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols)); 1103 if (mat->factortype) { 1104 MatSolverType solver; 1105 PetscCall(MatFactorGetSolverType(mat, &solver)); 1106 PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver)); 1107 } 1108 if (mat->ops->getinfo) { 1109 MatInfo info; 1110 PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info)); 1111 PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated)); 1112 if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs)); 1113 } 1114 PetscCall(MatGetNullSpace(mat, &nullsp)); 1115 PetscCall(MatGetTransposeNullSpace(mat, &transnullsp)); 1116 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached null space\n")); 1117 if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached transposed null space\n")); 1118 PetscCall(MatGetNearNullSpace(mat, &nullsp)); 1119 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached near null space\n")); 1120 PetscCall(PetscViewerASCIIPushTab(viewer)); 1121 PetscCall(MatProductView(mat, viewer)); 1122 PetscCall(PetscViewerASCIIPopTab(viewer)); 1123 } 1124 } else if (issaws) { 1125 #if defined(PETSC_HAVE_SAWS) 1126 PetscMPIInt rank; 1127 1128 PetscCall(PetscObjectName((PetscObject)mat)); 1129 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 1130 if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer)); 1131 #endif 1132 } else if (isstring) { 1133 const char *type; 1134 PetscCall(MatGetType(mat, &type)); 1135 PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type)); 1136 PetscTryTypeMethod(mat, view, viewer); 1137 } 1138 if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) { 1139 PetscCall(PetscViewerASCIIPushTab(viewer)); 1140 PetscUseTypeMethod(mat, viewnative, viewer); 1141 PetscCall(PetscViewerASCIIPopTab(viewer)); 1142 } else if (mat->ops->view) { 1143 PetscCall(PetscViewerASCIIPushTab(viewer)); 1144 PetscUseTypeMethod(mat, view, viewer); 1145 PetscCall(PetscViewerASCIIPopTab(viewer)); 1146 } 1147 if (isascii) { 1148 PetscCall(PetscViewerGetFormat(viewer, &format)); 1149 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer)); 1150 } 1151 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1152 PetscFunctionReturn(PETSC_SUCCESS); 1153 } 1154 1155 #if defined(PETSC_USE_DEBUG) 1156 #include <../src/sys/totalview/tv_data_display.h> 1157 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat) 1158 { 1159 TV_add_row("Local rows", "int", &mat->rmap->n); 1160 TV_add_row("Local columns", "int", &mat->cmap->n); 1161 TV_add_row("Global rows", "int", &mat->rmap->N); 1162 TV_add_row("Global columns", "int", &mat->cmap->N); 1163 TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name); 1164 return TV_format_OK; 1165 } 1166 #endif 1167 1168 /*@C 1169 MatLoad - Loads a matrix that has been stored in binary/HDF5 format 1170 with `MatView()`. The matrix format is determined from the options database. 1171 Generates a parallel MPI matrix if the communicator has more than one 1172 processor. The default matrix type is `MATAIJ`. 1173 1174 Collective 1175 1176 Input Parameters: 1177 + mat - the newly loaded matrix, this needs to have been created with `MatCreate()` 1178 or some related function before a call to `MatLoad()` 1179 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer 1180 1181 Options Database Keys: 1182 Used with block matrix formats (`MATSEQBAIJ`, ...) to specify 1183 block size 1184 . -matload_block_size <bs> - set block size 1185 1186 Level: beginner 1187 1188 Notes: 1189 If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the 1190 `Mat` before calling this routine if you wish to set it from the options database. 1191 1192 `MatLoad()` automatically loads into the options database any options 1193 given in the file filename.info where filename is the name of the file 1194 that was passed to the `PetscViewerBinaryOpen()`. The options in the info 1195 file will be ignored if you use the -viewer_binary_skip_info option. 1196 1197 If the type or size of mat is not set before a call to `MatLoad()`, PETSc 1198 sets the default matrix type AIJ and sets the local and global sizes. 1199 If type and/or size is already set, then the same are used. 1200 1201 In parallel, each processor can load a subset of rows (or the 1202 entire matrix). This routine is especially useful when a large 1203 matrix is stored on disk and only part of it is desired on each 1204 processor. For example, a parallel solver may access only some of 1205 the rows from each processor. The algorithm used here reads 1206 relatively small blocks of data rather than reading the entire 1207 matrix and then subsetting it. 1208 1209 Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`. 1210 Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`, 1211 or the sequence like 1212 .vb 1213 `PetscViewer` v; 1214 `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v); 1215 `PetscViewerSetType`(v,`PETSCVIEWERBINARY`); 1216 `PetscViewerSetFromOptions`(v); 1217 `PetscViewerFileSetMode`(v,`FILE_MODE_READ`); 1218 `PetscViewerFileSetName`(v,"datafile"); 1219 .ve 1220 The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option 1221 $ -viewer_type {binary, hdf5} 1222 1223 See the example src/ksp/ksp/tutorials/ex27.c with the first approach, 1224 and src/mat/tutorials/ex10.c with the second approach. 1225 1226 In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks 1227 is read onto rank 0 and then shipped to its destination rank, one after another. 1228 Multiple objects, both matrices and vectors, can be stored within the same file. 1229 Their PetscObject name is ignored; they are loaded in the order of their storage. 1230 1231 Most users should not need to know the details of the binary storage 1232 format, since `MatLoad()` and `MatView()` completely hide these details. 1233 But for anyone who's interested, the standard binary matrix storage 1234 format is 1235 1236 .vb 1237 PetscInt MAT_FILE_CLASSID 1238 PetscInt number of rows 1239 PetscInt number of columns 1240 PetscInt total number of nonzeros 1241 PetscInt *number nonzeros in each row 1242 PetscInt *column indices of all nonzeros (starting index is zero) 1243 PetscScalar *values of all nonzeros 1244 .ve 1245 1246 PETSc automatically does the byte swapping for 1247 machines that store the bytes reversed. Thus if you write your own binary 1248 read/write routines you have to swap the bytes; see `PetscBinaryRead()` 1249 and `PetscBinaryWrite()` to see how this may be done. 1250 1251 In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used. 1252 Each processor's chunk is loaded independently by its owning rank. 1253 Multiple objects, both matrices and vectors, can be stored within the same file. 1254 They are looked up by their PetscObject name. 1255 1256 As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use 1257 by default the same structure and naming of the AIJ arrays and column count 1258 within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g. 1259 $ save example.mat A b -v7.3 1260 can be directly read by this routine (see Reference 1 for details). 1261 1262 Depending on your MATLAB version, this format might be a default, 1263 otherwise you can set it as default in Preferences. 1264 1265 Unless -nocompression flag is used to save the file in MATLAB, 1266 PETSc must be configured with ZLIB package. 1267 1268 See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c 1269 1270 This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5` 1271 1272 Corresponding `MatView()` is not yet implemented. 1273 1274 The loaded matrix is actually a transpose of the original one in MATLAB, 1275 unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above). 1276 With this format, matrix is automatically transposed by PETSc, 1277 unless the matrix is marked as SPD or symmetric 1278 (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`). 1279 1280 References: 1281 . * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version 1282 1283 .seealso: [](chapter_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()` 1284 @*/ 1285 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer) 1286 { 1287 PetscBool flg; 1288 1289 PetscFunctionBegin; 1290 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1291 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1292 1293 if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ)); 1294 1295 flg = PETSC_FALSE; 1296 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL)); 1297 if (flg) { 1298 PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE)); 1299 PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE)); 1300 } 1301 flg = PETSC_FALSE; 1302 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL)); 1303 if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE)); 1304 1305 PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0)); 1306 PetscUseTypeMethod(mat, load, viewer); 1307 PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0)); 1308 PetscFunctionReturn(PETSC_SUCCESS); 1309 } 1310 1311 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant) 1312 { 1313 Mat_Redundant *redund = *redundant; 1314 1315 PetscFunctionBegin; 1316 if (redund) { 1317 if (redund->matseq) { /* via MatCreateSubMatrices() */ 1318 PetscCall(ISDestroy(&redund->isrow)); 1319 PetscCall(ISDestroy(&redund->iscol)); 1320 PetscCall(MatDestroySubMatrices(1, &redund->matseq)); 1321 } else { 1322 PetscCall(PetscFree2(redund->send_rank, redund->recv_rank)); 1323 PetscCall(PetscFree(redund->sbuf_j)); 1324 PetscCall(PetscFree(redund->sbuf_a)); 1325 for (PetscInt i = 0; i < redund->nrecvs; i++) { 1326 PetscCall(PetscFree(redund->rbuf_j[i])); 1327 PetscCall(PetscFree(redund->rbuf_a[i])); 1328 } 1329 PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a)); 1330 } 1331 1332 if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm)); 1333 PetscCall(PetscFree(redund)); 1334 } 1335 PetscFunctionReturn(PETSC_SUCCESS); 1336 } 1337 1338 /*@C 1339 MatDestroy - Frees space taken by a matrix. 1340 1341 Collective 1342 1343 Input Parameter: 1344 . A - the matrix 1345 1346 Level: beginner 1347 1348 Developer Note: 1349 Some special arrays of matrices are not destroyed in this routine but instead by the routines called by 1350 `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines. 1351 `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes 1352 if changes are needed here. 1353 1354 .seealso: [](chapter_matrices), `Mat`, `MatCreate()` 1355 @*/ 1356 PetscErrorCode MatDestroy(Mat *A) 1357 { 1358 PetscFunctionBegin; 1359 if (!*A) PetscFunctionReturn(PETSC_SUCCESS); 1360 PetscValidHeaderSpecific(*A, MAT_CLASSID, 1); 1361 if (--((PetscObject)(*A))->refct > 0) { 1362 *A = NULL; 1363 PetscFunctionReturn(PETSC_SUCCESS); 1364 } 1365 1366 /* if memory was published with SAWs then destroy it */ 1367 PetscCall(PetscObjectSAWsViewOff((PetscObject)*A)); 1368 PetscTryTypeMethod((*A), destroy); 1369 1370 PetscCall(PetscFree((*A)->factorprefix)); 1371 PetscCall(PetscFree((*A)->defaultvectype)); 1372 PetscCall(PetscFree((*A)->defaultrandtype)); 1373 PetscCall(PetscFree((*A)->bsizes)); 1374 PetscCall(PetscFree((*A)->solvertype)); 1375 for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i])); 1376 if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL; 1377 PetscCall(MatDestroy_Redundant(&(*A)->redundant)); 1378 PetscCall(MatProductClear(*A)); 1379 PetscCall(MatNullSpaceDestroy(&(*A)->nullsp)); 1380 PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp)); 1381 PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp)); 1382 PetscCall(MatDestroy(&(*A)->schur)); 1383 PetscCall(PetscLayoutDestroy(&(*A)->rmap)); 1384 PetscCall(PetscLayoutDestroy(&(*A)->cmap)); 1385 PetscCall(PetscHeaderDestroy(A)); 1386 PetscFunctionReturn(PETSC_SUCCESS); 1387 } 1388 1389 /*@C 1390 MatSetValues - Inserts or adds a block of values into a matrix. 1391 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1392 MUST be called after all calls to `MatSetValues()` have been completed. 1393 1394 Not Collective 1395 1396 Input Parameters: 1397 + mat - the matrix 1398 . v - a logically two-dimensional array of values 1399 . m - the number of rows 1400 . idxm - the global indices of the rows 1401 . n - the number of columns 1402 . idxn - the global indices of the columns 1403 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1404 1405 Level: beginner 1406 1407 Notes: 1408 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1409 1410 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1411 options cannot be mixed without intervening calls to the assembly 1412 routines. 1413 1414 `MatSetValues()` uses 0-based row and column numbers in Fortran 1415 as well as in C. 1416 1417 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1418 simply ignored. This allows easily inserting element stiffness matrices 1419 with homogeneous Dirchlet boundary conditions that you don't want represented 1420 in the matrix. 1421 1422 Efficiency Alert: 1423 The routine `MatSetValuesBlocked()` may offer much better efficiency 1424 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1425 1426 Developer Note: 1427 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1428 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1429 1430 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1431 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1432 @*/ 1433 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1434 { 1435 PetscFunctionBeginHot; 1436 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1437 PetscValidType(mat, 1); 1438 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1439 PetscValidIntPointer(idxm, 3); 1440 PetscValidIntPointer(idxn, 5); 1441 MatCheckPreallocated(mat, 1); 1442 1443 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1444 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1445 1446 if (PetscDefined(USE_DEBUG)) { 1447 PetscInt i, j; 1448 1449 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1450 for (i = 0; i < m; i++) { 1451 for (j = 0; j < n; j++) { 1452 if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j])) 1453 #if defined(PETSC_USE_COMPLEX) 1454 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Inserting %g+i%g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")", (double)PetscRealPart(v[i * n + j]), (double)PetscImaginaryPart(v[i * n + j]), idxm[i], idxn[j]); 1455 #else 1456 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Inserting %g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")", (double)v[i * n + j], idxm[i], idxn[j]); 1457 #endif 1458 } 1459 } 1460 for (i = 0; i < m; i++) PetscCheck(idxm[i] < mat->rmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot insert in row %" PetscInt_FMT ", maximum is %" PetscInt_FMT, idxm[i], mat->rmap->N - 1); 1461 for (i = 0; i < n; i++) PetscCheck(idxn[i] < mat->cmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot insert in column %" PetscInt_FMT ", maximum is %" PetscInt_FMT, idxn[i], mat->cmap->N - 1); 1462 } 1463 1464 if (mat->assembled) { 1465 mat->was_assembled = PETSC_TRUE; 1466 mat->assembled = PETSC_FALSE; 1467 } 1468 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1469 PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv); 1470 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1471 PetscFunctionReturn(PETSC_SUCCESS); 1472 } 1473 1474 /*@C 1475 MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns 1476 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1477 MUST be called after all calls to `MatSetValues()` have been completed. 1478 1479 Not Collective 1480 1481 Input Parameters: 1482 + mat - the matrix 1483 . v - a logically two-dimensional array of values 1484 . ism - the rows to provide 1485 . isn - the columns to provide 1486 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1487 1488 Level: beginner 1489 1490 Notes: 1491 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1492 1493 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1494 options cannot be mixed without intervening calls to the assembly 1495 routines. 1496 1497 `MatSetValues()` uses 0-based row and column numbers in Fortran 1498 as well as in C. 1499 1500 Negative indices may be passed in `ism` and `isn`, these rows and columns are 1501 simply ignored. This allows easily inserting element stiffness matrices 1502 with homogeneous Dirchlet boundary conditions that you don't want represented 1503 in the matrix. 1504 1505 Efficiency Alert: 1506 The routine `MatSetValuesBlocked()` may offer much better efficiency 1507 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1508 1509 This is currently not optimized for any particular `ISType` 1510 1511 Developer Notes: 1512 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1513 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1514 1515 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1516 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()` 1517 @*/ 1518 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv) 1519 { 1520 PetscInt m, n; 1521 const PetscInt *rows, *cols; 1522 1523 PetscFunctionBeginHot; 1524 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1525 PetscCall(ISGetIndices(ism, &rows)); 1526 PetscCall(ISGetIndices(isn, &cols)); 1527 PetscCall(ISGetLocalSize(ism, &m)); 1528 PetscCall(ISGetLocalSize(isn, &n)); 1529 PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv)); 1530 PetscCall(ISRestoreIndices(ism, &rows)); 1531 PetscCall(ISRestoreIndices(isn, &cols)); 1532 PetscFunctionReturn(PETSC_SUCCESS); 1533 } 1534 1535 /*@ 1536 MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1537 values into a matrix 1538 1539 Not Collective 1540 1541 Input Parameters: 1542 + mat - the matrix 1543 . row - the (block) row to set 1544 - v - a logically two-dimensional array of values 1545 1546 Level: intermediate 1547 1548 Notes: 1549 The values, `v`, are column-oriented (for the block version) and sorted 1550 1551 All the nonzeros in the row must be provided 1552 1553 The matrix must have previously had its column indices set, likely by having been assembled. 1554 1555 The row must belong to this process 1556 1557 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1558 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()` 1559 @*/ 1560 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[]) 1561 { 1562 PetscInt globalrow; 1563 1564 PetscFunctionBegin; 1565 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1566 PetscValidType(mat, 1); 1567 PetscValidScalarPointer(v, 3); 1568 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow)); 1569 PetscCall(MatSetValuesRow(mat, globalrow, v)); 1570 PetscFunctionReturn(PETSC_SUCCESS); 1571 } 1572 1573 /*@ 1574 MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1575 values into a matrix 1576 1577 Not Collective 1578 1579 Input Parameters: 1580 + mat - the matrix 1581 . row - the (block) row to set 1582 - v - a logically two-dimensional (column major) array of values for block matrices with blocksize larger than one, otherwise a one dimensional array of values 1583 1584 Level: advanced 1585 1586 Notes: 1587 The values, `v`, are column-oriented for the block version. 1588 1589 All the nonzeros in the row must be provided 1590 1591 THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used. 1592 1593 The row must belong to this process 1594 1595 .seealso: [](chapter_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1596 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()` 1597 @*/ 1598 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[]) 1599 { 1600 PetscFunctionBeginHot; 1601 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1602 PetscValidType(mat, 1); 1603 MatCheckPreallocated(mat, 1); 1604 PetscValidScalarPointer(v, 3); 1605 PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values"); 1606 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1607 mat->insertmode = INSERT_VALUES; 1608 1609 if (mat->assembled) { 1610 mat->was_assembled = PETSC_TRUE; 1611 mat->assembled = PETSC_FALSE; 1612 } 1613 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1614 PetscUseTypeMethod(mat, setvaluesrow, row, v); 1615 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1616 PetscFunctionReturn(PETSC_SUCCESS); 1617 } 1618 1619 /*@ 1620 MatSetValuesStencil - Inserts or adds a block of values into a matrix. 1621 Using structured grid indexing 1622 1623 Not Collective 1624 1625 Input Parameters: 1626 + mat - the matrix 1627 . m - number of rows being entered 1628 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered 1629 . n - number of columns being entered 1630 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered 1631 . v - a logically two-dimensional array of values 1632 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values 1633 1634 Level: beginner 1635 1636 Notes: 1637 By default the values, `v`, are row-oriented. See `MatSetOption()` for other options. 1638 1639 Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1640 options cannot be mixed without intervening calls to the assembly 1641 routines. 1642 1643 The grid coordinates are across the entire grid, not just the local portion 1644 1645 `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran 1646 as well as in C. 1647 1648 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1649 1650 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1651 or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1652 1653 The columns and rows in the stencil passed in MUST be contained within the 1654 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1655 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1656 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1657 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1658 1659 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 1660 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 1661 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 1662 `DM_BOUNDARY_PERIODIC` boundary type. 1663 1664 For indices that don't mean anything for your case (like the k index when working in 2d) or the c index when you have 1665 a single value per point) you can skip filling those indices. 1666 1667 Inspired by the structured grid interface to the HYPRE package 1668 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1669 1670 Efficiency Alert: 1671 The routine `MatSetValuesBlockedStencil()` may offer much better efficiency 1672 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1673 1674 Fortran Note: 1675 `idxm` and `idxn` should be declared as 1676 $ MatStencil idxm(4,m),idxn(4,n) 1677 and the values inserted using 1678 .vb 1679 idxm(MatStencil_i,1) = i 1680 idxm(MatStencil_j,1) = j 1681 idxm(MatStencil_k,1) = k 1682 idxm(MatStencil_c,1) = c 1683 etc 1684 .ve 1685 1686 .seealso: [](chapter_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1687 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil` 1688 @*/ 1689 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1690 { 1691 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1692 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1693 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1694 1695 PetscFunctionBegin; 1696 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1697 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1698 PetscValidType(mat, 1); 1699 PetscValidPointer(idxm, 3); 1700 PetscValidPointer(idxn, 5); 1701 1702 if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 1703 jdxm = buf; 1704 jdxn = buf + m; 1705 } else { 1706 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1707 jdxm = bufm; 1708 jdxn = bufn; 1709 } 1710 for (i = 0; i < m; i++) { 1711 for (j = 0; j < 3 - sdim; j++) dxm++; 1712 tmp = *dxm++ - starts[0]; 1713 for (j = 0; j < dim - 1; j++) { 1714 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1715 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1716 } 1717 if (mat->stencil.noc) dxm++; 1718 jdxm[i] = tmp; 1719 } 1720 for (i = 0; i < n; i++) { 1721 for (j = 0; j < 3 - sdim; j++) dxn++; 1722 tmp = *dxn++ - starts[0]; 1723 for (j = 0; j < dim - 1; j++) { 1724 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1725 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1726 } 1727 if (mat->stencil.noc) dxn++; 1728 jdxn[i] = tmp; 1729 } 1730 PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv)); 1731 PetscCall(PetscFree2(bufm, bufn)); 1732 PetscFunctionReturn(PETSC_SUCCESS); 1733 } 1734 1735 /*@ 1736 MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix. 1737 Using structured grid indexing 1738 1739 Not Collective 1740 1741 Input Parameters: 1742 + mat - the matrix 1743 . m - number of rows being entered 1744 . idxm - grid coordinates for matrix rows being entered 1745 . n - number of columns being entered 1746 . idxn - grid coordinates for matrix columns being entered 1747 . v - a logically two-dimensional array of values 1748 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values 1749 1750 Level: beginner 1751 1752 Notes: 1753 By default the values, `v`, are row-oriented and unsorted. 1754 See `MatSetOption()` for other options. 1755 1756 Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1757 options cannot be mixed without intervening calls to the assembly 1758 routines. 1759 1760 The grid coordinates are across the entire grid, not just the local portion 1761 1762 `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran 1763 as well as in C. 1764 1765 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1766 1767 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1768 or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1769 1770 The columns and rows in the stencil passed in MUST be contained within the 1771 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1772 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1773 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1774 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1775 1776 Negative indices may be passed in idxm and idxn, these rows and columns are 1777 simply ignored. This allows easily inserting element stiffness matrices 1778 with homogeneous Dirchlet boundary conditions that you don't want represented 1779 in the matrix. 1780 1781 Inspired by the structured grid interface to the HYPRE package 1782 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1783 1784 Fortran Note: 1785 `idxm` and `idxn` should be declared as 1786 $ MatStencil idxm(4,m),idxn(4,n) 1787 and the values inserted using 1788 .vb 1789 idxm(MatStencil_i,1) = i 1790 idxm(MatStencil_j,1) = j 1791 idxm(MatStencil_k,1) = k 1792 etc 1793 .ve 1794 1795 .seealso: [](chapter_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1796 `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`, 1797 `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` 1798 @*/ 1799 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1800 { 1801 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1802 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1803 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1804 1805 PetscFunctionBegin; 1806 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1807 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1808 PetscValidType(mat, 1); 1809 PetscValidPointer(idxm, 3); 1810 PetscValidPointer(idxn, 5); 1811 PetscValidScalarPointer(v, 6); 1812 1813 if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 1814 jdxm = buf; 1815 jdxn = buf + m; 1816 } else { 1817 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1818 jdxm = bufm; 1819 jdxn = bufn; 1820 } 1821 for (i = 0; i < m; i++) { 1822 for (j = 0; j < 3 - sdim; j++) dxm++; 1823 tmp = *dxm++ - starts[0]; 1824 for (j = 0; j < sdim - 1; j++) { 1825 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1826 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1827 } 1828 dxm++; 1829 jdxm[i] = tmp; 1830 } 1831 for (i = 0; i < n; i++) { 1832 for (j = 0; j < 3 - sdim; j++) dxn++; 1833 tmp = *dxn++ - starts[0]; 1834 for (j = 0; j < sdim - 1; j++) { 1835 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1836 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1837 } 1838 dxn++; 1839 jdxn[i] = tmp; 1840 } 1841 PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv)); 1842 PetscCall(PetscFree2(bufm, bufn)); 1843 PetscFunctionReturn(PETSC_SUCCESS); 1844 } 1845 1846 /*@ 1847 MatSetStencil - Sets the grid information for setting values into a matrix via 1848 `MatSetValuesStencil()` 1849 1850 Not Collective 1851 1852 Input Parameters: 1853 + mat - the matrix 1854 . dim - dimension of the grid 1, 2, or 3 1855 . dims - number of grid points in x, y, and z direction, including ghost points on your processor 1856 . starts - starting point of ghost nodes on your processor in x, y, and z direction 1857 - dof - number of degrees of freedom per node 1858 1859 Level: beginner 1860 1861 Notes: 1862 Inspired by the structured grid interface to the HYPRE package 1863 (www.llnl.gov/CASC/hyper) 1864 1865 For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the 1866 user. 1867 1868 .seealso: [](chapter_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1869 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()` 1870 @*/ 1871 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof) 1872 { 1873 PetscFunctionBegin; 1874 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1875 PetscValidIntPointer(dims, 3); 1876 PetscValidIntPointer(starts, 4); 1877 1878 mat->stencil.dim = dim + (dof > 1); 1879 for (PetscInt i = 0; i < dim; i++) { 1880 mat->stencil.dims[i] = dims[dim - i - 1]; /* copy the values in backwards */ 1881 mat->stencil.starts[i] = starts[dim - i - 1]; 1882 } 1883 mat->stencil.dims[dim] = dof; 1884 mat->stencil.starts[dim] = 0; 1885 mat->stencil.noc = (PetscBool)(dof == 1); 1886 PetscFunctionReturn(PETSC_SUCCESS); 1887 } 1888 1889 /*@C 1890 MatSetValuesBlocked - Inserts or adds a block of values into a matrix. 1891 1892 Not Collective 1893 1894 Input Parameters: 1895 + mat - the matrix 1896 . v - a logically two-dimensional array of values 1897 . m - the number of block rows 1898 . idxm - the global block indices 1899 . n - the number of block columns 1900 . idxn - the global block indices 1901 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values 1902 1903 Level: intermediate 1904 1905 Notes: 1906 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call 1907 MatXXXXSetPreallocation() or `MatSetUp()` before using this routine. 1908 1909 The `m` and `n` count the NUMBER of blocks in the row direction and column direction, 1910 NOT the total number of rows/columns; for example, if the block size is 2 and 1911 you are passing in values for rows 2,3,4,5 then m would be 2 (not 4). 1912 The values in idxm would be 1 2; that is the first index for each block divided by 1913 the block size. 1914 1915 You must call `MatSetBlockSize()` when constructing this matrix (before 1916 preallocating it). 1917 1918 By default the values, `v`, are row-oriented, so the layout of 1919 `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options. 1920 1921 Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES` 1922 options cannot be mixed without intervening calls to the assembly 1923 routines. 1924 1925 `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran 1926 as well as in C. 1927 1928 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1929 simply ignored. This allows easily inserting element stiffness matrices 1930 with homogeneous Dirchlet boundary conditions that you don't want represented 1931 in the matrix. 1932 1933 Each time an entry is set within a sparse matrix via `MatSetValues()`, 1934 internal searching must be done to determine where to place the 1935 data in the matrix storage space. By instead inserting blocks of 1936 entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is 1937 reduced. 1938 1939 Example: 1940 .vb 1941 Suppose m=n=2 and block size(bs) = 2 The array is 1942 1943 1 2 | 3 4 1944 5 6 | 7 8 1945 - - - | - - - 1946 9 10 | 11 12 1947 13 14 | 15 16 1948 1949 v[] should be passed in like 1950 v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] 1951 1952 If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then 1953 v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16] 1954 .ve 1955 1956 .seealso: [](chapter_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()` 1957 @*/ 1958 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1959 { 1960 PetscFunctionBeginHot; 1961 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1962 PetscValidType(mat, 1); 1963 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1964 PetscValidIntPointer(idxm, 3); 1965 PetscValidIntPointer(idxn, 5); 1966 MatCheckPreallocated(mat, 1); 1967 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1968 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1969 if (PetscDefined(USE_DEBUG)) { 1970 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1971 PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 1972 } 1973 if (PetscDefined(USE_DEBUG)) { 1974 PetscInt rbs, cbs, M, N, i; 1975 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1976 PetscCall(MatGetSize(mat, &M, &N)); 1977 for (i = 0; i < m; i++) PetscCheck(idxm[i] * rbs < M, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row block index %" PetscInt_FMT " (index %" PetscInt_FMT ") greater than row length %" PetscInt_FMT, i, idxm[i], M); 1978 for (i = 0; i < n; i++) PetscCheck(idxn[i] * cbs < N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column block index %" PetscInt_FMT " (index %" PetscInt_FMT ") great than column length %" PetscInt_FMT, i, idxn[i], N); 1979 } 1980 if (mat->assembled) { 1981 mat->was_assembled = PETSC_TRUE; 1982 mat->assembled = PETSC_FALSE; 1983 } 1984 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1985 if (mat->ops->setvaluesblocked) { 1986 PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv); 1987 } else { 1988 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn; 1989 PetscInt i, j, bs, cbs; 1990 1991 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 1992 if (m * bs + n * cbs <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 1993 iidxm = buf; 1994 iidxn = buf + m * bs; 1995 } else { 1996 PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc)); 1997 iidxm = bufr; 1998 iidxn = bufc; 1999 } 2000 for (i = 0; i < m; i++) { 2001 for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j; 2002 } 2003 if (m != n || bs != cbs || idxm != idxn) { 2004 for (i = 0; i < n; i++) { 2005 for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j; 2006 } 2007 } else iidxn = iidxm; 2008 PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv)); 2009 PetscCall(PetscFree2(bufr, bufc)); 2010 } 2011 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2012 PetscFunctionReturn(PETSC_SUCCESS); 2013 } 2014 2015 /*@C 2016 MatGetValues - Gets a block of local values from a matrix. 2017 2018 Not Collective; can only return values that are owned by the give process 2019 2020 Input Parameters: 2021 + mat - the matrix 2022 . v - a logically two-dimensional array for storing the values 2023 . m - the number of rows 2024 . idxm - the global indices of the rows 2025 . n - the number of columns 2026 - idxn - the global indices of the columns 2027 2028 Level: advanced 2029 2030 Notes: 2031 The user must allocate space (m*n `PetscScalar`s) for the values, `v`. 2032 The values, `v`, are then returned in a row-oriented format, 2033 analogous to that used by default in `MatSetValues()`. 2034 2035 `MatGetValues()` uses 0-based row and column numbers in 2036 Fortran as well as in C. 2037 2038 `MatGetValues()` requires that the matrix has been assembled 2039 with `MatAssemblyBegin()`/`MatAssemblyEnd()`. Thus, calls to 2040 `MatSetValues()` and `MatGetValues()` CANNOT be made in succession 2041 without intermediate matrix assembly. 2042 2043 Negative row or column indices will be ignored and those locations in `v` will be 2044 left unchanged. 2045 2046 For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI rank. 2047 That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable 2048 from `MatGetOwnershipRange`(mat,&rstart,&rend). 2049 2050 .seealso: [](chapter_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()` 2051 @*/ 2052 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) 2053 { 2054 PetscFunctionBegin; 2055 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2056 PetscValidType(mat, 1); 2057 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); 2058 PetscValidIntPointer(idxm, 3); 2059 PetscValidIntPointer(idxn, 5); 2060 PetscValidScalarPointer(v, 6); 2061 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2062 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2063 MatCheckPreallocated(mat, 1); 2064 2065 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2066 PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v); 2067 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2068 PetscFunctionReturn(PETSC_SUCCESS); 2069 } 2070 2071 /*@C 2072 MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices 2073 defined previously by `MatSetLocalToGlobalMapping()` 2074 2075 Not Collective 2076 2077 Input Parameters: 2078 + mat - the matrix 2079 . nrow - number of rows 2080 . irow - the row local indices 2081 . ncol - number of columns 2082 - icol - the column local indices 2083 2084 Output Parameter: 2085 . y - a logically two-dimensional array of values 2086 2087 Level: advanced 2088 2089 Notes: 2090 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine. 2091 2092 This routine can only return values that are owned by the requesting MPI rank. That is, for standard matrix formats, rows that, in the global numbering, 2093 are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can 2094 determine if the resulting global row associated with the local row r is owned by the requesting MPI rank by applying the `ISLocalToGlobalMapping` set 2095 with `MatSetLocalToGlobalMapping()`. 2096 2097 Developer Note: 2098 This is labelled with C so does not automatically generate Fortran stubs and interfaces 2099 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2100 2101 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2102 `MatSetValuesLocal()`, `MatGetValues()` 2103 @*/ 2104 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[]) 2105 { 2106 PetscFunctionBeginHot; 2107 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2108 PetscValidType(mat, 1); 2109 MatCheckPreallocated(mat, 1); 2110 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */ 2111 PetscValidIntPointer(irow, 3); 2112 PetscValidIntPointer(icol, 5); 2113 if (PetscDefined(USE_DEBUG)) { 2114 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2115 PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2116 } 2117 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2118 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2119 if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y); 2120 else { 2121 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm; 2122 if ((nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2123 irowm = buf; 2124 icolm = buf + nrow; 2125 } else { 2126 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2127 irowm = bufr; 2128 icolm = bufc; 2129 } 2130 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping())."); 2131 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping())."); 2132 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm)); 2133 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm)); 2134 PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y)); 2135 PetscCall(PetscFree2(bufr, bufc)); 2136 } 2137 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2138 PetscFunctionReturn(PETSC_SUCCESS); 2139 } 2140 2141 /*@ 2142 MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and 2143 the same size. Currently, this can only be called once and creates the given matrix. 2144 2145 Not Collective 2146 2147 Input Parameters: 2148 + mat - the matrix 2149 . nb - the number of blocks 2150 . bs - the number of rows (and columns) in each block 2151 . rows - a concatenation of the rows for each block 2152 - v - a concatenation of logically two-dimensional arrays of values 2153 2154 Level: advanced 2155 2156 Note: 2157 `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values 2158 2159 In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix. 2160 2161 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 2162 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()` 2163 @*/ 2164 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[]) 2165 { 2166 PetscFunctionBegin; 2167 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2168 PetscValidType(mat, 1); 2169 PetscValidIntPointer(rows, 4); 2170 PetscValidScalarPointer(v, 5); 2171 PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2172 2173 PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0)); 2174 if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v); 2175 else { 2176 for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES)); 2177 } 2178 PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0)); 2179 PetscFunctionReturn(PETSC_SUCCESS); 2180 } 2181 2182 /*@ 2183 MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by 2184 the routine `MatSetValuesLocal()` to allow users to insert matrix entries 2185 using a local (per-processor) numbering. 2186 2187 Not Collective 2188 2189 Input Parameters: 2190 + x - the matrix 2191 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()` 2192 - cmapping - column mapping 2193 2194 Level: intermediate 2195 2196 Note: 2197 If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix 2198 2199 .seealso: [](chapter_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()` 2200 @*/ 2201 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping) 2202 { 2203 PetscFunctionBegin; 2204 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 2205 PetscValidType(x, 1); 2206 if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2); 2207 if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3); 2208 if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping); 2209 else { 2210 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping)); 2211 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping)); 2212 } 2213 PetscFunctionReturn(PETSC_SUCCESS); 2214 } 2215 2216 /*@ 2217 MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()` 2218 2219 Not Collective 2220 2221 Input Parameter: 2222 . A - the matrix 2223 2224 Output Parameters: 2225 + rmapping - row mapping 2226 - cmapping - column mapping 2227 2228 Level: advanced 2229 2230 .seealso: [](chapter_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()` 2231 @*/ 2232 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping) 2233 { 2234 PetscFunctionBegin; 2235 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2236 PetscValidType(A, 1); 2237 if (rmapping) { 2238 PetscValidPointer(rmapping, 2); 2239 *rmapping = A->rmap->mapping; 2240 } 2241 if (cmapping) { 2242 PetscValidPointer(cmapping, 3); 2243 *cmapping = A->cmap->mapping; 2244 } 2245 PetscFunctionReturn(PETSC_SUCCESS); 2246 } 2247 2248 /*@ 2249 MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix 2250 2251 Logically Collective 2252 2253 Input Parameters: 2254 + A - the matrix 2255 . rmap - row layout 2256 - cmap - column layout 2257 2258 Level: advanced 2259 2260 Note: 2261 The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called. 2262 2263 .seealso: [](chapter_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()` 2264 @*/ 2265 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap) 2266 { 2267 PetscFunctionBegin; 2268 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2269 PetscCall(PetscLayoutReference(rmap, &A->rmap)); 2270 PetscCall(PetscLayoutReference(cmap, &A->cmap)); 2271 PetscFunctionReturn(PETSC_SUCCESS); 2272 } 2273 2274 /*@ 2275 MatGetLayouts - Gets the `PetscLayout` objects for rows and columns 2276 2277 Not Collective 2278 2279 Input Parameter: 2280 . A - the matrix 2281 2282 Output Parameters: 2283 + rmap - row layout 2284 - cmap - column layout 2285 2286 Level: advanced 2287 2288 .seealso: [](chapter_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()` 2289 @*/ 2290 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap) 2291 { 2292 PetscFunctionBegin; 2293 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2294 PetscValidType(A, 1); 2295 if (rmap) { 2296 PetscValidPointer(rmap, 2); 2297 *rmap = A->rmap; 2298 } 2299 if (cmap) { 2300 PetscValidPointer(cmap, 3); 2301 *cmap = A->cmap; 2302 } 2303 PetscFunctionReturn(PETSC_SUCCESS); 2304 } 2305 2306 /*@C 2307 MatSetValuesLocal - Inserts or adds values into certain locations of a matrix, 2308 using a local numbering of the nodes. 2309 2310 Not Collective 2311 2312 Input Parameters: 2313 + mat - the matrix 2314 . nrow - number of rows 2315 . irow - the row local indices 2316 . ncol - number of columns 2317 . icol - the column local indices 2318 . y - a logically two-dimensional array of values 2319 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2320 2321 Level: intermediate 2322 2323 Notes: 2324 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 2325 `MatSetUp()` before using this routine 2326 2327 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine 2328 2329 Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2330 options cannot be mixed without intervening calls to the assembly 2331 routines. 2332 2333 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2334 MUST be called after all calls to `MatSetValuesLocal()` have been completed. 2335 2336 Developer Note: 2337 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2338 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2339 2340 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2341 `MatGetValuesLocal()` 2342 @*/ 2343 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2344 { 2345 PetscFunctionBeginHot; 2346 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2347 PetscValidType(mat, 1); 2348 MatCheckPreallocated(mat, 1); 2349 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2350 PetscValidIntPointer(irow, 3); 2351 PetscValidIntPointer(icol, 5); 2352 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2353 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2354 if (PetscDefined(USE_DEBUG)) { 2355 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2356 PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2357 } 2358 2359 if (mat->assembled) { 2360 mat->was_assembled = PETSC_TRUE; 2361 mat->assembled = PETSC_FALSE; 2362 } 2363 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2364 if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv); 2365 else { 2366 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2367 const PetscInt *irowm, *icolm; 2368 2369 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2370 bufr = buf; 2371 bufc = buf + nrow; 2372 irowm = bufr; 2373 icolm = bufc; 2374 } else { 2375 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2376 irowm = bufr; 2377 icolm = bufc; 2378 } 2379 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr)); 2380 else irowm = irow; 2381 if (mat->cmap->mapping) { 2382 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2383 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc)); 2384 } else icolm = irowm; 2385 } else icolm = icol; 2386 PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv)); 2387 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2388 } 2389 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2390 PetscFunctionReturn(PETSC_SUCCESS); 2391 } 2392 2393 /*@C 2394 MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix, 2395 using a local ordering of the nodes a block at a time. 2396 2397 Not Collective 2398 2399 Input Parameters: 2400 + x - the matrix 2401 . nrow - number of rows 2402 . irow - the row local indices 2403 . ncol - number of columns 2404 . icol - the column local indices 2405 . y - a logically two-dimensional array of values 2406 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2407 2408 Level: intermediate 2409 2410 Notes: 2411 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 2412 `MatSetUp()` before using this routine 2413 2414 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()` 2415 before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the 2416 2417 Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2418 options cannot be mixed without intervening calls to the assembly 2419 routines. 2420 2421 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2422 MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed. 2423 2424 Developer Note: 2425 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2426 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2427 2428 .seealso: [](chapter_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, 2429 `MatSetValuesLocal()`, `MatSetValuesBlocked()` 2430 @*/ 2431 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2432 { 2433 PetscFunctionBeginHot; 2434 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2435 PetscValidType(mat, 1); 2436 MatCheckPreallocated(mat, 1); 2437 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2438 PetscValidIntPointer(irow, 3); 2439 PetscValidIntPointer(icol, 5); 2440 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2441 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2442 if (PetscDefined(USE_DEBUG)) { 2443 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2444 PetscCheck(mat->ops->setvaluesblockedlocal || mat->ops->setvaluesblocked || mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2445 } 2446 2447 if (mat->assembled) { 2448 mat->was_assembled = PETSC_TRUE; 2449 mat->assembled = PETSC_FALSE; 2450 } 2451 if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */ 2452 PetscInt irbs, rbs; 2453 PetscCall(MatGetBlockSizes(mat, &rbs, NULL)); 2454 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs)); 2455 PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs); 2456 } 2457 if (PetscUnlikelyDebug(mat->cmap->mapping)) { 2458 PetscInt icbs, cbs; 2459 PetscCall(MatGetBlockSizes(mat, NULL, &cbs)); 2460 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs)); 2461 PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs); 2462 } 2463 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2464 if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv); 2465 else { 2466 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2467 const PetscInt *irowm, *icolm; 2468 2469 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2470 bufr = buf; 2471 bufc = buf + nrow; 2472 irowm = bufr; 2473 icolm = bufc; 2474 } else { 2475 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2476 irowm = bufr; 2477 icolm = bufc; 2478 } 2479 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr)); 2480 else irowm = irow; 2481 if (mat->cmap->mapping) { 2482 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2483 PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc)); 2484 } else icolm = irowm; 2485 } else icolm = icol; 2486 PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv)); 2487 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2488 } 2489 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2490 PetscFunctionReturn(PETSC_SUCCESS); 2491 } 2492 2493 /*@ 2494 MatMultDiagonalBlock - Computes the matrix-vector product, y = Dx. Where D is defined by the inode or block structure of the diagonal 2495 2496 Collective 2497 2498 Input Parameters: 2499 + mat - the matrix 2500 - x - the vector to be multiplied 2501 2502 Output Parameter: 2503 . y - the result 2504 2505 Level: developer 2506 2507 Note: 2508 The vectors `x` and `y` cannot be the same. I.e., one cannot 2509 call `MatMultDiagonalBlock`(A,y,y). 2510 2511 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2512 @*/ 2513 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y) 2514 { 2515 PetscFunctionBegin; 2516 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2517 PetscValidType(mat, 1); 2518 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2519 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2520 2521 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2522 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2523 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2524 MatCheckPreallocated(mat, 1); 2525 2526 PetscUseTypeMethod(mat, multdiagonalblock, x, y); 2527 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2528 PetscFunctionReturn(PETSC_SUCCESS); 2529 } 2530 2531 /*@ 2532 MatMult - Computes the matrix-vector product, y = Ax. 2533 2534 Neighbor-wise Collective 2535 2536 Input Parameters: 2537 + mat - the matrix 2538 - x - the vector to be multiplied 2539 2540 Output Parameter: 2541 . y - the result 2542 2543 Level: beginner 2544 2545 Note: 2546 The vectors `x` and `y` cannot be the same. I.e., one cannot 2547 call `MatMult`(A,y,y). 2548 2549 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2550 @*/ 2551 PetscErrorCode MatMult(Mat mat, Vec x, Vec y) 2552 { 2553 PetscFunctionBegin; 2554 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2555 PetscValidType(mat, 1); 2556 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2557 VecCheckAssembled(x); 2558 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2559 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2560 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2561 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2562 PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N); 2563 PetscCheck(mat->rmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, y->map->N); 2564 PetscCheck(mat->cmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, x->map->n); 2565 PetscCheck(mat->rmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, y->map->n); 2566 PetscCall(VecSetErrorIfLocked(y, 3)); 2567 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2568 MatCheckPreallocated(mat, 1); 2569 2570 PetscCall(VecLockReadPush(x)); 2571 PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0)); 2572 PetscUseTypeMethod(mat, mult, x, y); 2573 PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0)); 2574 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2575 PetscCall(VecLockReadPop(x)); 2576 PetscFunctionReturn(PETSC_SUCCESS); 2577 } 2578 2579 /*@ 2580 MatMultTranspose - Computes matrix transpose times a vector y = A^T * x. 2581 2582 Neighbor-wise Collective 2583 2584 Input Parameters: 2585 + mat - the matrix 2586 - x - the vector to be multiplied 2587 2588 Output Parameter: 2589 . y - the result 2590 2591 Level: beginner 2592 2593 Notes: 2594 The vectors `x` and `y` cannot be the same. I.e., one cannot 2595 call `MatMultTranspose`(A,y,y). 2596 2597 For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple, 2598 use `MatMultHermitianTranspose()` 2599 2600 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()` 2601 @*/ 2602 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y) 2603 { 2604 PetscErrorCode (*op)(Mat, Vec, Vec) = NULL; 2605 2606 PetscFunctionBegin; 2607 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2608 PetscValidType(mat, 1); 2609 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2610 VecCheckAssembled(x); 2611 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2612 2613 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2614 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2615 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2616 PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N); 2617 PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N); 2618 PetscCheck(mat->cmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, y->map->n); 2619 PetscCheck(mat->rmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, x->map->n); 2620 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2621 MatCheckPreallocated(mat, 1); 2622 2623 if (!mat->ops->multtranspose) { 2624 if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult; 2625 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s does not have a multiply transpose defined or is symmetric and does not have a multiply defined", ((PetscObject)mat)->type_name); 2626 } else op = mat->ops->multtranspose; 2627 PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0)); 2628 PetscCall(VecLockReadPush(x)); 2629 PetscCall((*op)(mat, x, y)); 2630 PetscCall(VecLockReadPop(x)); 2631 PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0)); 2632 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2633 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2634 PetscFunctionReturn(PETSC_SUCCESS); 2635 } 2636 2637 /*@ 2638 MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector. 2639 2640 Neighbor-wise Collective 2641 2642 Input Parameters: 2643 + mat - the matrix 2644 - x - the vector to be multilplied 2645 2646 Output Parameter: 2647 . y - the result 2648 2649 Level: beginner 2650 2651 Notes: 2652 The vectors `x` and `y` cannot be the same. I.e., one cannot 2653 call `MatMultHermitianTranspose`(A,y,y). 2654 2655 Also called the conjugate transpose, complex conjugate transpose, or adjoint. 2656 2657 For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical. 2658 2659 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()` 2660 @*/ 2661 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y) 2662 { 2663 PetscFunctionBegin; 2664 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2665 PetscValidType(mat, 1); 2666 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2667 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2668 2669 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2670 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2671 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2672 PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N); 2673 PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N); 2674 PetscCheck(mat->cmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, y->map->n); 2675 PetscCheck(mat->rmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, x->map->n); 2676 MatCheckPreallocated(mat, 1); 2677 2678 PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0)); 2679 #if defined(PETSC_USE_COMPLEX) 2680 if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) { 2681 PetscCall(VecLockReadPush(x)); 2682 if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y); 2683 else PetscUseTypeMethod(mat, mult, x, y); 2684 PetscCall(VecLockReadPop(x)); 2685 } else { 2686 Vec w; 2687 PetscCall(VecDuplicate(x, &w)); 2688 PetscCall(VecCopy(x, w)); 2689 PetscCall(VecConjugate(w)); 2690 PetscCall(MatMultTranspose(mat, w, y)); 2691 PetscCall(VecDestroy(&w)); 2692 PetscCall(VecConjugate(y)); 2693 } 2694 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2695 #else 2696 PetscCall(MatMultTranspose(mat, x, y)); 2697 #endif 2698 PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0)); 2699 PetscFunctionReturn(PETSC_SUCCESS); 2700 } 2701 2702 /*@ 2703 MatMultAdd - Computes v3 = v2 + A * v1. 2704 2705 Neighbor-wise Collective 2706 2707 Input Parameters: 2708 + mat - the matrix 2709 . v1 - the vector to be multiplied by `mat` 2710 - v2 - the vector to be added to the result 2711 2712 Output Parameter: 2713 . v3 - the result 2714 2715 Level: beginner 2716 2717 Note: 2718 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2719 call `MatMultAdd`(A,v1,v2,v1). 2720 2721 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()` 2722 @*/ 2723 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2724 { 2725 PetscFunctionBegin; 2726 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2727 PetscValidType(mat, 1); 2728 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2729 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2730 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2731 2732 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2733 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2734 PetscCheck(mat->cmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v1->map->N); 2735 /* PetscCheck(mat->rmap->N == v2->map->N,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v2->map->N); 2736 PetscCheck(mat->rmap->N == v3->map->N,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v3->map->N); */ 2737 PetscCheck(mat->rmap->n == v3->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, v3->map->n); 2738 PetscCheck(mat->rmap->n == v2->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, v2->map->n); 2739 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2740 MatCheckPreallocated(mat, 1); 2741 2742 PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3)); 2743 PetscCall(VecLockReadPush(v1)); 2744 PetscUseTypeMethod(mat, multadd, v1, v2, v3); 2745 PetscCall(VecLockReadPop(v1)); 2746 PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3)); 2747 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2748 PetscFunctionReturn(PETSC_SUCCESS); 2749 } 2750 2751 /*@ 2752 MatMultTransposeAdd - Computes v3 = v2 + A' * v1. 2753 2754 Neighbor-wise Collective 2755 2756 Input Parameters: 2757 + mat - the matrix 2758 . v1 - the vector to be multiplied by the transpose of the matrix 2759 - v2 - the vector to be added to the result 2760 2761 Output Parameter: 2762 . v3 - the result 2763 2764 Level: beginner 2765 2766 Note: 2767 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2768 call `MatMultTransposeAdd`(A,v1,v2,v1). 2769 2770 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2771 @*/ 2772 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2773 { 2774 PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd; 2775 2776 PetscFunctionBegin; 2777 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2778 PetscValidType(mat, 1); 2779 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2780 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2781 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2782 2783 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2784 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2785 PetscCheck(mat->rmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, v1->map->N); 2786 PetscCheck(mat->cmap->N == v2->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v2->map->N); 2787 PetscCheck(mat->cmap->N == v3->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v3->map->N); 2788 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2789 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2790 MatCheckPreallocated(mat, 1); 2791 2792 PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2793 PetscCall(VecLockReadPush(v1)); 2794 PetscCall((*op)(mat, v1, v2, v3)); 2795 PetscCall(VecLockReadPop(v1)); 2796 PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2797 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2798 PetscFunctionReturn(PETSC_SUCCESS); 2799 } 2800 2801 /*@ 2802 MatMultHermitianTransposeAdd - Computes v3 = v2 + A^H * v1. 2803 2804 Neighbor-wise Collective 2805 2806 Input Parameters: 2807 + mat - the matrix 2808 . v1 - the vector to be multiplied by the Hermitian transpose 2809 - v2 - the vector to be added to the result 2810 2811 Output Parameter: 2812 . v3 - the result 2813 2814 Level: beginner 2815 2816 Note: 2817 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2818 call `MatMultHermitianTransposeAdd`(A,v1,v2,v1). 2819 2820 .seealso: [](chapter_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2821 @*/ 2822 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2823 { 2824 PetscFunctionBegin; 2825 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2826 PetscValidType(mat, 1); 2827 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2828 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2829 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2830 2831 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2832 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2833 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2834 PetscCheck(mat->rmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, v1->map->N); 2835 PetscCheck(mat->cmap->N == v2->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v2->map->N); 2836 PetscCheck(mat->cmap->N == v3->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v3->map->N); 2837 MatCheckPreallocated(mat, 1); 2838 2839 PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2840 PetscCall(VecLockReadPush(v1)); 2841 if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3); 2842 else { 2843 Vec w, z; 2844 PetscCall(VecDuplicate(v1, &w)); 2845 PetscCall(VecCopy(v1, w)); 2846 PetscCall(VecConjugate(w)); 2847 PetscCall(VecDuplicate(v3, &z)); 2848 PetscCall(MatMultTranspose(mat, w, z)); 2849 PetscCall(VecDestroy(&w)); 2850 PetscCall(VecConjugate(z)); 2851 if (v2 != v3) { 2852 PetscCall(VecWAXPY(v3, 1.0, v2, z)); 2853 } else { 2854 PetscCall(VecAXPY(v3, 1.0, z)); 2855 } 2856 PetscCall(VecDestroy(&z)); 2857 } 2858 PetscCall(VecLockReadPop(v1)); 2859 PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2860 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2861 PetscFunctionReturn(PETSC_SUCCESS); 2862 } 2863 2864 /*@C 2865 MatGetFactorType - gets the type of factorization it is 2866 2867 Not Collective 2868 2869 Input Parameter: 2870 . mat - the matrix 2871 2872 Output Parameter: 2873 . t - the type, one of `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2874 2875 Level: intermediate 2876 2877 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2878 `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2879 @*/ 2880 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t) 2881 { 2882 PetscFunctionBegin; 2883 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2884 PetscValidType(mat, 1); 2885 PetscValidPointer(t, 2); 2886 *t = mat->factortype; 2887 PetscFunctionReturn(PETSC_SUCCESS); 2888 } 2889 2890 /*@C 2891 MatSetFactorType - sets the type of factorization it is 2892 2893 Logically Collective 2894 2895 Input Parameters: 2896 + mat - the matrix 2897 - t - the type, one of `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2898 2899 Level: intermediate 2900 2901 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2902 `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2903 @*/ 2904 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t) 2905 { 2906 PetscFunctionBegin; 2907 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2908 PetscValidType(mat, 1); 2909 mat->factortype = t; 2910 PetscFunctionReturn(PETSC_SUCCESS); 2911 } 2912 2913 /*@C 2914 MatGetInfo - Returns information about matrix storage (number of 2915 nonzeros, memory, etc.). 2916 2917 Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag 2918 2919 Input Parameters: 2920 + mat - the matrix 2921 - flag - flag indicating the type of parameters to be returned (`MAT_LOCAL` - local matrix, `MAT_GLOBAL_MAX` - maximum over all processors, `MAT_GLOBAL_SUM` - sum over all processors) 2922 2923 Output Parameter: 2924 . info - matrix information context 2925 2926 Options Database Key: 2927 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT` 2928 2929 Notes: 2930 The `MatInfo` context contains a variety of matrix data, including 2931 number of nonzeros allocated and used, number of mallocs during 2932 matrix assembly, etc. Additional information for factored matrices 2933 is provided (such as the fill ratio, number of mallocs during 2934 factorization, etc.). 2935 2936 Example: 2937 See the file ${PETSC_DIR}/include/petscmat.h for a complete list of 2938 data within the MatInfo context. For example, 2939 .vb 2940 MatInfo info; 2941 Mat A; 2942 double mal, nz_a, nz_u; 2943 2944 MatGetInfo(A, MAT_LOCAL, &info); 2945 mal = info.mallocs; 2946 nz_a = info.nz_allocated; 2947 .ve 2948 2949 Fortran users should declare info as a double precision 2950 array of dimension `MAT_INFO_SIZE`, and then extract the parameters 2951 of interest. See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h 2952 a complete list of parameter names. 2953 .vb 2954 double precision info(MAT_INFO_SIZE) 2955 double precision mal, nz_a 2956 Mat A 2957 integer ierr 2958 2959 call MatGetInfo(A, MAT_LOCAL, info, ierr) 2960 mal = info(MAT_INFO_MALLOCS) 2961 nz_a = info(MAT_INFO_NZ_ALLOCATED) 2962 .ve 2963 2964 Level: intermediate 2965 2966 Developer Note: 2967 The Fortran interface is not autogenerated as the 2968 interface definition cannot be generated correctly [due to `MatInfo` argument] 2969 2970 .seealso: [](chapter_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()` 2971 @*/ 2972 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info) 2973 { 2974 PetscFunctionBegin; 2975 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2976 PetscValidType(mat, 1); 2977 PetscValidPointer(info, 3); 2978 MatCheckPreallocated(mat, 1); 2979 PetscUseTypeMethod(mat, getinfo, flag, info); 2980 PetscFunctionReturn(PETSC_SUCCESS); 2981 } 2982 2983 /* 2984 This is used by external packages where it is not easy to get the info from the actual 2985 matrix factorization. 2986 */ 2987 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info) 2988 { 2989 PetscFunctionBegin; 2990 PetscCall(PetscMemzero(info, sizeof(MatInfo))); 2991 PetscFunctionReturn(PETSC_SUCCESS); 2992 } 2993 2994 /*@C 2995 MatLUFactor - Performs in-place LU factorization of matrix. 2996 2997 Collective 2998 2999 Input Parameters: 3000 + mat - the matrix 3001 . row - row permutation 3002 . col - column permutation 3003 - info - options for factorization, includes 3004 .vb 3005 fill - expected fill as ratio of original fill. 3006 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3007 Run with the option -info to determine an optimal value to use 3008 .ve 3009 Level: developer 3010 3011 Notes: 3012 Most users should employ the `KSP` interface for linear solvers 3013 instead of working directly with matrix algebra routines such as this. 3014 See, e.g., `KSPCreate()`. 3015 3016 This changes the state of the matrix to a factored matrix; it cannot be used 3017 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3018 3019 This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()` 3020 when not using `KSP`. 3021 3022 Developer Note: 3023 The Fortran interface is not autogenerated as the 3024 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3025 3026 .seealso: [](chapter_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, 3027 `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3028 @*/ 3029 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3030 { 3031 MatFactorInfo tinfo; 3032 3033 PetscFunctionBegin; 3034 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3035 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3036 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3037 if (info) PetscValidPointer(info, 4); 3038 PetscValidType(mat, 1); 3039 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3040 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3041 MatCheckPreallocated(mat, 1); 3042 if (!info) { 3043 PetscCall(MatFactorInfoInitialize(&tinfo)); 3044 info = &tinfo; 3045 } 3046 3047 PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0)); 3048 PetscUseTypeMethod(mat, lufactor, row, col, info); 3049 PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0)); 3050 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3051 PetscFunctionReturn(PETSC_SUCCESS); 3052 } 3053 3054 /*@C 3055 MatILUFactor - Performs in-place ILU factorization of matrix. 3056 3057 Collective 3058 3059 Input Parameters: 3060 + mat - the matrix 3061 . row - row permutation 3062 . col - column permutation 3063 - info - structure containing 3064 .vb 3065 levels - number of levels of fill. 3066 expected fill - as ratio of original fill. 3067 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 3068 missing diagonal entries) 3069 .ve 3070 3071 Level: developer 3072 3073 Notes: 3074 Most users should employ the `KSP` interface for linear solvers 3075 instead of working directly with matrix algebra routines such as this. 3076 See, e.g., `KSPCreate()`. 3077 3078 Probably really in-place only when level of fill is zero, otherwise allocates 3079 new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()` 3080 when not using `KSP`. 3081 3082 Developer Note: 3083 The Fortran interface is not autogenerated as the 3084 interface definition cannot be generated correctly [due to MatFactorInfo] 3085 3086 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 3087 @*/ 3088 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3089 { 3090 PetscFunctionBegin; 3091 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3092 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3093 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3094 PetscValidPointer(info, 4); 3095 PetscValidType(mat, 1); 3096 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 3097 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3098 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3099 MatCheckPreallocated(mat, 1); 3100 3101 PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0)); 3102 PetscUseTypeMethod(mat, ilufactor, row, col, info); 3103 PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0)); 3104 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3105 PetscFunctionReturn(PETSC_SUCCESS); 3106 } 3107 3108 /*@C 3109 MatLUFactorSymbolic - Performs symbolic LU factorization of matrix. 3110 Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`. 3111 3112 Collective 3113 3114 Input Parameters: 3115 + fact - the factor matrix obtained with `MatGetFactor()` 3116 . mat - the matrix 3117 . row - the row permutation 3118 . col - the column permutation 3119 - info - options for factorization, includes 3120 .vb 3121 fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use 3122 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3123 .ve 3124 3125 Level: developer 3126 3127 Notes: 3128 See [Matrix Factorization](sec_matfactor) for additional information about factorizations 3129 3130 Most users should employ the simplified `KSP` interface for linear solvers 3131 instead of working directly with matrix algebra routines such as this. 3132 See, e.g., `KSPCreate()`. 3133 3134 Developer Note: 3135 The Fortran interface is not autogenerated as the 3136 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3137 3138 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3139 @*/ 3140 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 3141 { 3142 MatFactorInfo tinfo; 3143 3144 PetscFunctionBegin; 3145 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3146 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3147 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 3148 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 3149 if (info) PetscValidPointer(info, 5); 3150 PetscValidType(fact, 1); 3151 PetscValidType(mat, 2); 3152 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3153 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3154 MatCheckPreallocated(mat, 2); 3155 if (!info) { 3156 PetscCall(MatFactorInfoInitialize(&tinfo)); 3157 info = &tinfo; 3158 } 3159 3160 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0)); 3161 PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info); 3162 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0)); 3163 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3164 PetscFunctionReturn(PETSC_SUCCESS); 3165 } 3166 3167 /*@C 3168 MatLUFactorNumeric - Performs numeric LU factorization of a matrix. 3169 Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`. 3170 3171 Collective 3172 3173 Input Parameters: 3174 + fact - the factor matrix obtained with `MatGetFactor()` 3175 . mat - the matrix 3176 - info - options for factorization 3177 3178 Level: developer 3179 3180 Notes: 3181 See `MatLUFactor()` for in-place factorization. See 3182 `MatCholeskyFactorNumeric()` for the symmetric, positive definite case. 3183 3184 Most users should employ the `KSP` interface for linear solvers 3185 instead of working directly with matrix algebra routines such as this. 3186 See, e.g., `KSPCreate()`. 3187 3188 Developer Note: 3189 The Fortran interface is not autogenerated as the 3190 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3191 3192 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()` 3193 @*/ 3194 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3195 { 3196 MatFactorInfo tinfo; 3197 3198 PetscFunctionBegin; 3199 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3200 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3201 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3202 PetscValidType(fact, 1); 3203 PetscValidType(mat, 2); 3204 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3205 PetscCheck(mat->rmap->N == (fact)->rmap->N && mat->cmap->N == (fact)->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Mat fact: global dimensions are different %" PetscInt_FMT " should = %" PetscInt_FMT " %" PetscInt_FMT " should = %" PetscInt_FMT, 3206 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3207 3208 MatCheckPreallocated(mat, 2); 3209 if (!info) { 3210 PetscCall(MatFactorInfoInitialize(&tinfo)); 3211 info = &tinfo; 3212 } 3213 3214 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3215 else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0)); 3216 PetscUseTypeMethod(fact, lufactornumeric, mat, info); 3217 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3218 else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0)); 3219 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3220 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3221 PetscFunctionReturn(PETSC_SUCCESS); 3222 } 3223 3224 /*@C 3225 MatCholeskyFactor - Performs in-place Cholesky factorization of a 3226 symmetric matrix. 3227 3228 Collective 3229 3230 Input Parameters: 3231 + mat - the matrix 3232 . perm - row and column permutations 3233 - f - expected fill as ratio of original fill 3234 3235 Level: developer 3236 3237 Notes: 3238 See `MatLUFactor()` for the nonsymmetric case. See also `MatGetFactor()`, 3239 `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`. 3240 3241 Most users should employ the `KSP` interface for linear solvers 3242 instead of working directly with matrix algebra routines such as this. 3243 See, e.g., `KSPCreate()`. 3244 3245 Developer Note: 3246 The Fortran interface is not autogenerated as the 3247 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3248 3249 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()` 3250 `MatGetOrdering()` 3251 @*/ 3252 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info) 3253 { 3254 MatFactorInfo tinfo; 3255 3256 PetscFunctionBegin; 3257 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3258 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2); 3259 if (info) PetscValidPointer(info, 3); 3260 PetscValidType(mat, 1); 3261 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3262 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3263 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3264 MatCheckPreallocated(mat, 1); 3265 if (!info) { 3266 PetscCall(MatFactorInfoInitialize(&tinfo)); 3267 info = &tinfo; 3268 } 3269 3270 PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0)); 3271 PetscUseTypeMethod(mat, choleskyfactor, perm, info); 3272 PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0)); 3273 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3274 PetscFunctionReturn(PETSC_SUCCESS); 3275 } 3276 3277 /*@C 3278 MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization 3279 of a symmetric matrix. 3280 3281 Collective 3282 3283 Input Parameters: 3284 + fact - the factor matrix obtained with `MatGetFactor()` 3285 . mat - the matrix 3286 . perm - row and column permutations 3287 - info - options for factorization, includes 3288 .vb 3289 fill - expected fill as ratio of original fill. 3290 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3291 Run with the option -info to determine an optimal value to use 3292 .ve 3293 3294 Level: developer 3295 3296 Notes: 3297 See `MatLUFactorSymbolic()` for the nonsymmetric case. See also 3298 `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`. 3299 3300 Most users should employ the `KSP` interface for linear solvers 3301 instead of working directly with matrix algebra routines such as this. 3302 See, e.g., `KSPCreate()`. 3303 3304 Developer Note: 3305 The Fortran interface is not autogenerated as the 3306 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3307 3308 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()` 3309 `MatGetOrdering()` 3310 @*/ 3311 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 3312 { 3313 MatFactorInfo tinfo; 3314 3315 PetscFunctionBegin; 3316 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3317 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3318 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 3319 if (info) PetscValidPointer(info, 4); 3320 PetscValidType(fact, 1); 3321 PetscValidType(mat, 2); 3322 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3323 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3324 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3325 MatCheckPreallocated(mat, 2); 3326 if (!info) { 3327 PetscCall(MatFactorInfoInitialize(&tinfo)); 3328 info = &tinfo; 3329 } 3330 3331 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3332 PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info); 3333 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3334 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3335 PetscFunctionReturn(PETSC_SUCCESS); 3336 } 3337 3338 /*@C 3339 MatCholeskyFactorNumeric - Performs numeric Cholesky factorization 3340 of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and 3341 `MatCholeskyFactorSymbolic()`. 3342 3343 Collective 3344 3345 Input Parameters: 3346 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored 3347 . mat - the initial matrix that is to be factored 3348 - info - options for factorization 3349 3350 Level: developer 3351 3352 Note: 3353 Most users should employ the `KSP` interface for linear solvers 3354 instead of working directly with matrix algebra routines such as this. 3355 See, e.g., `KSPCreate()`. 3356 3357 Developer Note: 3358 The Fortran interface is not autogenerated as the 3359 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3360 3361 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()` 3362 @*/ 3363 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3364 { 3365 MatFactorInfo tinfo; 3366 3367 PetscFunctionBegin; 3368 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3369 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3370 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3371 PetscValidType(fact, 1); 3372 PetscValidType(mat, 2); 3373 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3374 PetscCheck(mat->rmap->N == (fact)->rmap->N && mat->cmap->N == (fact)->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Mat fact: global dim %" PetscInt_FMT " should = %" PetscInt_FMT " %" PetscInt_FMT " should = %" PetscInt_FMT, 3375 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3376 MatCheckPreallocated(mat, 2); 3377 if (!info) { 3378 PetscCall(MatFactorInfoInitialize(&tinfo)); 3379 info = &tinfo; 3380 } 3381 3382 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3383 else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0)); 3384 PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info); 3385 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3386 else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0)); 3387 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3388 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3389 PetscFunctionReturn(PETSC_SUCCESS); 3390 } 3391 3392 /*@ 3393 MatQRFactor - Performs in-place QR factorization of matrix. 3394 3395 Collective 3396 3397 Input Parameters: 3398 + mat - the matrix 3399 . col - column permutation 3400 - info - options for factorization, includes 3401 .vb 3402 fill - expected fill as ratio of original fill. 3403 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3404 Run with the option -info to determine an optimal value to use 3405 .ve 3406 3407 Level: developer 3408 3409 Notes: 3410 Most users should employ the `KSP` interface for linear solvers 3411 instead of working directly with matrix algebra routines such as this. 3412 See, e.g., `KSPCreate()`. 3413 3414 This changes the state of the matrix to a factored matrix; it cannot be used 3415 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3416 3417 Developer Note: 3418 The Fortran interface is not autogenerated as the 3419 interface definition cannot be generated correctly [due to MatFactorInfo] 3420 3421 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`, 3422 `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3423 @*/ 3424 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info) 3425 { 3426 PetscFunctionBegin; 3427 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3428 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2); 3429 if (info) PetscValidPointer(info, 3); 3430 PetscValidType(mat, 1); 3431 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3432 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3433 MatCheckPreallocated(mat, 1); 3434 PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0)); 3435 PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info)); 3436 PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0)); 3437 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3438 PetscFunctionReturn(PETSC_SUCCESS); 3439 } 3440 3441 /*@ 3442 MatQRFactorSymbolic - Performs symbolic QR factorization of matrix. 3443 Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`. 3444 3445 Collective 3446 3447 Input Parameters: 3448 + fact - the factor matrix obtained with `MatGetFactor()` 3449 . mat - the matrix 3450 . col - column permutation 3451 - info - options for factorization, includes 3452 .vb 3453 fill - expected fill as ratio of original fill. 3454 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3455 Run with the option -info to determine an optimal value to use 3456 .ve 3457 3458 Level: developer 3459 3460 Note: 3461 Most users should employ the `KSP` interface for linear solvers 3462 instead of working directly with matrix algebra routines such as this. 3463 See, e.g., `KSPCreate()`. 3464 3465 Developer Note: 3466 The Fortran interface is not autogenerated as the 3467 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3468 3469 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3470 @*/ 3471 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info) 3472 { 3473 MatFactorInfo tinfo; 3474 3475 PetscFunctionBegin; 3476 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3477 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3478 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3479 if (info) PetscValidPointer(info, 4); 3480 PetscValidType(fact, 1); 3481 PetscValidType(mat, 2); 3482 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3483 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3484 MatCheckPreallocated(mat, 2); 3485 if (!info) { 3486 PetscCall(MatFactorInfoInitialize(&tinfo)); 3487 info = &tinfo; 3488 } 3489 3490 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3491 PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info)); 3492 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3493 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3494 PetscFunctionReturn(PETSC_SUCCESS); 3495 } 3496 3497 /*@ 3498 MatQRFactorNumeric - Performs numeric QR factorization of a matrix. 3499 Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`. 3500 3501 Collective 3502 3503 Input Parameters: 3504 + fact - the factor matrix obtained with `MatGetFactor()` 3505 . mat - the matrix 3506 - info - options for factorization 3507 3508 Level: developer 3509 3510 Notes: 3511 See `MatQRFactor()` for in-place factorization. 3512 3513 Most users should employ the `KSP` interface for linear solvers 3514 instead of working directly with matrix algebra routines such as this. 3515 See, e.g., `KSPCreate()`. 3516 3517 Developer Note: 3518 The Fortran interface is not autogenerated as the 3519 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3520 3521 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()` 3522 @*/ 3523 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3524 { 3525 MatFactorInfo tinfo; 3526 3527 PetscFunctionBegin; 3528 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3529 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3530 PetscValidType(fact, 1); 3531 PetscValidType(mat, 2); 3532 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3533 PetscCheck(mat->rmap->N == fact->rmap->N && mat->cmap->N == fact->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Mat fact: global dimensions are different %" PetscInt_FMT " should = %" PetscInt_FMT " %" PetscInt_FMT " should = %" PetscInt_FMT, 3534 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3535 3536 MatCheckPreallocated(mat, 2); 3537 if (!info) { 3538 PetscCall(MatFactorInfoInitialize(&tinfo)); 3539 info = &tinfo; 3540 } 3541 3542 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3543 else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0)); 3544 PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info)); 3545 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3546 else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0)); 3547 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3548 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3549 PetscFunctionReturn(PETSC_SUCCESS); 3550 } 3551 3552 /*@ 3553 MatSolve - Solves A x = b, given a factored matrix. 3554 3555 Neighbor-wise Collective 3556 3557 Input Parameters: 3558 + mat - the factored matrix 3559 - b - the right-hand-side vector 3560 3561 Output Parameter: 3562 . x - the result vector 3563 3564 Level: developer 3565 3566 Notes: 3567 The vectors `b` and `x` cannot be the same. I.e., one cannot 3568 call `MatSolve`(A,x,x). 3569 3570 Most users should employ the `KSP` interface for linear solvers 3571 instead of working directly with matrix algebra routines such as this. 3572 See, e.g., `KSPCreate()`. 3573 3574 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3575 @*/ 3576 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x) 3577 { 3578 PetscFunctionBegin; 3579 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3580 PetscValidType(mat, 1); 3581 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3582 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3583 PetscCheckSameComm(mat, 1, b, 2); 3584 PetscCheckSameComm(mat, 1, x, 3); 3585 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3586 PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N); 3587 PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N); 3588 PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n); 3589 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3590 MatCheckPreallocated(mat, 1); 3591 3592 PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0)); 3593 if (mat->factorerrortype) { 3594 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3595 PetscCall(VecSetInf(x)); 3596 } else PetscUseTypeMethod(mat, solve, b, x); 3597 PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0)); 3598 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3599 PetscFunctionReturn(PETSC_SUCCESS); 3600 } 3601 3602 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans) 3603 { 3604 Vec b, x; 3605 PetscInt N, i; 3606 PetscErrorCode (*f)(Mat, Vec, Vec); 3607 PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE; 3608 3609 PetscFunctionBegin; 3610 if (A->factorerrortype) { 3611 PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype)); 3612 PetscCall(MatSetInf(X)); 3613 PetscFunctionReturn(PETSC_SUCCESS); 3614 } 3615 f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose; 3616 PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 3617 PetscCall(MatBoundToCPU(A, &Abound)); 3618 if (!Abound) { 3619 PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3620 PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3621 } 3622 #if PetscDefined(HAVE_CUDA) 3623 if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B)); 3624 if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X)); 3625 #elif PetscDefined(HAVE_HIP) 3626 if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B)); 3627 if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X)); 3628 #endif 3629 PetscCall(MatGetSize(B, NULL, &N)); 3630 for (i = 0; i < N; i++) { 3631 PetscCall(MatDenseGetColumnVecRead(B, i, &b)); 3632 PetscCall(MatDenseGetColumnVecWrite(X, i, &x)); 3633 PetscCall((*f)(A, b, x)); 3634 PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x)); 3635 PetscCall(MatDenseRestoreColumnVecRead(B, i, &b)); 3636 } 3637 if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B)); 3638 if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X)); 3639 PetscFunctionReturn(PETSC_SUCCESS); 3640 } 3641 3642 /*@ 3643 MatMatSolve - Solves A X = B, given a factored matrix. 3644 3645 Neighbor-wise Collective 3646 3647 Input Parameters: 3648 + A - the factored matrix 3649 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS) 3650 3651 Output Parameter: 3652 . X - the result matrix (dense matrix) 3653 3654 Level: developer 3655 3656 Note: 3657 If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`; 3658 otherwise, `B` and `X` cannot be the same. 3659 3660 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3661 @*/ 3662 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X) 3663 { 3664 PetscFunctionBegin; 3665 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3666 PetscValidType(A, 1); 3667 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3668 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3669 PetscCheckSameComm(A, 1, B, 2); 3670 PetscCheckSameComm(A, 1, X, 3); 3671 PetscCheck(A->cmap->N == X->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat X: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->cmap->N, X->rmap->N); 3672 PetscCheck(A->rmap->N == B->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat B: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->N, B->rmap->N); 3673 PetscCheck(X->cmap->N == B->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Solution matrix must have same number of columns as rhs matrix"); 3674 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3675 MatCheckPreallocated(A, 1); 3676 3677 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3678 if (!A->ops->matsolve) { 3679 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name)); 3680 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE)); 3681 } else PetscUseTypeMethod(A, matsolve, B, X); 3682 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3683 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3684 PetscFunctionReturn(PETSC_SUCCESS); 3685 } 3686 3687 /*@ 3688 MatMatSolveTranspose - Solves A^T X = B, given a factored matrix. 3689 3690 Neighbor-wise Collective 3691 3692 Input Parameters: 3693 + A - the factored matrix 3694 - B - the right-hand-side matrix (`MATDENSE` matrix) 3695 3696 Output Parameter: 3697 . X - the result matrix (dense matrix) 3698 3699 Level: developer 3700 3701 Note: 3702 The matrices `B` and `X` cannot be the same. I.e., one cannot 3703 call `MatMatSolveTranspose`(A,X,X). 3704 3705 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()` 3706 @*/ 3707 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X) 3708 { 3709 PetscFunctionBegin; 3710 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3711 PetscValidType(A, 1); 3712 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3713 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3714 PetscCheckSameComm(A, 1, B, 2); 3715 PetscCheckSameComm(A, 1, X, 3); 3716 PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3717 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); 3718 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); 3719 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); 3720 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"); 3721 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3722 MatCheckPreallocated(A, 1); 3723 3724 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3725 if (!A->ops->matsolvetranspose) { 3726 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name)); 3727 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE)); 3728 } else PetscUseTypeMethod(A, matsolvetranspose, B, X); 3729 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3730 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3731 PetscFunctionReturn(PETSC_SUCCESS); 3732 } 3733 3734 /*@ 3735 MatMatTransposeSolve - Solves A X = B^T, given a factored matrix. 3736 3737 Neighbor-wise Collective 3738 3739 Input Parameters: 3740 + A - the factored matrix 3741 - Bt - the transpose of right-hand-side matrix as a `MATDENSE` 3742 3743 Output Parameter: 3744 . X - the result matrix (dense matrix) 3745 3746 Level: developer 3747 3748 Note: 3749 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 3750 format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`. 3751 3752 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3753 @*/ 3754 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X) 3755 { 3756 PetscFunctionBegin; 3757 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3758 PetscValidType(A, 1); 3759 PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2); 3760 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3761 PetscCheckSameComm(A, 1, Bt, 2); 3762 PetscCheckSameComm(A, 1, X, 3); 3763 3764 PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3765 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); 3766 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); 3767 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"); 3768 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3769 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3770 MatCheckPreallocated(A, 1); 3771 3772 PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0)); 3773 PetscUseTypeMethod(A, mattransposesolve, Bt, X); 3774 PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0)); 3775 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3776 PetscFunctionReturn(PETSC_SUCCESS); 3777 } 3778 3779 /*@ 3780 MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or 3781 U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U, 3782 3783 Neighbor-wise Collective 3784 3785 Input Parameters: 3786 + mat - the factored matrix 3787 - b - the right-hand-side vector 3788 3789 Output Parameter: 3790 . x - the result vector 3791 3792 Level: developer 3793 3794 Notes: 3795 `MatSolve()` should be used for most applications, as it performs 3796 a forward solve followed by a backward solve. 3797 3798 The vectors `b` and `x` cannot be the same, i.e., one cannot 3799 call `MatForwardSolve`(A,x,x). 3800 3801 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3802 the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet. 3803 `MatForwardSolve()` solves U^T*D y = b, and 3804 `MatBackwardSolve()` solves U x = y. 3805 Thus they do not provide a symmetric preconditioner. 3806 3807 .seealso: [](chapter_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatBackwardSolve()` 3808 @*/ 3809 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x) 3810 { 3811 PetscFunctionBegin; 3812 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3813 PetscValidType(mat, 1); 3814 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3815 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3816 PetscCheckSameComm(mat, 1, b, 2); 3817 PetscCheckSameComm(mat, 1, x, 3); 3818 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3819 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); 3820 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); 3821 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); 3822 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3823 MatCheckPreallocated(mat, 1); 3824 3825 PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0)); 3826 PetscUseTypeMethod(mat, forwardsolve, b, x); 3827 PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0)); 3828 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3829 PetscFunctionReturn(PETSC_SUCCESS); 3830 } 3831 3832 /*@ 3833 MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU. 3834 D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U, 3835 3836 Neighbor-wise Collective 3837 3838 Input Parameters: 3839 + mat - the factored matrix 3840 - b - the right-hand-side vector 3841 3842 Output Parameter: 3843 . x - the result vector 3844 3845 Level: developer 3846 3847 Notes: 3848 `MatSolve()` should be used for most applications, as it performs 3849 a forward solve followed by a backward solve. 3850 3851 The vectors `b` and `x` cannot be the same. I.e., one cannot 3852 call `MatBackwardSolve`(A,x,x). 3853 3854 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3855 the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet. 3856 `MatForwardSolve()` solves U^T*D y = b, and 3857 `MatBackwardSolve()` solves U x = y. 3858 Thus they do not provide a symmetric preconditioner. 3859 3860 .seealso: [](chapter_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatForwardSolve()` 3861 @*/ 3862 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x) 3863 { 3864 PetscFunctionBegin; 3865 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3866 PetscValidType(mat, 1); 3867 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3868 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3869 PetscCheckSameComm(mat, 1, b, 2); 3870 PetscCheckSameComm(mat, 1, x, 3); 3871 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3872 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); 3873 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); 3874 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); 3875 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3876 MatCheckPreallocated(mat, 1); 3877 3878 PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0)); 3879 PetscUseTypeMethod(mat, backwardsolve, b, x); 3880 PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0)); 3881 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3882 PetscFunctionReturn(PETSC_SUCCESS); 3883 } 3884 3885 /*@ 3886 MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix. 3887 3888 Neighbor-wise Collective 3889 3890 Input Parameters: 3891 + mat - the factored matrix 3892 . b - the right-hand-side vector 3893 - y - the vector to be added to 3894 3895 Output Parameter: 3896 . x - the result vector 3897 3898 Level: developer 3899 3900 Note: 3901 The vectors `b` and `x` cannot be the same. I.e., one cannot 3902 call `MatSolveAdd`(A,x,y,x). 3903 3904 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3905 @*/ 3906 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x) 3907 { 3908 PetscScalar one = 1.0; 3909 Vec tmp; 3910 3911 PetscFunctionBegin; 3912 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3913 PetscValidType(mat, 1); 3914 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 3915 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3916 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 3917 PetscCheckSameComm(mat, 1, b, 2); 3918 PetscCheckSameComm(mat, 1, y, 3); 3919 PetscCheckSameComm(mat, 1, x, 4); 3920 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3921 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); 3922 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); 3923 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); 3924 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); 3925 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); 3926 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3927 MatCheckPreallocated(mat, 1); 3928 3929 PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y)); 3930 if (mat->factorerrortype) { 3931 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3932 PetscCall(VecSetInf(x)); 3933 } else if (mat->ops->solveadd) { 3934 PetscUseTypeMethod(mat, solveadd, b, y, x); 3935 } else { 3936 /* do the solve then the add manually */ 3937 if (x != y) { 3938 PetscCall(MatSolve(mat, b, x)); 3939 PetscCall(VecAXPY(x, one, y)); 3940 } else { 3941 PetscCall(VecDuplicate(x, &tmp)); 3942 PetscCall(VecCopy(x, tmp)); 3943 PetscCall(MatSolve(mat, b, x)); 3944 PetscCall(VecAXPY(x, one, tmp)); 3945 PetscCall(VecDestroy(&tmp)); 3946 } 3947 } 3948 PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y)); 3949 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3950 PetscFunctionReturn(PETSC_SUCCESS); 3951 } 3952 3953 /*@ 3954 MatSolveTranspose - Solves A' x = b, given a factored matrix. 3955 3956 Neighbor-wise Collective 3957 3958 Input Parameters: 3959 + mat - the factored matrix 3960 - b - the right-hand-side vector 3961 3962 Output Parameter: 3963 . x - the result vector 3964 3965 Level: developer 3966 3967 Notes: 3968 The vectors `b` and `x` cannot be the same. I.e., one cannot 3969 call `MatSolveTranspose`(A,x,x). 3970 3971 Most users should employ the `KSP` interface for linear solvers 3972 instead of working directly with matrix algebra routines such as this. 3973 See, e.g., `KSPCreate()`. 3974 3975 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()` 3976 @*/ 3977 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x) 3978 { 3979 PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose; 3980 3981 PetscFunctionBegin; 3982 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3983 PetscValidType(mat, 1); 3984 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3985 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3986 PetscCheckSameComm(mat, 1, b, 2); 3987 PetscCheckSameComm(mat, 1, x, 3); 3988 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3989 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); 3990 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); 3991 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3992 MatCheckPreallocated(mat, 1); 3993 PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0)); 3994 if (mat->factorerrortype) { 3995 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3996 PetscCall(VecSetInf(x)); 3997 } else { 3998 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name); 3999 PetscCall((*f)(mat, b, x)); 4000 } 4001 PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0)); 4002 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4003 PetscFunctionReturn(PETSC_SUCCESS); 4004 } 4005 4006 /*@ 4007 MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a 4008 factored matrix. 4009 4010 Neighbor-wise Collective 4011 4012 Input Parameters: 4013 + mat - the factored matrix 4014 . b - the right-hand-side vector 4015 - y - the vector to be added to 4016 4017 Output Parameter: 4018 . x - the result vector 4019 4020 Level: developer 4021 4022 Note: 4023 The vectors `b` and `x` cannot be the same. I.e., one cannot 4024 call `MatSolveTransposeAdd`(A,x,y,x). 4025 4026 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()` 4027 @*/ 4028 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x) 4029 { 4030 PetscScalar one = 1.0; 4031 Vec tmp; 4032 PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd; 4033 4034 PetscFunctionBegin; 4035 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4036 PetscValidType(mat, 1); 4037 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4038 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4039 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4040 PetscCheckSameComm(mat, 1, b, 2); 4041 PetscCheckSameComm(mat, 1, y, 3); 4042 PetscCheckSameComm(mat, 1, x, 4); 4043 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4044 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); 4045 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); 4046 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); 4047 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); 4048 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4049 MatCheckPreallocated(mat, 1); 4050 4051 PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y)); 4052 if (mat->factorerrortype) { 4053 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4054 PetscCall(VecSetInf(x)); 4055 } else if (f) { 4056 PetscCall((*f)(mat, b, y, x)); 4057 } else { 4058 /* do the solve then the add manually */ 4059 if (x != y) { 4060 PetscCall(MatSolveTranspose(mat, b, x)); 4061 PetscCall(VecAXPY(x, one, y)); 4062 } else { 4063 PetscCall(VecDuplicate(x, &tmp)); 4064 PetscCall(VecCopy(x, tmp)); 4065 PetscCall(MatSolveTranspose(mat, b, x)); 4066 PetscCall(VecAXPY(x, one, tmp)); 4067 PetscCall(VecDestroy(&tmp)); 4068 } 4069 } 4070 PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y)); 4071 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4072 PetscFunctionReturn(PETSC_SUCCESS); 4073 } 4074 4075 /*@ 4076 MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps. 4077 4078 Neighbor-wise Collective 4079 4080 Input Parameters: 4081 + mat - the matrix 4082 . b - the right hand side 4083 . omega - the relaxation factor 4084 . flag - flag indicating the type of SOR (see below) 4085 . shift - diagonal shift 4086 . its - the number of iterations 4087 - lits - the number of local iterations 4088 4089 Output Parameter: 4090 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess) 4091 4092 SOR Flags: 4093 + `SOR_FORWARD_SWEEP` - forward SOR 4094 . `SOR_BACKWARD_SWEEP` - backward SOR 4095 . `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR) 4096 . `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR 4097 . `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR 4098 . `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR 4099 . `SOR_EISENSTAT` - SOR with Eisenstat trick 4100 . `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies 4101 upper/lower triangular part of matrix to 4102 vector (with omega) 4103 - `SOR_ZERO_INITIAL_GUESS` - zero initial guess 4104 4105 Level: developer 4106 4107 Notes: 4108 `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and 4109 `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings 4110 on each processor. 4111 4112 Application programmers will not generally use `MatSOR()` directly, 4113 but instead will employ the `KSP`/`PC` interface. 4114 4115 For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing 4116 4117 Most users should employ the `KSP` interface for linear solvers 4118 instead of working directly with matrix algebra routines such as this. 4119 See, e.g., `KSPCreate()`. 4120 4121 Vectors `x` and `b` CANNOT be the same 4122 4123 The flags are implemented as bitwise inclusive or operations. 4124 For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`) 4125 to specify a zero initial guess for SSOR. 4126 4127 Developer Note: 4128 We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes 4129 4130 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()` 4131 @*/ 4132 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x) 4133 { 4134 PetscFunctionBegin; 4135 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4136 PetscValidType(mat, 1); 4137 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4138 PetscValidHeaderSpecific(x, VEC_CLASSID, 8); 4139 PetscCheckSameComm(mat, 1, b, 2); 4140 PetscCheckSameComm(mat, 1, x, 8); 4141 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4142 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4143 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); 4144 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); 4145 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); 4146 PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its); 4147 PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits); 4148 PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same"); 4149 4150 MatCheckPreallocated(mat, 1); 4151 PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0)); 4152 PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x); 4153 PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0)); 4154 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4155 PetscFunctionReturn(PETSC_SUCCESS); 4156 } 4157 4158 /* 4159 Default matrix copy routine. 4160 */ 4161 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str) 4162 { 4163 PetscInt i, rstart = 0, rend = 0, nz; 4164 const PetscInt *cwork; 4165 const PetscScalar *vwork; 4166 4167 PetscFunctionBegin; 4168 if (B->assembled) PetscCall(MatZeroEntries(B)); 4169 if (str == SAME_NONZERO_PATTERN) { 4170 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 4171 for (i = rstart; i < rend; i++) { 4172 PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork)); 4173 PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES)); 4174 PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork)); 4175 } 4176 } else { 4177 PetscCall(MatAYPX(B, 0.0, A, str)); 4178 } 4179 PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 4180 PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 4181 PetscFunctionReturn(PETSC_SUCCESS); 4182 } 4183 4184 /*@ 4185 MatCopy - Copies a matrix to another matrix. 4186 4187 Collective 4188 4189 Input Parameters: 4190 + A - the matrix 4191 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN` 4192 4193 Output Parameter: 4194 . B - where the copy is put 4195 4196 Level: intermediate 4197 4198 Notes: 4199 If you use `SAME_NONZERO_PATTERN` then the two matrices must have the same nonzero pattern or the routine will crash. 4200 4201 `MatCopy()` copies the matrix entries of a matrix to another existing 4202 matrix (after first zeroing the second matrix). A related routine is 4203 `MatConvert()`, which first creates a new matrix and then copies the data. 4204 4205 .seealso: [](chapter_matrices), `Mat`, `MatConvert()`, `MatDuplicate()` 4206 @*/ 4207 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str) 4208 { 4209 PetscInt i; 4210 4211 PetscFunctionBegin; 4212 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 4213 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 4214 PetscValidType(A, 1); 4215 PetscValidType(B, 2); 4216 PetscCheckSameComm(A, 1, B, 2); 4217 MatCheckPreallocated(B, 2); 4218 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4219 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4220 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, 4221 A->cmap->N, B->cmap->N); 4222 MatCheckPreallocated(A, 1); 4223 if (A == B) PetscFunctionReturn(PETSC_SUCCESS); 4224 4225 PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0)); 4226 if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str); 4227 else PetscCall(MatCopy_Basic(A, B, str)); 4228 4229 B->stencil.dim = A->stencil.dim; 4230 B->stencil.noc = A->stencil.noc; 4231 for (i = 0; i <= A->stencil.dim; i++) { 4232 B->stencil.dims[i] = A->stencil.dims[i]; 4233 B->stencil.starts[i] = A->stencil.starts[i]; 4234 } 4235 4236 PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0)); 4237 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4238 PetscFunctionReturn(PETSC_SUCCESS); 4239 } 4240 4241 /*@C 4242 MatConvert - Converts a matrix to another matrix, either of the same 4243 or different type. 4244 4245 Collective 4246 4247 Input Parameters: 4248 + mat - the matrix 4249 . newtype - new matrix type. Use `MATSAME` to create a new matrix of the 4250 same type as the original matrix. 4251 - reuse - denotes if the destination matrix is to be created or reused. 4252 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 4253 `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). 4254 4255 Output Parameter: 4256 . M - pointer to place new matrix 4257 4258 Level: intermediate 4259 4260 Notes: 4261 `MatConvert()` first creates a new matrix and then copies the data from 4262 the first matrix. A related routine is `MatCopy()`, which copies the matrix 4263 entries of one matrix to another already existing matrix context. 4264 4265 Cannot be used to convert a sequential matrix to parallel or parallel to sequential, 4266 the MPI communicator of the generated matrix is always the same as the communicator 4267 of the input matrix. 4268 4269 .seealso: [](chapter_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 4270 @*/ 4271 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M) 4272 { 4273 PetscBool sametype, issame, flg; 4274 PetscBool3 issymmetric, ishermitian; 4275 char convname[256], mtype[256]; 4276 Mat B; 4277 4278 PetscFunctionBegin; 4279 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4280 PetscValidType(mat, 1); 4281 PetscValidPointer(M, 4); 4282 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4283 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4284 MatCheckPreallocated(mat, 1); 4285 4286 PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg)); 4287 if (flg) newtype = mtype; 4288 4289 PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype)); 4290 PetscCall(PetscStrcmp(newtype, "same", &issame)); 4291 PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix"); 4292 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"); 4293 4294 if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) { 4295 PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4296 PetscFunctionReturn(PETSC_SUCCESS); 4297 } 4298 4299 /* Cache Mat options because some converters use MatHeaderReplace */ 4300 issymmetric = mat->symmetric; 4301 ishermitian = mat->hermitian; 4302 4303 if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) { 4304 PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4305 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4306 } else { 4307 PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL; 4308 const char *prefix[3] = {"seq", "mpi", ""}; 4309 PetscInt i; 4310 /* 4311 Order of precedence: 4312 0) See if newtype is a superclass of the current matrix. 4313 1) See if a specialized converter is known to the current matrix. 4314 2) See if a specialized converter is known to the desired matrix class. 4315 3) See if a good general converter is registered for the desired class 4316 (as of 6/27/03 only MATMPIADJ falls into this category). 4317 4) See if a good general converter is known for the current matrix. 4318 5) Use a really basic converter. 4319 */ 4320 4321 /* 0) See if newtype is a superclass of the current matrix. 4322 i.e mat is mpiaij and newtype is aij */ 4323 for (i = 0; i < 2; i++) { 4324 PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname))); 4325 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4326 PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg)); 4327 PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg)); 4328 if (flg) { 4329 if (reuse == MAT_INPLACE_MATRIX) { 4330 PetscCall(PetscInfo(mat, "Early return\n")); 4331 PetscFunctionReturn(PETSC_SUCCESS); 4332 } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) { 4333 PetscCall(PetscInfo(mat, "Calling MatDuplicate\n")); 4334 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4335 PetscFunctionReturn(PETSC_SUCCESS); 4336 } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) { 4337 PetscCall(PetscInfo(mat, "Calling MatCopy\n")); 4338 PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN)); 4339 PetscFunctionReturn(PETSC_SUCCESS); 4340 } 4341 } 4342 } 4343 /* 1) See if a specialized converter is known to the current matrix and the desired class */ 4344 for (i = 0; i < 3; i++) { 4345 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4346 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4347 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4348 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4349 PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname))); 4350 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4351 PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv)); 4352 PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv)); 4353 if (conv) goto foundconv; 4354 } 4355 4356 /* 2) See if a specialized converter is known to the desired matrix class. */ 4357 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B)); 4358 PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 4359 PetscCall(MatSetType(B, newtype)); 4360 for (i = 0; i < 3; i++) { 4361 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4362 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4363 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4364 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4365 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4366 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4367 PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv)); 4368 PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv)); 4369 if (conv) { 4370 PetscCall(MatDestroy(&B)); 4371 goto foundconv; 4372 } 4373 } 4374 4375 /* 3) See if a good general converter is registered for the desired class */ 4376 conv = B->ops->convertfrom; 4377 PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv)); 4378 PetscCall(MatDestroy(&B)); 4379 if (conv) goto foundconv; 4380 4381 /* 4) See if a good general converter is known for the current matrix */ 4382 if (mat->ops->convert) conv = mat->ops->convert; 4383 PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv)); 4384 if (conv) goto foundconv; 4385 4386 /* 5) Use a really basic converter. */ 4387 PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n")); 4388 conv = MatConvert_Basic; 4389 4390 foundconv: 4391 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4392 PetscCall((*conv)(mat, newtype, reuse, M)); 4393 if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) { 4394 /* the block sizes must be same if the mappings are copied over */ 4395 (*M)->rmap->bs = mat->rmap->bs; 4396 (*M)->cmap->bs = mat->cmap->bs; 4397 PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping)); 4398 PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping)); 4399 (*M)->rmap->mapping = mat->rmap->mapping; 4400 (*M)->cmap->mapping = mat->cmap->mapping; 4401 } 4402 (*M)->stencil.dim = mat->stencil.dim; 4403 (*M)->stencil.noc = mat->stencil.noc; 4404 for (i = 0; i <= mat->stencil.dim; i++) { 4405 (*M)->stencil.dims[i] = mat->stencil.dims[i]; 4406 (*M)->stencil.starts[i] = mat->stencil.starts[i]; 4407 } 4408 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4409 } 4410 PetscCall(PetscObjectStateIncrease((PetscObject)*M)); 4411 4412 /* Copy Mat options */ 4413 if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE)); 4414 else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE)); 4415 if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE)); 4416 else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE)); 4417 PetscFunctionReturn(PETSC_SUCCESS); 4418 } 4419 4420 /*@C 4421 MatFactorGetSolverType - Returns name of the package providing the factorization routines 4422 4423 Not Collective 4424 4425 Input Parameter: 4426 . mat - the matrix, must be a factored matrix 4427 4428 Output Parameter: 4429 . type - the string name of the package (do not free this string) 4430 4431 Level: intermediate 4432 4433 Fortran Note: 4434 Pass in an empty string and the package name will be copied into it. Make sure the string is long enough. 4435 4436 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()` 4437 @*/ 4438 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type) 4439 { 4440 PetscErrorCode (*conv)(Mat, MatSolverType *); 4441 4442 PetscFunctionBegin; 4443 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4444 PetscValidType(mat, 1); 4445 PetscValidPointer(type, 2); 4446 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 4447 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv)); 4448 if (conv) PetscCall((*conv)(mat, type)); 4449 else *type = MATSOLVERPETSC; 4450 PetscFunctionReturn(PETSC_SUCCESS); 4451 } 4452 4453 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType; 4454 struct _MatSolverTypeForSpecifcType { 4455 MatType mtype; 4456 /* no entry for MAT_FACTOR_NONE */ 4457 PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *); 4458 MatSolverTypeForSpecifcType next; 4459 }; 4460 4461 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder; 4462 struct _MatSolverTypeHolder { 4463 char *name; 4464 MatSolverTypeForSpecifcType handlers; 4465 MatSolverTypeHolder next; 4466 }; 4467 4468 static MatSolverTypeHolder MatSolverTypeHolders = NULL; 4469 4470 /*@C 4471 MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type 4472 4473 Input Parameters: 4474 + package - name of the package, for example petsc or superlu 4475 . mtype - the matrix type that works with this package 4476 . ftype - the type of factorization supported by the package 4477 - createfactor - routine that will create the factored matrix ready to be used 4478 4479 Level: developer 4480 4481 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()` 4482 @*/ 4483 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *)) 4484 { 4485 MatSolverTypeHolder next = MatSolverTypeHolders, prev = NULL; 4486 PetscBool flg; 4487 MatSolverTypeForSpecifcType inext, iprev = NULL; 4488 4489 PetscFunctionBegin; 4490 PetscCall(MatInitializePackage()); 4491 if (!next) { 4492 PetscCall(PetscNew(&MatSolverTypeHolders)); 4493 PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name)); 4494 PetscCall(PetscNew(&MatSolverTypeHolders->handlers)); 4495 PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype)); 4496 MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor; 4497 PetscFunctionReturn(PETSC_SUCCESS); 4498 } 4499 while (next) { 4500 PetscCall(PetscStrcasecmp(package, next->name, &flg)); 4501 if (flg) { 4502 PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers"); 4503 inext = next->handlers; 4504 while (inext) { 4505 PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg)); 4506 if (flg) { 4507 inext->createfactor[(int)ftype - 1] = createfactor; 4508 PetscFunctionReturn(PETSC_SUCCESS); 4509 } 4510 iprev = inext; 4511 inext = inext->next; 4512 } 4513 PetscCall(PetscNew(&iprev->next)); 4514 PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype)); 4515 iprev->next->createfactor[(int)ftype - 1] = createfactor; 4516 PetscFunctionReturn(PETSC_SUCCESS); 4517 } 4518 prev = next; 4519 next = next->next; 4520 } 4521 PetscCall(PetscNew(&prev->next)); 4522 PetscCall(PetscStrallocpy(package, &prev->next->name)); 4523 PetscCall(PetscNew(&prev->next->handlers)); 4524 PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype)); 4525 prev->next->handlers->createfactor[(int)ftype - 1] = createfactor; 4526 PetscFunctionReturn(PETSC_SUCCESS); 4527 } 4528 4529 /*@C 4530 MatSolverTypeGet - Gets the function that creates the factor matrix if it exist 4531 4532 Input Parameters: 4533 + type - name of the package, for example petsc or superlu 4534 . ftype - the type of factorization supported by the type 4535 - mtype - the matrix type that works with this type 4536 4537 Output Parameters: 4538 + foundtype - `PETSC_TRUE` if the type was registered 4539 . foundmtype - `PETSC_TRUE` if the type supports the requested mtype 4540 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found 4541 4542 Level: developer 4543 4544 .seealso: [](chapter_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()` 4545 @*/ 4546 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *)) 4547 { 4548 MatSolverTypeHolder next = MatSolverTypeHolders; 4549 PetscBool flg; 4550 MatSolverTypeForSpecifcType inext; 4551 4552 PetscFunctionBegin; 4553 if (foundtype) *foundtype = PETSC_FALSE; 4554 if (foundmtype) *foundmtype = PETSC_FALSE; 4555 if (createfactor) *createfactor = NULL; 4556 4557 if (type) { 4558 while (next) { 4559 PetscCall(PetscStrcasecmp(type, next->name, &flg)); 4560 if (flg) { 4561 if (foundtype) *foundtype = PETSC_TRUE; 4562 inext = next->handlers; 4563 while (inext) { 4564 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4565 if (flg) { 4566 if (foundmtype) *foundmtype = PETSC_TRUE; 4567 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4568 PetscFunctionReturn(PETSC_SUCCESS); 4569 } 4570 inext = inext->next; 4571 } 4572 } 4573 next = next->next; 4574 } 4575 } else { 4576 while (next) { 4577 inext = next->handlers; 4578 while (inext) { 4579 PetscCall(PetscStrcmp(mtype, inext->mtype, &flg)); 4580 if (flg && inext->createfactor[(int)ftype - 1]) { 4581 if (foundtype) *foundtype = PETSC_TRUE; 4582 if (foundmtype) *foundmtype = PETSC_TRUE; 4583 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4584 PetscFunctionReturn(PETSC_SUCCESS); 4585 } 4586 inext = inext->next; 4587 } 4588 next = next->next; 4589 } 4590 /* try with base classes inext->mtype */ 4591 next = MatSolverTypeHolders; 4592 while (next) { 4593 inext = next->handlers; 4594 while (inext) { 4595 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4596 if (flg && inext->createfactor[(int)ftype - 1]) { 4597 if (foundtype) *foundtype = PETSC_TRUE; 4598 if (foundmtype) *foundmtype = PETSC_TRUE; 4599 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4600 PetscFunctionReturn(PETSC_SUCCESS); 4601 } 4602 inext = inext->next; 4603 } 4604 next = next->next; 4605 } 4606 } 4607 PetscFunctionReturn(PETSC_SUCCESS); 4608 } 4609 4610 PetscErrorCode MatSolverTypeDestroy(void) 4611 { 4612 MatSolverTypeHolder next = MatSolverTypeHolders, prev; 4613 MatSolverTypeForSpecifcType inext, iprev; 4614 4615 PetscFunctionBegin; 4616 while (next) { 4617 PetscCall(PetscFree(next->name)); 4618 inext = next->handlers; 4619 while (inext) { 4620 PetscCall(PetscFree(inext->mtype)); 4621 iprev = inext; 4622 inext = inext->next; 4623 PetscCall(PetscFree(iprev)); 4624 } 4625 prev = next; 4626 next = next->next; 4627 PetscCall(PetscFree(prev)); 4628 } 4629 MatSolverTypeHolders = NULL; 4630 PetscFunctionReturn(PETSC_SUCCESS); 4631 } 4632 4633 /*@C 4634 MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4635 4636 Logically Collective 4637 4638 Input Parameter: 4639 . mat - the matrix 4640 4641 Output Parameter: 4642 . flg - `PETSC_TRUE` if uses the ordering 4643 4644 Level: developer 4645 4646 Note: 4647 Most internal PETSc factorizations use the ordering passed to the factorization routine but external 4648 packages do not, thus we want to skip generating the ordering when it is not needed or used. 4649 4650 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4651 @*/ 4652 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg) 4653 { 4654 PetscFunctionBegin; 4655 *flg = mat->canuseordering; 4656 PetscFunctionReturn(PETSC_SUCCESS); 4657 } 4658 4659 /*@C 4660 MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object 4661 4662 Logically Collective 4663 4664 Input Parameters: 4665 + mat - the matrix obtained with `MatGetFactor()` 4666 - ftype - the factorization type to be used 4667 4668 Output Parameter: 4669 . otype - the preferred ordering type 4670 4671 Level: developer 4672 4673 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4674 @*/ 4675 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype) 4676 { 4677 PetscFunctionBegin; 4678 *otype = mat->preferredordering[ftype]; 4679 PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering"); 4680 PetscFunctionReturn(PETSC_SUCCESS); 4681 } 4682 4683 /*@C 4684 MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic() 4685 4686 Collective 4687 4688 Input Parameters: 4689 + mat - the matrix 4690 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4691 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4692 4693 Output Parameter: 4694 . f - the factor matrix used with MatXXFactorSymbolic() calls. Can be `NULL` in some cases, see notes below. 4695 4696 Options Database Key: 4697 . -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory. 4698 One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices. 4699 4700 Level: intermediate 4701 4702 Notes: 4703 The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization 4704 types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime. 4705 4706 Users usually access the factorization solvers via `KSP` 4707 4708 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4709 such as pastix, superlu, mumps etc. 4710 4711 PETSc must have been ./configure to use the external solver, using the option --download-package 4712 4713 Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption 4714 where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set 4715 call `MatSetOptionsPrefixFactor()` on the originating matrix or `MatSetOptionsPrefix()` on the resulting factor matrix. 4716 4717 Developer Note: 4718 This should actually be called `MatCreateFactor()` since it creates a new factor object 4719 4720 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, 4721 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4722 @*/ 4723 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f) 4724 { 4725 PetscBool foundtype, foundmtype; 4726 PetscErrorCode (*conv)(Mat, MatFactorType, Mat *); 4727 4728 PetscFunctionBegin; 4729 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4730 PetscValidType(mat, 1); 4731 4732 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4733 MatCheckPreallocated(mat, 1); 4734 4735 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv)); 4736 if (!foundtype) { 4737 if (type) { 4738 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], 4739 ((PetscObject)mat)->type_name, type); 4740 } else { 4741 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); 4742 } 4743 } 4744 PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name); 4745 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); 4746 4747 PetscCall((*conv)(mat, ftype, f)); 4748 if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix)); 4749 PetscFunctionReturn(PETSC_SUCCESS); 4750 } 4751 4752 /*@C 4753 MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type 4754 4755 Not Collective 4756 4757 Input Parameters: 4758 + mat - the matrix 4759 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4760 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4761 4762 Output Parameter: 4763 . flg - PETSC_TRUE if the factorization is available 4764 4765 Level: intermediate 4766 4767 Notes: 4768 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4769 such as pastix, superlu, mumps etc. 4770 4771 PETSc must have been ./configure to use the external solver, using the option --download-package 4772 4773 Developer Note: 4774 This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object 4775 4776 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactor()`, `MatSolverTypeRegister()`, 4777 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4778 @*/ 4779 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg) 4780 { 4781 PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *); 4782 4783 PetscFunctionBegin; 4784 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4785 PetscValidType(mat, 1); 4786 PetscValidBoolPointer(flg, 4); 4787 4788 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4789 MatCheckPreallocated(mat, 1); 4790 4791 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv)); 4792 *flg = gconv ? PETSC_TRUE : PETSC_FALSE; 4793 PetscFunctionReturn(PETSC_SUCCESS); 4794 } 4795 4796 /*@ 4797 MatDuplicate - Duplicates a matrix including the non-zero structure. 4798 4799 Collective 4800 4801 Input Parameters: 4802 + mat - the matrix 4803 - op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`. 4804 See the manual page for `MatDuplicateOption()` for an explanation of these options. 4805 4806 Output Parameter: 4807 . M - pointer to place new matrix 4808 4809 Level: intermediate 4810 4811 Notes: 4812 You cannot change the nonzero pattern for the parent or child matrix if you use `MAT_SHARE_NONZERO_PATTERN`. 4813 4814 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. 4815 4816 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 4817 is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated. 4818 User should not use `MatDuplicate()` to create new matrix M if M is intended to be reused as the product of matrix operation. 4819 4820 .seealso: [](chapter_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption` 4821 @*/ 4822 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M) 4823 { 4824 Mat B; 4825 VecType vtype; 4826 PetscInt i; 4827 PetscObject dm, container_h, container_d; 4828 void (*viewf)(void); 4829 4830 PetscFunctionBegin; 4831 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4832 PetscValidType(mat, 1); 4833 PetscValidPointer(M, 3); 4834 PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix"); 4835 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4836 MatCheckPreallocated(mat, 1); 4837 4838 *M = NULL; 4839 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4840 PetscUseTypeMethod(mat, duplicate, op, M); 4841 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4842 B = *M; 4843 4844 PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf)); 4845 if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf)); 4846 PetscCall(MatGetVecType(mat, &vtype)); 4847 PetscCall(MatSetVecType(B, vtype)); 4848 4849 B->stencil.dim = mat->stencil.dim; 4850 B->stencil.noc = mat->stencil.noc; 4851 for (i = 0; i <= mat->stencil.dim; i++) { 4852 B->stencil.dims[i] = mat->stencil.dims[i]; 4853 B->stencil.starts[i] = mat->stencil.starts[i]; 4854 } 4855 4856 B->nooffproczerorows = mat->nooffproczerorows; 4857 B->nooffprocentries = mat->nooffprocentries; 4858 4859 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm)); 4860 if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm)); 4861 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h)); 4862 if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h)); 4863 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d)); 4864 if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d)); 4865 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4866 PetscFunctionReturn(PETSC_SUCCESS); 4867 } 4868 4869 /*@ 4870 MatGetDiagonal - Gets the diagonal of a matrix as a `Vec` 4871 4872 Logically Collective 4873 4874 Input Parameter: 4875 . mat - the matrix 4876 4877 Output Parameter: 4878 . v - the diagonal of the matrix 4879 4880 Level: intermediate 4881 4882 Note: 4883 Currently only correct in parallel for square matrices. 4884 4885 .seealso: [](chapter_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()` 4886 @*/ 4887 PetscErrorCode MatGetDiagonal(Mat mat, Vec v) 4888 { 4889 PetscFunctionBegin; 4890 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4891 PetscValidType(mat, 1); 4892 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4893 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4894 MatCheckPreallocated(mat, 1); 4895 4896 PetscUseTypeMethod(mat, getdiagonal, v); 4897 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4898 PetscFunctionReturn(PETSC_SUCCESS); 4899 } 4900 4901 /*@C 4902 MatGetRowMin - Gets the minimum value (of the real part) of each 4903 row of the matrix 4904 4905 Logically Collective 4906 4907 Input Parameter: 4908 . mat - the matrix 4909 4910 Output Parameters: 4911 + v - the vector for storing the maximums 4912 - idx - the indices of the column found for each row (optional) 4913 4914 Level: intermediate 4915 4916 Note: 4917 The result of this call are the same as if one converted the matrix to dense format 4918 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 4919 4920 This code is only implemented for a couple of matrix formats. 4921 4922 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, 4923 `MatGetRowMax()` 4924 @*/ 4925 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[]) 4926 { 4927 PetscFunctionBegin; 4928 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4929 PetscValidType(mat, 1); 4930 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4931 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4932 4933 if (!mat->cmap->N) { 4934 PetscCall(VecSet(v, PETSC_MAX_REAL)); 4935 if (idx) { 4936 PetscInt i, m = mat->rmap->n; 4937 for (i = 0; i < m; i++) idx[i] = -1; 4938 } 4939 } else { 4940 MatCheckPreallocated(mat, 1); 4941 } 4942 PetscUseTypeMethod(mat, getrowmin, v, idx); 4943 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4944 PetscFunctionReturn(PETSC_SUCCESS); 4945 } 4946 4947 /*@C 4948 MatGetRowMinAbs - Gets the minimum value (in absolute value) of each 4949 row of the matrix 4950 4951 Logically Collective 4952 4953 Input Parameter: 4954 . mat - the matrix 4955 4956 Output Parameters: 4957 + v - the vector for storing the minimums 4958 - idx - the indices of the column found for each row (or `NULL` if not needed) 4959 4960 Level: intermediate 4961 4962 Notes: 4963 if a row is completely empty or has only 0.0 values then the idx[] value for that 4964 row is 0 (the first column). 4965 4966 This code is only implemented for a couple of matrix formats. 4967 4968 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()` 4969 @*/ 4970 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[]) 4971 { 4972 PetscFunctionBegin; 4973 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4974 PetscValidType(mat, 1); 4975 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4976 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4977 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4978 4979 if (!mat->cmap->N) { 4980 PetscCall(VecSet(v, 0.0)); 4981 if (idx) { 4982 PetscInt i, m = mat->rmap->n; 4983 for (i = 0; i < m; i++) idx[i] = -1; 4984 } 4985 } else { 4986 MatCheckPreallocated(mat, 1); 4987 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 4988 PetscUseTypeMethod(mat, getrowminabs, v, idx); 4989 } 4990 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4991 PetscFunctionReturn(PETSC_SUCCESS); 4992 } 4993 4994 /*@C 4995 MatGetRowMax - Gets the maximum value (of the real part) of each 4996 row of the matrix 4997 4998 Logically Collective 4999 5000 Input Parameter: 5001 . mat - the matrix 5002 5003 Output Parameters: 5004 + v - the vector for storing the maximums 5005 - idx - the indices of the column found for each row (optional) 5006 5007 Level: intermediate 5008 5009 Notes: 5010 The result of this call are the same as if one converted the matrix to dense format 5011 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5012 5013 This code is only implemented for a couple of matrix formats. 5014 5015 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5016 @*/ 5017 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[]) 5018 { 5019 PetscFunctionBegin; 5020 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5021 PetscValidType(mat, 1); 5022 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5023 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5024 5025 if (!mat->cmap->N) { 5026 PetscCall(VecSet(v, PETSC_MIN_REAL)); 5027 if (idx) { 5028 PetscInt i, m = mat->rmap->n; 5029 for (i = 0; i < m; i++) idx[i] = -1; 5030 } 5031 } else { 5032 MatCheckPreallocated(mat, 1); 5033 PetscUseTypeMethod(mat, getrowmax, v, idx); 5034 } 5035 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5036 PetscFunctionReturn(PETSC_SUCCESS); 5037 } 5038 5039 /*@C 5040 MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each 5041 row of the matrix 5042 5043 Logically Collective 5044 5045 Input Parameter: 5046 . mat - the matrix 5047 5048 Output Parameters: 5049 + v - the vector for storing the maximums 5050 - idx - the indices of the column found for each row (or `NULL` if not needed) 5051 5052 Level: intermediate 5053 5054 Notes: 5055 if a row is completely empty or has only 0.0 values then the idx[] value for that 5056 row is 0 (the first column). 5057 5058 This code is only implemented for a couple of matrix formats. 5059 5060 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5061 @*/ 5062 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[]) 5063 { 5064 PetscFunctionBegin; 5065 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5066 PetscValidType(mat, 1); 5067 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5068 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5069 5070 if (!mat->cmap->N) { 5071 PetscCall(VecSet(v, 0.0)); 5072 if (idx) { 5073 PetscInt i, m = mat->rmap->n; 5074 for (i = 0; i < m; i++) idx[i] = -1; 5075 } 5076 } else { 5077 MatCheckPreallocated(mat, 1); 5078 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5079 PetscUseTypeMethod(mat, getrowmaxabs, v, idx); 5080 } 5081 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5082 PetscFunctionReturn(PETSC_SUCCESS); 5083 } 5084 5085 /*@ 5086 MatGetRowSum - Gets the sum of each row of the matrix 5087 5088 Logically or Neighborhood Collective 5089 5090 Input Parameter: 5091 . mat - the matrix 5092 5093 Output Parameter: 5094 . v - the vector for storing the sum of rows 5095 5096 Level: intermediate 5097 5098 Notes: 5099 This code is slow since it is not currently specialized for different formats 5100 5101 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()` 5102 @*/ 5103 PetscErrorCode MatGetRowSum(Mat mat, Vec v) 5104 { 5105 Vec ones; 5106 5107 PetscFunctionBegin; 5108 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5109 PetscValidType(mat, 1); 5110 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5111 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5112 MatCheckPreallocated(mat, 1); 5113 PetscCall(MatCreateVecs(mat, &ones, NULL)); 5114 PetscCall(VecSet(ones, 1.)); 5115 PetscCall(MatMult(mat, ones, v)); 5116 PetscCall(VecDestroy(&ones)); 5117 PetscFunctionReturn(PETSC_SUCCESS); 5118 } 5119 5120 /*@ 5121 MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) 5122 when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B) 5123 5124 Collective 5125 5126 Input Parameter: 5127 . mat - the matrix to provide the transpose 5128 5129 Output Parameter: 5130 . 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 5131 5132 Level: advanced 5133 5134 Note: 5135 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 5136 routine allows bypassing that call. 5137 5138 .seealso: [](chapter_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5139 @*/ 5140 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B) 5141 { 5142 PetscContainer rB = NULL; 5143 MatParentState *rb = NULL; 5144 5145 PetscFunctionBegin; 5146 PetscCall(PetscNew(&rb)); 5147 rb->id = ((PetscObject)mat)->id; 5148 rb->state = 0; 5149 PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate)); 5150 PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB)); 5151 PetscCall(PetscContainerSetPointer(rB, rb)); 5152 PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault)); 5153 PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB)); 5154 PetscCall(PetscObjectDereference((PetscObject)rB)); 5155 PetscFunctionReturn(PETSC_SUCCESS); 5156 } 5157 5158 /*@ 5159 MatTranspose - Computes an in-place or out-of-place transpose of a matrix. 5160 5161 Collective 5162 5163 Input Parameters: 5164 + mat - the matrix to transpose 5165 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5166 5167 Output Parameter: 5168 . B - the transpose 5169 5170 Level: intermediate 5171 5172 Notes: 5173 If you use `MAT_INPLACE_MATRIX` then you must pass in &mat for B 5174 5175 `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 5176 transpose, call `MatTransposeSetPrecursor`(mat,B) before calling this routine. 5177 5178 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. 5179 5180 Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed. 5181 5182 If mat is unchanged from the last call this function returns immediately without recomputing the result 5183 5184 If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()` 5185 5186 .seealso: [](chapter_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`, 5187 `MatTransposeSymbolic()`, `MatCreateTranspose()` 5188 @*/ 5189 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B) 5190 { 5191 PetscContainer rB = NULL; 5192 MatParentState *rb = NULL; 5193 5194 PetscFunctionBegin; 5195 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5196 PetscValidType(mat, 1); 5197 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5198 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5199 PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first"); 5200 PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX"); 5201 MatCheckPreallocated(mat, 1); 5202 if (reuse == MAT_REUSE_MATRIX) { 5203 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5204 PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor()."); 5205 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5206 PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5207 if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS); 5208 } 5209 5210 PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0)); 5211 if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) { 5212 PetscUseTypeMethod(mat, transpose, reuse, B); 5213 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5214 } 5215 PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0)); 5216 5217 if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B)); 5218 if (reuse != MAT_INPLACE_MATRIX) { 5219 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5220 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5221 rb->state = ((PetscObject)mat)->state; 5222 rb->nonzerostate = mat->nonzerostate; 5223 } 5224 PetscFunctionReturn(PETSC_SUCCESS); 5225 } 5226 5227 /*@ 5228 MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix. 5229 5230 Collective 5231 5232 Input Parameter: 5233 . A - the matrix to transpose 5234 5235 Output Parameter: 5236 . 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 5237 numerical portion. 5238 5239 Level: intermediate 5240 5241 Note: 5242 This is not supported for many matrix types, use `MatTranspose()` in those cases 5243 5244 .seealso: [](chapter_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5245 @*/ 5246 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B) 5247 { 5248 PetscFunctionBegin; 5249 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5250 PetscValidType(A, 1); 5251 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5252 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5253 PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0)); 5254 PetscUseTypeMethod(A, transposesymbolic, B); 5255 PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0)); 5256 5257 PetscCall(MatTransposeSetPrecursor(A, *B)); 5258 PetscFunctionReturn(PETSC_SUCCESS); 5259 } 5260 5261 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B) 5262 { 5263 PetscContainer rB; 5264 MatParentState *rb; 5265 5266 PetscFunctionBegin; 5267 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5268 PetscValidType(A, 1); 5269 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5270 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5271 PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB)); 5272 PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()"); 5273 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5274 PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5275 PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure"); 5276 PetscFunctionReturn(PETSC_SUCCESS); 5277 } 5278 5279 /*@ 5280 MatIsTranspose - Test whether a matrix is another one's transpose, 5281 or its own, in which case it tests symmetry. 5282 5283 Collective 5284 5285 Input Parameters: 5286 + A - the matrix to test 5287 . B - the matrix to test against, this can equal the first parameter 5288 - tol - tolerance, differences between entries smaller than this are counted as zero 5289 5290 Output Parameter: 5291 . flg - the result 5292 5293 Level: intermediate 5294 5295 Notes: 5296 Only available for `MATAIJ` matrices. 5297 5298 The sequential algorithm has a running time of the order of the number of nonzeros; the parallel 5299 test involves parallel copies of the block-offdiagonal parts of the matrix. 5300 5301 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()` 5302 @*/ 5303 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5304 { 5305 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5306 5307 PetscFunctionBegin; 5308 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5309 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5310 PetscValidBoolPointer(flg, 4); 5311 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f)); 5312 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g)); 5313 *flg = PETSC_FALSE; 5314 if (f && g) { 5315 PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test"); 5316 PetscCall((*f)(A, B, tol, flg)); 5317 } else { 5318 MatType mattype; 5319 5320 PetscCall(MatGetType(f ? B : A, &mattype)); 5321 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype); 5322 } 5323 PetscFunctionReturn(PETSC_SUCCESS); 5324 } 5325 5326 /*@ 5327 MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate. 5328 5329 Collective 5330 5331 Input Parameters: 5332 + mat - the matrix to transpose and complex conjugate 5333 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5334 5335 Output Parameter: 5336 . B - the Hermitian transpose 5337 5338 Level: intermediate 5339 5340 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse` 5341 @*/ 5342 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B) 5343 { 5344 PetscFunctionBegin; 5345 PetscCall(MatTranspose(mat, reuse, B)); 5346 #if defined(PETSC_USE_COMPLEX) 5347 PetscCall(MatConjugate(*B)); 5348 #endif 5349 PetscFunctionReturn(PETSC_SUCCESS); 5350 } 5351 5352 /*@ 5353 MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose, 5354 5355 Collective 5356 5357 Input Parameters: 5358 + A - the matrix to test 5359 . B - the matrix to test against, this can equal the first parameter 5360 - tol - tolerance, differences between entries smaller than this are counted as zero 5361 5362 Output Parameter: 5363 . flg - the result 5364 5365 Level: intermediate 5366 5367 Notes: 5368 Only available for `MATAIJ` matrices. 5369 5370 The sequential algorithm 5371 has a running time of the order of the number of nonzeros; the parallel 5372 test involves parallel copies of the block-offdiagonal parts of the matrix. 5373 5374 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()` 5375 @*/ 5376 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5377 { 5378 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5379 5380 PetscFunctionBegin; 5381 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5382 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5383 PetscValidBoolPointer(flg, 4); 5384 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f)); 5385 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g)); 5386 if (f && g) { 5387 PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test"); 5388 PetscCall((*f)(A, B, tol, flg)); 5389 } 5390 PetscFunctionReturn(PETSC_SUCCESS); 5391 } 5392 5393 /*@ 5394 MatPermute - Creates a new matrix with rows and columns permuted from the 5395 original. 5396 5397 Collective 5398 5399 Input Parameters: 5400 + mat - the matrix to permute 5401 . row - row permutation, each processor supplies only the permutation for its rows 5402 - col - column permutation, each processor supplies only the permutation for its columns 5403 5404 Output Parameter: 5405 . B - the permuted matrix 5406 5407 Level: advanced 5408 5409 Note: 5410 The index sets map from row/col of permuted matrix to row/col of original matrix. 5411 The index sets should be on the same communicator as mat and have the same local sizes. 5412 5413 Developer Note: 5414 If you want to implement `MatPermute()` for a matrix type, and your approach doesn't 5415 exploit the fact that row and col are permutations, consider implementing the 5416 more general `MatCreateSubMatrix()` instead. 5417 5418 .seealso: [](chapter_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()` 5419 @*/ 5420 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B) 5421 { 5422 PetscFunctionBegin; 5423 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5424 PetscValidType(mat, 1); 5425 PetscValidHeaderSpecific(row, IS_CLASSID, 2); 5426 PetscValidHeaderSpecific(col, IS_CLASSID, 3); 5427 PetscValidPointer(B, 4); 5428 PetscCheckSameComm(mat, 1, row, 2); 5429 if (row != col) PetscCheckSameComm(row, 2, col, 3); 5430 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5431 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5432 PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name); 5433 MatCheckPreallocated(mat, 1); 5434 5435 if (mat->ops->permute) { 5436 PetscUseTypeMethod(mat, permute, row, col, B); 5437 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5438 } else { 5439 PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B)); 5440 } 5441 PetscFunctionReturn(PETSC_SUCCESS); 5442 } 5443 5444 /*@ 5445 MatEqual - Compares two matrices. 5446 5447 Collective 5448 5449 Input Parameters: 5450 + A - the first matrix 5451 - B - the second matrix 5452 5453 Output Parameter: 5454 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise. 5455 5456 Level: intermediate 5457 5458 .seealso: [](chapter_matrices), `Mat` 5459 @*/ 5460 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg) 5461 { 5462 PetscFunctionBegin; 5463 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5464 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5465 PetscValidType(A, 1); 5466 PetscValidType(B, 2); 5467 PetscValidBoolPointer(flg, 3); 5468 PetscCheckSameComm(A, 1, B, 2); 5469 MatCheckPreallocated(A, 1); 5470 MatCheckPreallocated(B, 2); 5471 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5472 PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5473 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, 5474 B->cmap->N); 5475 if (A->ops->equal && A->ops->equal == B->ops->equal) { 5476 PetscUseTypeMethod(A, equal, B, flg); 5477 } else { 5478 PetscCall(MatMultEqual(A, B, 10, flg)); 5479 } 5480 PetscFunctionReturn(PETSC_SUCCESS); 5481 } 5482 5483 /*@ 5484 MatDiagonalScale - Scales a matrix on the left and right by diagonal 5485 matrices that are stored as vectors. Either of the two scaling 5486 matrices can be `NULL`. 5487 5488 Collective 5489 5490 Input Parameters: 5491 + mat - the matrix to be scaled 5492 . l - the left scaling vector (or `NULL`) 5493 - r - the right scaling vector (or `NULL`) 5494 5495 Level: intermediate 5496 5497 Note: 5498 `MatDiagonalScale()` computes A = LAR, where 5499 L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector) 5500 The L scales the rows of the matrix, the R scales the columns of the matrix. 5501 5502 .seealso: [](chapter_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()` 5503 @*/ 5504 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r) 5505 { 5506 PetscFunctionBegin; 5507 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5508 PetscValidType(mat, 1); 5509 if (l) { 5510 PetscValidHeaderSpecific(l, VEC_CLASSID, 2); 5511 PetscCheckSameComm(mat, 1, l, 2); 5512 } 5513 if (r) { 5514 PetscValidHeaderSpecific(r, VEC_CLASSID, 3); 5515 PetscCheckSameComm(mat, 1, r, 3); 5516 } 5517 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5518 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5519 MatCheckPreallocated(mat, 1); 5520 if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS); 5521 5522 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5523 PetscUseTypeMethod(mat, diagonalscale, l, r); 5524 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5525 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5526 if (l != r) mat->symmetric = PETSC_BOOL3_FALSE; 5527 PetscFunctionReturn(PETSC_SUCCESS); 5528 } 5529 5530 /*@ 5531 MatScale - Scales all elements of a matrix by a given number. 5532 5533 Logically Collective 5534 5535 Input Parameters: 5536 + mat - the matrix to be scaled 5537 - a - the scaling value 5538 5539 Level: intermediate 5540 5541 .seealso: [](chapter_matrices), `Mat`, `MatDiagonalScale()` 5542 @*/ 5543 PetscErrorCode MatScale(Mat mat, PetscScalar a) 5544 { 5545 PetscFunctionBegin; 5546 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5547 PetscValidType(mat, 1); 5548 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5549 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5550 PetscValidLogicalCollectiveScalar(mat, a, 2); 5551 MatCheckPreallocated(mat, 1); 5552 5553 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5554 if (a != (PetscScalar)1.0) { 5555 PetscUseTypeMethod(mat, scale, a); 5556 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5557 } 5558 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5559 PetscFunctionReturn(PETSC_SUCCESS); 5560 } 5561 5562 /*@ 5563 MatNorm - Calculates various norms of a matrix. 5564 5565 Collective 5566 5567 Input Parameters: 5568 + mat - the matrix 5569 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY` 5570 5571 Output Parameter: 5572 . nrm - the resulting norm 5573 5574 Level: intermediate 5575 5576 .seealso: [](chapter_matrices), `Mat` 5577 @*/ 5578 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm) 5579 { 5580 PetscFunctionBegin; 5581 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5582 PetscValidType(mat, 1); 5583 PetscValidRealPointer(nrm, 3); 5584 5585 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5586 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5587 MatCheckPreallocated(mat, 1); 5588 5589 PetscUseTypeMethod(mat, norm, type, nrm); 5590 PetscFunctionReturn(PETSC_SUCCESS); 5591 } 5592 5593 /* 5594 This variable is used to prevent counting of MatAssemblyBegin() that 5595 are called from within a MatAssemblyEnd(). 5596 */ 5597 static PetscInt MatAssemblyEnd_InUse = 0; 5598 /*@ 5599 MatAssemblyBegin - Begins assembling the matrix. This routine should 5600 be called after completing all calls to `MatSetValues()`. 5601 5602 Collective 5603 5604 Input Parameters: 5605 + mat - the matrix 5606 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5607 5608 Level: beginner 5609 5610 Notes: 5611 `MatSetValues()` generally caches the values that belong to other MPI ranks. The matrix is ready to 5612 use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called. 5613 5614 Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES` 5615 in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before 5616 using the matrix. 5617 5618 ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the 5619 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 5620 a global collective operation requiring all processes that share the matrix. 5621 5622 Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed 5623 out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros 5624 before `MAT_FINAL_ASSEMBLY` so the space is not compressed out. 5625 5626 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()` 5627 @*/ 5628 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type) 5629 { 5630 PetscFunctionBegin; 5631 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5632 PetscValidType(mat, 1); 5633 MatCheckPreallocated(mat, 1); 5634 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?"); 5635 if (mat->assembled) { 5636 mat->was_assembled = PETSC_TRUE; 5637 mat->assembled = PETSC_FALSE; 5638 } 5639 5640 if (!MatAssemblyEnd_InUse) { 5641 PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0)); 5642 PetscTryTypeMethod(mat, assemblybegin, type); 5643 PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0)); 5644 } else PetscTryTypeMethod(mat, assemblybegin, type); 5645 PetscFunctionReturn(PETSC_SUCCESS); 5646 } 5647 5648 /*@ 5649 MatAssembled - Indicates if a matrix has been assembled and is ready for 5650 use; for example, in matrix-vector product. 5651 5652 Not Collective 5653 5654 Input Parameter: 5655 . mat - the matrix 5656 5657 Output Parameter: 5658 . assembled - `PETSC_TRUE` or `PETSC_FALSE` 5659 5660 Level: advanced 5661 5662 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()` 5663 @*/ 5664 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled) 5665 { 5666 PetscFunctionBegin; 5667 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5668 PetscValidBoolPointer(assembled, 2); 5669 *assembled = mat->assembled; 5670 PetscFunctionReturn(PETSC_SUCCESS); 5671 } 5672 5673 /*@ 5674 MatAssemblyEnd - Completes assembling the matrix. This routine should 5675 be called after `MatAssemblyBegin()`. 5676 5677 Collective 5678 5679 Input Parameters: 5680 + mat - the matrix 5681 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5682 5683 Options Database Keys: 5684 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatEndAssembly()` 5685 . -mat_view ::ascii_info_detail - Prints more detailed info 5686 . -mat_view - Prints matrix in ASCII format 5687 . -mat_view ::ascii_matlab - Prints matrix in Matlab format 5688 . -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 5689 . -display <name> - Sets display name (default is host) 5690 . -draw_pause <sec> - Sets number of seconds to pause after display 5691 . -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See [Using MATLAB with PETSc](ch_matlab)) 5692 . -viewer_socket_machine <machine> - Machine to use for socket 5693 . -viewer_socket_port <port> - Port number to use for socket 5694 - -mat_view binary:filename[:append] - Save matrix to file in binary format 5695 5696 Level: beginner 5697 5698 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()` 5699 @*/ 5700 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type) 5701 { 5702 static PetscInt inassm = 0; 5703 PetscBool flg = PETSC_FALSE; 5704 5705 PetscFunctionBegin; 5706 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5707 PetscValidType(mat, 1); 5708 5709 inassm++; 5710 MatAssemblyEnd_InUse++; 5711 if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */ 5712 PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0)); 5713 PetscTryTypeMethod(mat, assemblyend, type); 5714 PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0)); 5715 } else PetscTryTypeMethod(mat, assemblyend, type); 5716 5717 /* Flush assembly is not a true assembly */ 5718 if (type != MAT_FLUSH_ASSEMBLY) { 5719 if (mat->num_ass) { 5720 if (!mat->symmetry_eternal) { 5721 mat->symmetric = PETSC_BOOL3_UNKNOWN; 5722 mat->hermitian = PETSC_BOOL3_UNKNOWN; 5723 } 5724 if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN; 5725 if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN; 5726 } 5727 mat->num_ass++; 5728 mat->assembled = PETSC_TRUE; 5729 mat->ass_nonzerostate = mat->nonzerostate; 5730 } 5731 5732 mat->insertmode = NOT_SET_VALUES; 5733 MatAssemblyEnd_InUse--; 5734 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5735 if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) { 5736 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 5737 5738 if (mat->checksymmetryonassembly) { 5739 PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg)); 5740 if (flg) { 5741 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5742 } else { 5743 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5744 } 5745 } 5746 if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL)); 5747 } 5748 inassm--; 5749 PetscFunctionReturn(PETSC_SUCCESS); 5750 } 5751 5752 /*@ 5753 MatSetOption - Sets a parameter option for a matrix. Some options 5754 may be specific to certain storage formats. Some options 5755 determine how values will be inserted (or added). Sorted, 5756 row-oriented input will generally assemble the fastest. The default 5757 is row-oriented. 5758 5759 Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption` 5760 5761 Input Parameters: 5762 + mat - the matrix 5763 . option - the option, one of those listed below (and possibly others), 5764 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5765 5766 Options Describing Matrix Structure: 5767 + `MAT_SPD` - symmetric positive definite 5768 . `MAT_SYMMETRIC` - symmetric in terms of both structure and value 5769 . `MAT_HERMITIAN` - transpose is the complex conjugation 5770 . `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure 5771 . `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix 5772 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix 5773 - `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix 5774 5775 These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they 5776 do not need to be computed (usually at a high cost) 5777 5778 Options For Use with `MatSetValues()`: 5779 Insert a logically dense subblock, which can be 5780 . `MAT_ROW_ORIENTED` - row-oriented (default) 5781 5782 These options reflect the data you pass in with `MatSetValues()`; it has 5783 nothing to do with how the data is stored internally in the matrix 5784 data structure. 5785 5786 When (re)assembling a matrix, we can restrict the input for 5787 efficiency/debugging purposes. These options include 5788 + `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow) 5789 . `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated 5790 . `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries 5791 . `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry 5792 . `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly 5793 . `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if 5794 any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves 5795 performance for very large process counts. 5796 - `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset 5797 of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly 5798 functions, instead sending only neighbor messages. 5799 5800 Level: intermediate 5801 5802 Notes: 5803 Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg! 5804 5805 Some options are relevant only for particular matrix types and 5806 are thus ignored by others. Other options are not supported by 5807 certain matrix types and will generate an error message if set. 5808 5809 If using Fortran to compute a matrix, one may need to 5810 use the column-oriented option (or convert to the row-oriented 5811 format). 5812 5813 `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion 5814 that would generate a new entry in the nonzero structure is instead 5815 ignored. Thus, if memory has not already been allocated for this particular 5816 data, then the insertion is ignored. For dense matrices, in which 5817 the entire array is allocated, no entries are ever ignored. 5818 Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction 5819 5820 `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion 5821 that would generate a new entry in the nonzero structure instead produces 5822 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 5823 5824 `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion 5825 that would generate a new entry that has not been preallocated will 5826 instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats 5827 only.) This is a useful flag when debugging matrix memory preallocation. 5828 If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 5829 5830 `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for 5831 other processors should be dropped, rather than stashed. 5832 This is useful if you know that the "owning" processor is also 5833 always generating the correct matrix entries, so that PETSc need 5834 not transfer duplicate entries generated on another processor. 5835 5836 `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the 5837 searches during matrix assembly. When this flag is set, the hash table 5838 is created during the first matrix assembly. This hash table is 5839 used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()` 5840 to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag 5841 should be used with `MAT_USE_HASH_TABLE` flag. This option is currently 5842 supported by `MATMPIBAIJ` format only. 5843 5844 `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries 5845 are kept in the nonzero structure 5846 5847 `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating 5848 a zero location in the matrix 5849 5850 `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types 5851 5852 `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the 5853 zero row routines and thus improves performance for very large process counts. 5854 5855 `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular 5856 part of the matrix (since they should match the upper triangular part). 5857 5858 `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a 5859 single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common 5860 with finite difference schemes with non-periodic boundary conditions. 5861 5862 Developer Note: 5863 `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other 5864 places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRIC` or `MAT_SPD` would need to be changed back 5865 to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had 5866 not changed. 5867 5868 .seealso: [](chapter_matrices), `MatOption`, `Mat`, `MatGetOption()` 5869 @*/ 5870 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg) 5871 { 5872 PetscFunctionBegin; 5873 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5874 if (op > 0) { 5875 PetscValidLogicalCollectiveEnum(mat, op, 2); 5876 PetscValidLogicalCollectiveBool(mat, flg, 3); 5877 } 5878 5879 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); 5880 5881 switch (op) { 5882 case MAT_FORCE_DIAGONAL_ENTRIES: 5883 mat->force_diagonals = flg; 5884 PetscFunctionReturn(PETSC_SUCCESS); 5885 case MAT_NO_OFF_PROC_ENTRIES: 5886 mat->nooffprocentries = flg; 5887 PetscFunctionReturn(PETSC_SUCCESS); 5888 case MAT_SUBSET_OFF_PROC_ENTRIES: 5889 mat->assembly_subset = flg; 5890 if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */ 5891 #if !defined(PETSC_HAVE_MPIUNI) 5892 PetscCall(MatStashScatterDestroy_BTS(&mat->stash)); 5893 #endif 5894 mat->stash.first_assembly_done = PETSC_FALSE; 5895 } 5896 PetscFunctionReturn(PETSC_SUCCESS); 5897 case MAT_NO_OFF_PROC_ZERO_ROWS: 5898 mat->nooffproczerorows = flg; 5899 PetscFunctionReturn(PETSC_SUCCESS); 5900 case MAT_SPD: 5901 if (flg) { 5902 mat->spd = PETSC_BOOL3_TRUE; 5903 mat->symmetric = PETSC_BOOL3_TRUE; 5904 mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5905 } else { 5906 mat->spd = PETSC_BOOL3_FALSE; 5907 } 5908 break; 5909 case MAT_SYMMETRIC: 5910 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5911 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5912 #if !defined(PETSC_USE_COMPLEX) 5913 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5914 #endif 5915 break; 5916 case MAT_HERMITIAN: 5917 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5918 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5919 #if !defined(PETSC_USE_COMPLEX) 5920 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5921 #endif 5922 break; 5923 case MAT_STRUCTURALLY_SYMMETRIC: 5924 mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5925 break; 5926 case MAT_SYMMETRY_ETERNAL: 5927 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"); 5928 mat->symmetry_eternal = flg; 5929 if (flg) mat->structural_symmetry_eternal = PETSC_TRUE; 5930 break; 5931 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 5932 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"); 5933 mat->structural_symmetry_eternal = flg; 5934 break; 5935 case MAT_SPD_ETERNAL: 5936 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"); 5937 mat->spd_eternal = flg; 5938 if (flg) { 5939 mat->structural_symmetry_eternal = PETSC_TRUE; 5940 mat->symmetry_eternal = PETSC_TRUE; 5941 } 5942 break; 5943 case MAT_STRUCTURE_ONLY: 5944 mat->structure_only = flg; 5945 break; 5946 case MAT_SORTED_FULL: 5947 mat->sortedfull = flg; 5948 break; 5949 default: 5950 break; 5951 } 5952 PetscTryTypeMethod(mat, setoption, op, flg); 5953 PetscFunctionReturn(PETSC_SUCCESS); 5954 } 5955 5956 /*@ 5957 MatGetOption - Gets a parameter option that has been set for a matrix. 5958 5959 Logically Collective 5960 5961 Input Parameters: 5962 + mat - the matrix 5963 - option - the option, this only responds to certain options, check the code for which ones 5964 5965 Output Parameter: 5966 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5967 5968 Level: intermediate 5969 5970 Notes: 5971 Can only be called after `MatSetSizes()` and `MatSetType()` have been set. 5972 5973 Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or 5974 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 5975 5976 .seealso: [](chapter_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, 5977 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 5978 @*/ 5979 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg) 5980 { 5981 PetscFunctionBegin; 5982 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5983 PetscValidType(mat, 1); 5984 5985 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); 5986 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()"); 5987 5988 switch (op) { 5989 case MAT_NO_OFF_PROC_ENTRIES: 5990 *flg = mat->nooffprocentries; 5991 break; 5992 case MAT_NO_OFF_PROC_ZERO_ROWS: 5993 *flg = mat->nooffproczerorows; 5994 break; 5995 case MAT_SYMMETRIC: 5996 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()"); 5997 break; 5998 case MAT_HERMITIAN: 5999 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()"); 6000 break; 6001 case MAT_STRUCTURALLY_SYMMETRIC: 6002 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()"); 6003 break; 6004 case MAT_SPD: 6005 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()"); 6006 break; 6007 case MAT_SYMMETRY_ETERNAL: 6008 *flg = mat->symmetry_eternal; 6009 break; 6010 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6011 *flg = mat->symmetry_eternal; 6012 break; 6013 default: 6014 break; 6015 } 6016 PetscFunctionReturn(PETSC_SUCCESS); 6017 } 6018 6019 /*@ 6020 MatZeroEntries - Zeros all entries of a matrix. For sparse matrices 6021 this routine retains the old nonzero structure. 6022 6023 Logically Collective 6024 6025 Input Parameter: 6026 . mat - the matrix 6027 6028 Level: intermediate 6029 6030 Note: 6031 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. 6032 See the Performance chapter of the users manual for information on preallocating matrices. 6033 6034 .seealso: [](chapter_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()` 6035 @*/ 6036 PetscErrorCode MatZeroEntries(Mat mat) 6037 { 6038 PetscFunctionBegin; 6039 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6040 PetscValidType(mat, 1); 6041 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6042 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"); 6043 MatCheckPreallocated(mat, 1); 6044 6045 PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0)); 6046 PetscUseTypeMethod(mat, zeroentries); 6047 PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0)); 6048 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6049 PetscFunctionReturn(PETSC_SUCCESS); 6050 } 6051 6052 /*@ 6053 MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal) 6054 of a set of rows and columns of a matrix. 6055 6056 Collective 6057 6058 Input Parameters: 6059 + mat - the matrix 6060 . numRows - the number of rows/columns to zero 6061 . rows - the global row indices 6062 . diag - value put in the diagonal of the eliminated rows 6063 . x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call 6064 - b - optional vector of the right hand side, that will be adjusted by provided solution entries 6065 6066 Level: intermediate 6067 6068 Notes: 6069 This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6070 6071 For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`. 6072 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 6073 6074 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6075 Krylov method to take advantage of the known solution on the zeroed rows. 6076 6077 For the parallel case, all processes that share the matrix (i.e., 6078 those in the communicator used for matrix creation) MUST call this 6079 routine, regardless of whether any rows being zeroed are owned by 6080 them. 6081 6082 Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix. 6083 6084 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6085 list only rows local to itself). 6086 6087 The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine. 6088 6089 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6090 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6091 @*/ 6092 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6093 { 6094 PetscFunctionBegin; 6095 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6096 PetscValidType(mat, 1); 6097 if (numRows) PetscValidIntPointer(rows, 3); 6098 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6099 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6100 MatCheckPreallocated(mat, 1); 6101 6102 PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b); 6103 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6104 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6105 PetscFunctionReturn(PETSC_SUCCESS); 6106 } 6107 6108 /*@ 6109 MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal) 6110 of a set of rows and columns of a matrix. 6111 6112 Collective 6113 6114 Input Parameters: 6115 + mat - the matrix 6116 . is - the rows to zero 6117 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6118 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6119 - b - optional vector of right hand side, that will be adjusted by provided solution 6120 6121 Level: intermediate 6122 6123 Note: 6124 See `MatZeroRowsColumns()` for details on how this routine operates. 6125 6126 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6127 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()` 6128 @*/ 6129 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6130 { 6131 PetscInt numRows; 6132 const PetscInt *rows; 6133 6134 PetscFunctionBegin; 6135 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6136 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6137 PetscValidType(mat, 1); 6138 PetscValidType(is, 2); 6139 PetscCall(ISGetLocalSize(is, &numRows)); 6140 PetscCall(ISGetIndices(is, &rows)); 6141 PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b)); 6142 PetscCall(ISRestoreIndices(is, &rows)); 6143 PetscFunctionReturn(PETSC_SUCCESS); 6144 } 6145 6146 /*@ 6147 MatZeroRows - Zeros all entries (except possibly the main diagonal) 6148 of a set of rows of a matrix. 6149 6150 Collective 6151 6152 Input Parameters: 6153 + mat - the matrix 6154 . numRows - the number of rows to zero 6155 . rows - the global row indices 6156 . diag - value put in the diagonal of the zeroed rows 6157 . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call 6158 - b - optional vector of right hand side, that will be adjusted by provided solution entries 6159 6160 Level: intermediate 6161 6162 Notes: 6163 This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6164 6165 For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`. 6166 6167 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6168 Krylov method to take advantage of the known solution on the zeroed rows. 6169 6170 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) 6171 from the matrix. 6172 6173 Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix 6174 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 6175 formats this does not alter the nonzero structure. 6176 6177 If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure 6178 of the matrix is not changed the values are 6179 merely zeroed. 6180 6181 The user can set a value in the diagonal entry (or for the `MATAIJ` format 6182 formats can optionally remove the main diagonal entry from the 6183 nonzero structure as well, by passing 0.0 as the final argument). 6184 6185 For the parallel case, all processes that share the matrix (i.e., 6186 those in the communicator used for matrix creation) MUST call this 6187 routine, regardless of whether any rows being zeroed are owned by 6188 them. 6189 6190 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6191 list only rows local to itself). 6192 6193 You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it 6194 owns that are to be zeroed. This saves a global synchronization in the implementation. 6195 6196 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6197 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE` 6198 @*/ 6199 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6200 { 6201 PetscFunctionBegin; 6202 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6203 PetscValidType(mat, 1); 6204 if (numRows) PetscValidIntPointer(rows, 3); 6205 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6206 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6207 MatCheckPreallocated(mat, 1); 6208 6209 PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b); 6210 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6211 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6212 PetscFunctionReturn(PETSC_SUCCESS); 6213 } 6214 6215 /*@ 6216 MatZeroRowsIS - Zeros all entries (except possibly the main diagonal) 6217 of a set of rows of a matrix. 6218 6219 Collective 6220 6221 Input Parameters: 6222 + mat - the matrix 6223 . is - index set of rows to remove (if `NULL` then no row is removed) 6224 . diag - value put in all diagonals of eliminated rows 6225 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6226 - b - optional vector of right hand side, that will be adjusted by provided solution 6227 6228 Level: intermediate 6229 6230 Note: 6231 See `MatZeroRows()` for details on how this routine operates. 6232 6233 .seealso: [](chapter_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6234 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6235 @*/ 6236 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6237 { 6238 PetscInt numRows = 0; 6239 const PetscInt *rows = NULL; 6240 6241 PetscFunctionBegin; 6242 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6243 PetscValidType(mat, 1); 6244 if (is) { 6245 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6246 PetscCall(ISGetLocalSize(is, &numRows)); 6247 PetscCall(ISGetIndices(is, &rows)); 6248 } 6249 PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b)); 6250 if (is) PetscCall(ISRestoreIndices(is, &rows)); 6251 PetscFunctionReturn(PETSC_SUCCESS); 6252 } 6253 6254 /*@ 6255 MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal) 6256 of a set of rows of a matrix. These rows must be local to the process. 6257 6258 Collective 6259 6260 Input Parameters: 6261 + mat - the matrix 6262 . numRows - the number of rows to remove 6263 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6264 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6265 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6266 - b - optional vector of right hand side, that will be adjusted by provided solution 6267 6268 Level: intermediate 6269 6270 Notes: 6271 See `MatZeroRows()` for details on how this routine operates. 6272 6273 The grid coordinates are across the entire grid, not just the local portion 6274 6275 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6276 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6277 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6278 `DM_BOUNDARY_PERIODIC` boundary type. 6279 6280 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 6281 a single value per point) you can skip filling those indices. 6282 6283 Fortran Note: 6284 `idxm` and `idxn` should be declared as 6285 $ MatStencil idxm(4, m) 6286 and the values inserted using 6287 .vb 6288 idxm(MatStencil_i, 1) = i 6289 idxm(MatStencil_j, 1) = j 6290 idxm(MatStencil_k, 1) = k 6291 idxm(MatStencil_c, 1) = c 6292 etc 6293 .ve 6294 6295 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6296 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6297 @*/ 6298 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6299 { 6300 PetscInt dim = mat->stencil.dim; 6301 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6302 PetscInt *dims = mat->stencil.dims + 1; 6303 PetscInt *starts = mat->stencil.starts; 6304 PetscInt *dxm = (PetscInt *)rows; 6305 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6306 6307 PetscFunctionBegin; 6308 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6309 PetscValidType(mat, 1); 6310 if (numRows) PetscValidPointer(rows, 3); 6311 6312 PetscCall(PetscMalloc1(numRows, &jdxm)); 6313 for (i = 0; i < numRows; ++i) { 6314 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6315 for (j = 0; j < 3 - sdim; ++j) dxm++; 6316 /* Local index in X dir */ 6317 tmp = *dxm++ - starts[0]; 6318 /* Loop over remaining dimensions */ 6319 for (j = 0; j < dim - 1; ++j) { 6320 /* If nonlocal, set index to be negative */ 6321 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6322 /* Update local index */ 6323 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6324 } 6325 /* Skip component slot if necessary */ 6326 if (mat->stencil.noc) dxm++; 6327 /* Local row number */ 6328 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6329 } 6330 PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b)); 6331 PetscCall(PetscFree(jdxm)); 6332 PetscFunctionReturn(PETSC_SUCCESS); 6333 } 6334 6335 /*@ 6336 MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal) 6337 of a set of rows and columns of a matrix. 6338 6339 Collective 6340 6341 Input Parameters: 6342 + mat - the matrix 6343 . numRows - the number of rows/columns to remove 6344 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6345 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6346 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6347 - b - optional vector of right hand side, that will be adjusted by provided solution 6348 6349 Level: intermediate 6350 6351 Notes: 6352 See `MatZeroRowsColumns()` for details on how this routine operates. 6353 6354 The grid coordinates are across the entire grid, not just the local portion 6355 6356 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6357 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6358 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6359 `DM_BOUNDARY_PERIODIC` boundary type. 6360 6361 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 6362 a single value per point) you can skip filling those indices. 6363 6364 Fortran Note: 6365 `idxm` and `idxn` should be declared as 6366 $ MatStencil idxm(4, m) 6367 and the values inserted using 6368 .vb 6369 idxm(MatStencil_i, 1) = i 6370 idxm(MatStencil_j, 1) = j 6371 idxm(MatStencil_k, 1) = k 6372 idxm(MatStencil_c, 1) = c 6373 etc 6374 .ve 6375 6376 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6377 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()` 6378 @*/ 6379 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6380 { 6381 PetscInt dim = mat->stencil.dim; 6382 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6383 PetscInt *dims = mat->stencil.dims + 1; 6384 PetscInt *starts = mat->stencil.starts; 6385 PetscInt *dxm = (PetscInt *)rows; 6386 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6387 6388 PetscFunctionBegin; 6389 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6390 PetscValidType(mat, 1); 6391 if (numRows) PetscValidPointer(rows, 3); 6392 6393 PetscCall(PetscMalloc1(numRows, &jdxm)); 6394 for (i = 0; i < numRows; ++i) { 6395 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6396 for (j = 0; j < 3 - sdim; ++j) dxm++; 6397 /* Local index in X dir */ 6398 tmp = *dxm++ - starts[0]; 6399 /* Loop over remaining dimensions */ 6400 for (j = 0; j < dim - 1; ++j) { 6401 /* If nonlocal, set index to be negative */ 6402 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6403 /* Update local index */ 6404 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6405 } 6406 /* Skip component slot if necessary */ 6407 if (mat->stencil.noc) dxm++; 6408 /* Local row number */ 6409 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6410 } 6411 PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b)); 6412 PetscCall(PetscFree(jdxm)); 6413 PetscFunctionReturn(PETSC_SUCCESS); 6414 } 6415 6416 /*@C 6417 MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal) 6418 of a set of rows of a matrix; using local numbering of rows. 6419 6420 Collective 6421 6422 Input Parameters: 6423 + mat - the matrix 6424 . numRows - the number of rows to remove 6425 . rows - the local row indices 6426 . diag - value put in all diagonals of eliminated rows 6427 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6428 - b - optional vector of right hand side, that will be adjusted by provided solution 6429 6430 Level: intermediate 6431 6432 Notes: 6433 Before calling `MatZeroRowsLocal()`, the user must first set the 6434 local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`. 6435 6436 See `MatZeroRows()` for details on how this routine operates. 6437 6438 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`, 6439 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6440 @*/ 6441 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6442 { 6443 PetscFunctionBegin; 6444 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6445 PetscValidType(mat, 1); 6446 if (numRows) PetscValidIntPointer(rows, 3); 6447 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6448 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6449 MatCheckPreallocated(mat, 1); 6450 6451 if (mat->ops->zerorowslocal) { 6452 PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b); 6453 } else { 6454 IS is, newis; 6455 const PetscInt *newRows; 6456 6457 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6458 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6459 PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis)); 6460 PetscCall(ISGetIndices(newis, &newRows)); 6461 PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b); 6462 PetscCall(ISRestoreIndices(newis, &newRows)); 6463 PetscCall(ISDestroy(&newis)); 6464 PetscCall(ISDestroy(&is)); 6465 } 6466 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6467 PetscFunctionReturn(PETSC_SUCCESS); 6468 } 6469 6470 /*@ 6471 MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal) 6472 of a set of rows of a matrix; using local numbering of rows. 6473 6474 Collective 6475 6476 Input Parameters: 6477 + mat - the matrix 6478 . is - index set of rows to remove 6479 . diag - value put in all diagonals of eliminated rows 6480 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6481 - b - optional vector of right hand side, that will be adjusted by provided solution 6482 6483 Level: intermediate 6484 6485 Notes: 6486 Before calling `MatZeroRowsLocalIS()`, the user must first set the 6487 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6488 6489 See `MatZeroRows()` for details on how this routine operates. 6490 6491 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6492 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6493 @*/ 6494 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6495 { 6496 PetscInt numRows; 6497 const PetscInt *rows; 6498 6499 PetscFunctionBegin; 6500 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6501 PetscValidType(mat, 1); 6502 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6503 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6504 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6505 MatCheckPreallocated(mat, 1); 6506 6507 PetscCall(ISGetLocalSize(is, &numRows)); 6508 PetscCall(ISGetIndices(is, &rows)); 6509 PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b)); 6510 PetscCall(ISRestoreIndices(is, &rows)); 6511 PetscFunctionReturn(PETSC_SUCCESS); 6512 } 6513 6514 /*@ 6515 MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal) 6516 of a set of rows and columns of a matrix; using local numbering of rows. 6517 6518 Collective 6519 6520 Input Parameters: 6521 + mat - the matrix 6522 . numRows - the number of rows to remove 6523 . rows - the global row indices 6524 . diag - value put in all diagonals of eliminated rows 6525 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6526 - b - optional vector of right hand side, that will be adjusted by provided solution 6527 6528 Level: intermediate 6529 6530 Notes: 6531 Before calling `MatZeroRowsColumnsLocal()`, the user must first set the 6532 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6533 6534 See `MatZeroRowsColumns()` for details on how this routine operates. 6535 6536 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6537 `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6538 @*/ 6539 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6540 { 6541 IS is, newis; 6542 const PetscInt *newRows; 6543 6544 PetscFunctionBegin; 6545 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6546 PetscValidType(mat, 1); 6547 if (numRows) PetscValidIntPointer(rows, 3); 6548 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6549 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6550 MatCheckPreallocated(mat, 1); 6551 6552 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6553 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6554 PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis)); 6555 PetscCall(ISGetIndices(newis, &newRows)); 6556 PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b); 6557 PetscCall(ISRestoreIndices(newis, &newRows)); 6558 PetscCall(ISDestroy(&newis)); 6559 PetscCall(ISDestroy(&is)); 6560 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6561 PetscFunctionReturn(PETSC_SUCCESS); 6562 } 6563 6564 /*@ 6565 MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal) 6566 of a set of rows and columns of a matrix; using local numbering of rows. 6567 6568 Collective 6569 6570 Input Parameters: 6571 + mat - the matrix 6572 . is - index set of rows to remove 6573 . diag - value put in all diagonals of eliminated rows 6574 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6575 - b - optional vector of right hand side, that will be adjusted by provided solution 6576 6577 Level: intermediate 6578 6579 Notes: 6580 Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the 6581 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6582 6583 See `MatZeroRowsColumns()` for details on how this routine operates. 6584 6585 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6586 `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6587 @*/ 6588 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6589 { 6590 PetscInt numRows; 6591 const PetscInt *rows; 6592 6593 PetscFunctionBegin; 6594 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6595 PetscValidType(mat, 1); 6596 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6597 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6598 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6599 MatCheckPreallocated(mat, 1); 6600 6601 PetscCall(ISGetLocalSize(is, &numRows)); 6602 PetscCall(ISGetIndices(is, &rows)); 6603 PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b)); 6604 PetscCall(ISRestoreIndices(is, &rows)); 6605 PetscFunctionReturn(PETSC_SUCCESS); 6606 } 6607 6608 /*@C 6609 MatGetSize - Returns the numbers of rows and columns in a matrix. 6610 6611 Not Collective 6612 6613 Input Parameter: 6614 . mat - the matrix 6615 6616 Output Parameters: 6617 + m - the number of global rows 6618 - n - the number of global columns 6619 6620 Level: beginner 6621 6622 Note: 6623 Both output parameters can be `NULL` on input. 6624 6625 .seealso: [](chapter_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()` 6626 @*/ 6627 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n) 6628 { 6629 PetscFunctionBegin; 6630 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6631 if (m) *m = mat->rmap->N; 6632 if (n) *n = mat->cmap->N; 6633 PetscFunctionReturn(PETSC_SUCCESS); 6634 } 6635 6636 /*@C 6637 MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns 6638 of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`. 6639 6640 Not Collective 6641 6642 Input Parameter: 6643 . mat - the matrix 6644 6645 Output Parameters: 6646 + m - the number of local rows, use `NULL` to not obtain this value 6647 - n - the number of local columns, use `NULL` to not obtain this value 6648 6649 Level: beginner 6650 6651 .seealso: [](chapter_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()` 6652 @*/ 6653 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n) 6654 { 6655 PetscFunctionBegin; 6656 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6657 if (m) PetscValidIntPointer(m, 2); 6658 if (n) PetscValidIntPointer(n, 3); 6659 if (m) *m = mat->rmap->n; 6660 if (n) *n = mat->cmap->n; 6661 PetscFunctionReturn(PETSC_SUCCESS); 6662 } 6663 6664 /*@C 6665 MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by 6666 this processor. (The columns of the "diagonal block" for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts. 6667 6668 Not Collective, unless matrix has not been allocated, then collective 6669 6670 Input Parameter: 6671 . mat - the matrix 6672 6673 Output Parameters: 6674 + m - the global index of the first local column, use `NULL` to not obtain this value 6675 - n - one more than the global index of the last local column, use `NULL` to not obtain this value 6676 6677 Level: developer 6678 6679 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout` 6680 @*/ 6681 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n) 6682 { 6683 PetscFunctionBegin; 6684 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6685 PetscValidType(mat, 1); 6686 if (m) PetscValidIntPointer(m, 2); 6687 if (n) PetscValidIntPointer(n, 3); 6688 MatCheckPreallocated(mat, 1); 6689 if (m) *m = mat->cmap->rstart; 6690 if (n) *n = mat->cmap->rend; 6691 PetscFunctionReturn(PETSC_SUCCESS); 6692 } 6693 6694 /*@C 6695 MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6696 this MPI rank. For all matrices it returns the range of matrix rows associated with rows of a vector that would contain the result of a matrix 6697 vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts 6698 6699 Not Collective 6700 6701 Input Parameter: 6702 . mat - the matrix 6703 6704 Output Parameters: 6705 + m - the global index of the first local row, use `NULL` to not obtain this value 6706 - n - one more than the global index of the last local row, use `NULL` to not obtain this value 6707 6708 Level: beginner 6709 6710 Note: 6711 This function requires that the matrix be preallocated. If you have not preallocated, consider using 6712 `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N) 6713 and then `MPI_Scan()` to calculate prefix sums of the local sizes. 6714 6715 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, 6716 `PetscLayout` 6717 @*/ 6718 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n) 6719 { 6720 PetscFunctionBegin; 6721 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6722 PetscValidType(mat, 1); 6723 if (m) PetscValidIntPointer(m, 2); 6724 if (n) PetscValidIntPointer(n, 3); 6725 MatCheckPreallocated(mat, 1); 6726 if (m) *m = mat->rmap->rstart; 6727 if (n) *n = mat->rmap->rend; 6728 PetscFunctionReturn(PETSC_SUCCESS); 6729 } 6730 6731 /*@C 6732 MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6733 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 6734 vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts 6735 6736 Not Collective, unless matrix has not been allocated 6737 6738 Input Parameter: 6739 . mat - the matrix 6740 6741 Output Parameter: 6742 . ranges - start of each processors portion plus one more than the total length at the end 6743 6744 Level: beginner 6745 6746 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout` 6747 @*/ 6748 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges) 6749 { 6750 PetscFunctionBegin; 6751 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6752 PetscValidType(mat, 1); 6753 MatCheckPreallocated(mat, 1); 6754 PetscCall(PetscLayoutGetRanges(mat->rmap, ranges)); 6755 PetscFunctionReturn(PETSC_SUCCESS); 6756 } 6757 6758 /*@C 6759 MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by 6760 each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts. 6761 6762 Not Collective, unless matrix has not been allocated 6763 6764 Input Parameter: 6765 . mat - the matrix 6766 6767 Output Parameter: 6768 . ranges - start of each processors portion plus one more then the total length at the end 6769 6770 Level: beginner 6771 6772 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()` 6773 @*/ 6774 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges) 6775 { 6776 PetscFunctionBegin; 6777 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6778 PetscValidType(mat, 1); 6779 MatCheckPreallocated(mat, 1); 6780 PetscCall(PetscLayoutGetRanges(mat->cmap, ranges)); 6781 PetscFunctionReturn(PETSC_SUCCESS); 6782 } 6783 6784 /*@C 6785 MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this 6786 corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership 6787 is more complicated. See :any:`<sec_matlayout>` for details on matrix layouts. 6788 6789 Not Collective 6790 6791 Input Parameter: 6792 . A - matrix 6793 6794 Output Parameters: 6795 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value 6796 - cols - columns in which this process owns elements, use `NULL` to not obtain this value 6797 6798 Level: intermediate 6799 6800 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK`` 6801 @*/ 6802 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols) 6803 { 6804 PetscErrorCode (*f)(Mat, IS *, IS *); 6805 6806 PetscFunctionBegin; 6807 MatCheckPreallocated(A, 1); 6808 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f)); 6809 if (f) { 6810 PetscCall((*f)(A, rows, cols)); 6811 } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */ 6812 if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows)); 6813 if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols)); 6814 } 6815 PetscFunctionReturn(PETSC_SUCCESS); 6816 } 6817 6818 /*@C 6819 MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()` 6820 Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()` 6821 to complete the factorization. 6822 6823 Collective 6824 6825 Input Parameters: 6826 + fact - the factorized matrix obtained with `MatGetFactor()` 6827 . mat - the matrix 6828 . row - row permutation 6829 . col - column permutation 6830 - info - structure containing 6831 .vb 6832 levels - number of levels of fill. 6833 expected fill - as ratio of original fill. 6834 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 6835 missing diagonal entries) 6836 .ve 6837 6838 Level: developer 6839 6840 Notes: 6841 See [Matrix Factorization](sec_matfactor) for additional information. 6842 6843 Most users should employ the `KSP` interface for linear solvers 6844 instead of working directly with matrix algebra routines such as this. 6845 See, e.g., `KSPCreate()`. 6846 6847 Uses the definition of level of fill as in Y. Saad, 2003 6848 6849 Developer Note: 6850 The Fortran interface is not autogenerated as the 6851 interface definition cannot be generated correctly [due to `MatFactorInfo`] 6852 6853 References: 6854 . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003 6855 6856 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 6857 `MatGetOrdering()`, `MatFactorInfo` 6858 @*/ 6859 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 6860 { 6861 PetscFunctionBegin; 6862 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 6863 PetscValidType(mat, 2); 6864 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 6865 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 6866 PetscValidPointer(info, 5); 6867 PetscValidPointer(fact, 1); 6868 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels); 6869 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 6870 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6871 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6872 MatCheckPreallocated(mat, 2); 6873 6874 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0)); 6875 PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info); 6876 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0)); 6877 PetscFunctionReturn(PETSC_SUCCESS); 6878 } 6879 6880 /*@C 6881 MatICCFactorSymbolic - Performs symbolic incomplete 6882 Cholesky factorization for a symmetric matrix. Use 6883 `MatCholeskyFactorNumeric()` to complete the factorization. 6884 6885 Collective 6886 6887 Input Parameters: 6888 + fact - the factorized matrix obtained with `MatGetFactor()` 6889 . mat - the matrix to be factored 6890 . perm - row and column permutation 6891 - info - structure containing 6892 .vb 6893 levels - number of levels of fill. 6894 expected fill - as ratio of original fill. 6895 .ve 6896 6897 Level: developer 6898 6899 Notes: 6900 Most users should employ the `KSP` interface for linear solvers 6901 instead of working directly with matrix algebra routines such as this. 6902 See, e.g., `KSPCreate()`. 6903 6904 This uses the definition of level of fill as in Y. Saad, 2003 6905 6906 Developer Note: 6907 The Fortran interface is not autogenerated as the 6908 interface definition cannot be generated correctly [due to `MatFactorInfo`] 6909 6910 References: 6911 . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003 6912 6913 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 6914 @*/ 6915 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 6916 { 6917 PetscFunctionBegin; 6918 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 6919 PetscValidType(mat, 2); 6920 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 6921 PetscValidPointer(info, 4); 6922 PetscValidPointer(fact, 1); 6923 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6924 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels); 6925 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 6926 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6927 MatCheckPreallocated(mat, 2); 6928 6929 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 6930 PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info); 6931 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 6932 PetscFunctionReturn(PETSC_SUCCESS); 6933 } 6934 6935 /*@C 6936 MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat 6937 points to an array of valid matrices, they may be reused to store the new 6938 submatrices. 6939 6940 Collective 6941 6942 Input Parameters: 6943 + mat - the matrix 6944 . n - the number of submatrixes to be extracted (on this processor, may be zero) 6945 . irow - index set of rows to extract 6946 . icol - index set of columns to extract 6947 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 6948 6949 Output Parameter: 6950 . submat - the array of submatrices 6951 6952 Level: advanced 6953 6954 Notes: 6955 `MatCreateSubMatrices()` can extract ONLY sequential submatrices 6956 (from both sequential and parallel matrices). Use `MatCreateSubMatrix()` 6957 to extract a parallel submatrix. 6958 6959 Some matrix types place restrictions on the row and column 6960 indices, such as that they be sorted or that they be equal to each other. 6961 6962 The index sets may not have duplicate entries. 6963 6964 When extracting submatrices from a parallel matrix, each processor can 6965 form a different submatrix by setting the rows and columns of its 6966 individual index sets according to the local submatrix desired. 6967 6968 When finished using the submatrices, the user should destroy 6969 them with `MatDestroySubMatrices()`. 6970 6971 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 6972 original matrix has not changed from that last call to `MatCreateSubMatrices()`. 6973 6974 This routine creates the matrices in submat; you should NOT create them before 6975 calling it. It also allocates the array of matrix pointers submat. 6976 6977 For `MATBAIJ` matrices the index sets must respect the block structure, that is if they 6978 request one row/column in a block, they must request all rows/columns that are in 6979 that block. For example, if the block size is 2 you cannot request just row 0 and 6980 column 0. 6981 6982 Fortran Note: 6983 The Fortran interface is slightly different from that given below; it 6984 requires one to pass in as `submat` a `Mat` (integer) array of size at least n+1. 6985 6986 .seealso: [](chapter_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 6987 @*/ 6988 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 6989 { 6990 PetscInt i; 6991 PetscBool eq; 6992 6993 PetscFunctionBegin; 6994 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6995 PetscValidType(mat, 1); 6996 if (n) { 6997 PetscValidPointer(irow, 3); 6998 for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3); 6999 PetscValidPointer(icol, 4); 7000 for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4); 7001 } 7002 PetscValidPointer(submat, 6); 7003 if (n && scall == MAT_REUSE_MATRIX) { 7004 PetscValidPointer(*submat, 6); 7005 for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6); 7006 } 7007 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7008 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7009 MatCheckPreallocated(mat, 1); 7010 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7011 PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat); 7012 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7013 for (i = 0; i < n; i++) { 7014 (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */ 7015 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7016 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7017 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 7018 if (mat->boundtocpu && mat->bindingpropagates) { 7019 PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE)); 7020 PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE)); 7021 } 7022 #endif 7023 } 7024 PetscFunctionReturn(PETSC_SUCCESS); 7025 } 7026 7027 /*@C 7028 MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms). 7029 7030 Collective 7031 7032 Input Parameters: 7033 + mat - the matrix 7034 . n - the number of submatrixes to be extracted 7035 . irow - index set of rows to extract 7036 . icol - index set of columns to extract 7037 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7038 7039 Output Parameter: 7040 . submat - the array of submatrices 7041 7042 Level: advanced 7043 7044 Note: 7045 This is used by `PCGASM` 7046 7047 .seealso: [](chapter_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7048 @*/ 7049 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7050 { 7051 PetscInt i; 7052 PetscBool eq; 7053 7054 PetscFunctionBegin; 7055 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7056 PetscValidType(mat, 1); 7057 if (n) { 7058 PetscValidPointer(irow, 3); 7059 PetscValidHeaderSpecific(*irow, IS_CLASSID, 3); 7060 PetscValidPointer(icol, 4); 7061 PetscValidHeaderSpecific(*icol, IS_CLASSID, 4); 7062 } 7063 PetscValidPointer(submat, 6); 7064 if (n && scall == MAT_REUSE_MATRIX) { 7065 PetscValidPointer(*submat, 6); 7066 PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6); 7067 } 7068 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7069 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7070 MatCheckPreallocated(mat, 1); 7071 7072 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7073 PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat); 7074 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7075 for (i = 0; i < n; i++) { 7076 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7077 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7078 } 7079 PetscFunctionReturn(PETSC_SUCCESS); 7080 } 7081 7082 /*@C 7083 MatDestroyMatrices - Destroys an array of matrices. 7084 7085 Collective 7086 7087 Input Parameters: 7088 + n - the number of local matrices 7089 - mat - the matrices (this is a pointer to the array of matrices) 7090 7091 Level: advanced 7092 7093 Note: 7094 Frees not only the matrices, but also the array that contains the matrices 7095 7096 Fortran Note: 7097 This does not free the array. 7098 7099 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()` 7100 @*/ 7101 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[]) 7102 { 7103 PetscInt i; 7104 7105 PetscFunctionBegin; 7106 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7107 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7108 PetscValidPointer(mat, 2); 7109 7110 for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i])); 7111 7112 /* memory is allocated even if n = 0 */ 7113 PetscCall(PetscFree(*mat)); 7114 PetscFunctionReturn(PETSC_SUCCESS); 7115 } 7116 7117 /*@C 7118 MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`. 7119 7120 Collective 7121 7122 Input Parameters: 7123 + n - the number of local matrices 7124 - mat - the matrices (this is a pointer to the array of matrices, just to match the calling 7125 sequence of `MatCreateSubMatrices()`) 7126 7127 Level: advanced 7128 7129 Note: 7130 Frees not only the matrices, but also the array that contains the matrices 7131 7132 Fortran Note: 7133 This does not free the array. 7134 7135 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7136 @*/ 7137 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[]) 7138 { 7139 Mat mat0; 7140 7141 PetscFunctionBegin; 7142 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7143 /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */ 7144 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7145 PetscValidPointer(mat, 2); 7146 7147 mat0 = (*mat)[0]; 7148 if (mat0 && mat0->ops->destroysubmatrices) { 7149 PetscCall((*mat0->ops->destroysubmatrices)(n, mat)); 7150 } else { 7151 PetscCall(MatDestroyMatrices(n, mat)); 7152 } 7153 PetscFunctionReturn(PETSC_SUCCESS); 7154 } 7155 7156 /*@C 7157 MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process 7158 7159 Collective 7160 7161 Input Parameter: 7162 . mat - the matrix 7163 7164 Output Parameter: 7165 . matstruct - the sequential matrix with the nonzero structure of mat 7166 7167 Level: developer 7168 7169 .seealso: [](chapter_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7170 @*/ 7171 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct) 7172 { 7173 PetscFunctionBegin; 7174 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7175 PetscValidPointer(matstruct, 2); 7176 7177 PetscValidType(mat, 1); 7178 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7179 MatCheckPreallocated(mat, 1); 7180 7181 PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7182 PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct); 7183 PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7184 PetscFunctionReturn(PETSC_SUCCESS); 7185 } 7186 7187 /*@C 7188 MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`. 7189 7190 Collective 7191 7192 Input Parameter: 7193 . mat - the matrix (this is a pointer to the array of matrices, just to match the calling 7194 sequence of `MatGetSeqNonzeroStructure()`) 7195 7196 Level: advanced 7197 7198 Note: 7199 Frees not only the matrices, but also the array that contains the matrices 7200 7201 .seealso: [](chapter_matrices), `Mat`, `MatGetSeqNonzeroStructure()` 7202 @*/ 7203 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat) 7204 { 7205 PetscFunctionBegin; 7206 PetscValidPointer(mat, 1); 7207 PetscCall(MatDestroy(mat)); 7208 PetscFunctionReturn(PETSC_SUCCESS); 7209 } 7210 7211 /*@ 7212 MatIncreaseOverlap - Given a set of submatrices indicated by index sets, 7213 replaces the index sets by larger ones that represent submatrices with 7214 additional overlap. 7215 7216 Collective 7217 7218 Input Parameters: 7219 + mat - the matrix 7220 . n - the number of index sets 7221 . is - the array of index sets (these index sets will changed during the call) 7222 - ov - the additional overlap requested 7223 7224 Options Database Key: 7225 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7226 7227 Level: developer 7228 7229 Note: 7230 The computed overlap preserves the matrix block sizes when the blocks are square. 7231 That is: if a matrix nonzero for a given block would increase the overlap all columns associated with 7232 that block are included in the overlap regardless of whether each specific column would increase the overlap. 7233 7234 .seealso: [](chapter_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()` 7235 @*/ 7236 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov) 7237 { 7238 PetscInt i, bs, cbs; 7239 7240 PetscFunctionBegin; 7241 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7242 PetscValidType(mat, 1); 7243 PetscValidLogicalCollectiveInt(mat, n, 2); 7244 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7245 if (n) { 7246 PetscValidPointer(is, 3); 7247 for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3); 7248 } 7249 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7250 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7251 MatCheckPreallocated(mat, 1); 7252 7253 if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS); 7254 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7255 PetscUseTypeMethod(mat, increaseoverlap, n, is, ov); 7256 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7257 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 7258 if (bs == cbs) { 7259 for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs)); 7260 } 7261 PetscFunctionReturn(PETSC_SUCCESS); 7262 } 7263 7264 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt); 7265 7266 /*@ 7267 MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across 7268 a sub communicator, replaces the index sets by larger ones that represent submatrices with 7269 additional overlap. 7270 7271 Collective 7272 7273 Input Parameters: 7274 + mat - the matrix 7275 . n - the number of index sets 7276 . is - the array of index sets (these index sets will changed during the call) 7277 - ov - the additional overlap requested 7278 7279 ` Options Database Key: 7280 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7281 7282 Level: developer 7283 7284 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()` 7285 @*/ 7286 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov) 7287 { 7288 PetscInt i; 7289 7290 PetscFunctionBegin; 7291 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7292 PetscValidType(mat, 1); 7293 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7294 if (n) { 7295 PetscValidPointer(is, 3); 7296 PetscValidHeaderSpecific(*is, IS_CLASSID, 3); 7297 } 7298 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7299 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7300 MatCheckPreallocated(mat, 1); 7301 if (!ov) PetscFunctionReturn(PETSC_SUCCESS); 7302 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7303 for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov)); 7304 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7305 PetscFunctionReturn(PETSC_SUCCESS); 7306 } 7307 7308 /*@ 7309 MatGetBlockSize - Returns the matrix block size. 7310 7311 Not Collective 7312 7313 Input Parameter: 7314 . mat - the matrix 7315 7316 Output Parameter: 7317 . bs - block size 7318 7319 Level: intermediate 7320 7321 Notes: 7322 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7323 7324 If the block size has not been set yet this routine returns 1. 7325 7326 .seealso: [](chapter_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()` 7327 @*/ 7328 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs) 7329 { 7330 PetscFunctionBegin; 7331 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7332 PetscValidIntPointer(bs, 2); 7333 *bs = PetscAbs(mat->rmap->bs); 7334 PetscFunctionReturn(PETSC_SUCCESS); 7335 } 7336 7337 /*@ 7338 MatGetBlockSizes - Returns the matrix block row and column sizes. 7339 7340 Not Collective 7341 7342 Input Parameter: 7343 . mat - the matrix 7344 7345 Output Parameters: 7346 + rbs - row block size 7347 - cbs - column block size 7348 7349 Level: intermediate 7350 7351 Notes: 7352 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7353 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7354 7355 If a block size has not been set yet this routine returns 1. 7356 7357 .seealso: [](chapter_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()` 7358 @*/ 7359 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs) 7360 { 7361 PetscFunctionBegin; 7362 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7363 if (rbs) PetscValidIntPointer(rbs, 2); 7364 if (cbs) PetscValidIntPointer(cbs, 3); 7365 if (rbs) *rbs = PetscAbs(mat->rmap->bs); 7366 if (cbs) *cbs = PetscAbs(mat->cmap->bs); 7367 PetscFunctionReturn(PETSC_SUCCESS); 7368 } 7369 7370 /*@ 7371 MatSetBlockSize - Sets the matrix block size. 7372 7373 Logically Collective 7374 7375 Input Parameters: 7376 + mat - the matrix 7377 - bs - block size 7378 7379 Level: intermediate 7380 7381 Notes: 7382 Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix. 7383 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7384 7385 For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size 7386 is compatible with the matrix local sizes. 7387 7388 .seealso: [](chapter_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()` 7389 @*/ 7390 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs) 7391 { 7392 PetscFunctionBegin; 7393 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7394 PetscValidLogicalCollectiveInt(mat, bs, 2); 7395 PetscCall(MatSetBlockSizes(mat, bs, bs)); 7396 PetscFunctionReturn(PETSC_SUCCESS); 7397 } 7398 7399 typedef struct { 7400 PetscInt n; 7401 IS *is; 7402 Mat *mat; 7403 PetscObjectState nonzerostate; 7404 Mat C; 7405 } EnvelopeData; 7406 7407 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata) 7408 { 7409 for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i])); 7410 PetscCall(PetscFree(edata->is)); 7411 PetscCall(PetscFree(edata)); 7412 return PETSC_SUCCESS; 7413 } 7414 7415 /* 7416 MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores 7417 the sizes of these blocks in the matrix. An individual block may lie over several processes. 7418 7419 Collective 7420 7421 Input Parameter: 7422 . mat - the matrix 7423 7424 Notes: 7425 There can be zeros within the blocks 7426 7427 The blocks can overlap between processes, including laying on more than two processes 7428 7429 .seealso: [](chapter_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()` 7430 */ 7431 static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat) 7432 { 7433 PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend; 7434 PetscInt *diag, *odiag, sc; 7435 VecScatter scatter; 7436 PetscScalar *seqv; 7437 const PetscScalar *parv; 7438 const PetscInt *ia, *ja; 7439 PetscBool set, flag, done; 7440 Mat AA = mat, A; 7441 MPI_Comm comm; 7442 PetscMPIInt rank, size, tag; 7443 MPI_Status status; 7444 PetscContainer container; 7445 EnvelopeData *edata; 7446 Vec seq, par; 7447 IS isglobal; 7448 7449 PetscFunctionBegin; 7450 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7451 PetscCall(MatIsSymmetricKnown(mat, &set, &flag)); 7452 if (!set || !flag) { 7453 /* TOO: only needs nonzero structure of transpose */ 7454 PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA)); 7455 PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN)); 7456 } 7457 PetscCall(MatAIJGetLocalMat(AA, &A)); 7458 PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7459 PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix"); 7460 7461 PetscCall(MatGetLocalSize(mat, &n, NULL)); 7462 PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag)); 7463 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 7464 PetscCallMPI(MPI_Comm_size(comm, &size)); 7465 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7466 7467 PetscCall(PetscMalloc2(n, &sizes, n, &starts)); 7468 7469 if (rank > 0) { 7470 PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7471 PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7472 } 7473 PetscCall(MatGetOwnershipRange(mat, &rstart, NULL)); 7474 for (i = 0; i < n; i++) { 7475 env = PetscMax(env, ja[ia[i + 1] - 1]); 7476 II = rstart + i; 7477 if (env == II) { 7478 starts[lblocks] = tbs; 7479 sizes[lblocks++] = 1 + II - tbs; 7480 tbs = 1 + II; 7481 } 7482 } 7483 if (rank < size - 1) { 7484 PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm)); 7485 PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm)); 7486 } 7487 7488 PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7489 if (!set || !flag) PetscCall(MatDestroy(&AA)); 7490 PetscCall(MatDestroy(&A)); 7491 7492 PetscCall(PetscNew(&edata)); 7493 PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate)); 7494 edata->n = lblocks; 7495 /* create IS needed for extracting blocks from the original matrix */ 7496 PetscCall(PetscMalloc1(lblocks, &edata->is)); 7497 for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i])); 7498 7499 /* Create the resulting inverse matrix structure with preallocation information */ 7500 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C)); 7501 PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 7502 PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat)); 7503 PetscCall(MatSetType(edata->C, MATAIJ)); 7504 7505 /* Communicate the start and end of each row, from each block to the correct rank */ 7506 /* TODO: Use PetscSF instead of VecScatter */ 7507 for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i]; 7508 PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq)); 7509 PetscCall(VecGetArrayWrite(seq, &seqv)); 7510 for (PetscInt i = 0; i < lblocks; i++) { 7511 for (PetscInt j = 0; j < sizes[i]; j++) { 7512 seqv[cnt] = starts[i]; 7513 seqv[cnt + 1] = starts[i] + sizes[i]; 7514 cnt += 2; 7515 } 7516 } 7517 PetscCall(VecRestoreArrayWrite(seq, &seqv)); 7518 PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 7519 sc -= cnt; 7520 PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par)); 7521 PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal)); 7522 PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter)); 7523 PetscCall(ISDestroy(&isglobal)); 7524 PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7525 PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7526 PetscCall(VecScatterDestroy(&scatter)); 7527 PetscCall(VecDestroy(&seq)); 7528 PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend)); 7529 PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag)); 7530 PetscCall(VecGetArrayRead(par, &parv)); 7531 cnt = 0; 7532 PetscCall(MatGetSize(mat, NULL, &n)); 7533 for (PetscInt i = 0; i < mat->rmap->n; i++) { 7534 PetscInt start, end, d = 0, od = 0; 7535 7536 start = (PetscInt)PetscRealPart(parv[cnt]); 7537 end = (PetscInt)PetscRealPart(parv[cnt + 1]); 7538 cnt += 2; 7539 7540 if (start < cstart) { 7541 od += cstart - start + n - cend; 7542 d += cend - cstart; 7543 } else if (start < cend) { 7544 od += n - cend; 7545 d += cend - start; 7546 } else od += n - start; 7547 if (end <= cstart) { 7548 od -= cstart - end + n - cend; 7549 d -= cend - cstart; 7550 } else if (end < cend) { 7551 od -= n - cend; 7552 d -= cend - end; 7553 } else od -= n - end; 7554 7555 odiag[i] = od; 7556 diag[i] = d; 7557 } 7558 PetscCall(VecRestoreArrayRead(par, &parv)); 7559 PetscCall(VecDestroy(&par)); 7560 PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL)); 7561 PetscCall(PetscFree2(diag, odiag)); 7562 PetscCall(PetscFree2(sizes, starts)); 7563 7564 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container)); 7565 PetscCall(PetscContainerSetPointer(container, edata)); 7566 PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy)); 7567 PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container)); 7568 PetscCall(PetscObjectDereference((PetscObject)container)); 7569 PetscFunctionReturn(PETSC_SUCCESS); 7570 } 7571 7572 /*@ 7573 MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A 7574 7575 Collective 7576 7577 Input Parameters: 7578 + A - the matrix 7579 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine 7580 7581 Output Parameter: 7582 . C - matrix with inverted block diagonal of `A` 7583 7584 Level: advanced 7585 7586 Note: 7587 For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal. 7588 7589 .seealso: [](chapter_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()` 7590 @*/ 7591 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C) 7592 { 7593 PetscContainer container; 7594 EnvelopeData *edata; 7595 PetscObjectState nonzerostate; 7596 7597 PetscFunctionBegin; 7598 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7599 if (!container) { 7600 PetscCall(MatComputeVariableBlockEnvelope(A)); 7601 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7602 } 7603 PetscCall(PetscContainerGetPointer(container, (void **)&edata)); 7604 PetscCall(MatGetNonzeroState(A, &nonzerostate)); 7605 PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure"); 7606 PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output"); 7607 7608 PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat)); 7609 *C = edata->C; 7610 7611 for (PetscInt i = 0; i < edata->n; i++) { 7612 Mat D; 7613 PetscScalar *dvalues; 7614 7615 PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D)); 7616 PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE)); 7617 PetscCall(MatSeqDenseInvert(D)); 7618 PetscCall(MatDenseGetArray(D, &dvalues)); 7619 PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES)); 7620 PetscCall(MatDestroy(&D)); 7621 } 7622 PetscCall(MatDestroySubMatrices(edata->n, &edata->mat)); 7623 PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY)); 7624 PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY)); 7625 PetscFunctionReturn(PETSC_SUCCESS); 7626 } 7627 7628 /*@ 7629 MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size 7630 7631 Logically Collective 7632 7633 Input Parameters: 7634 + mat - the matrix 7635 . nblocks - the number of blocks on this process, each block can only exist on a single process 7636 - bsizes - the block sizes 7637 7638 Level: intermediate 7639 7640 Notes: 7641 Currently used by `PCVPBJACOBI` for `MATAIJ` matrices 7642 7643 Each variable point-block set of degrees of freedom must live on a single MPI rank. That is a point block cannot straddle two MPI ranks. 7644 7645 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, 7646 `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI` 7647 @*/ 7648 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes) 7649 { 7650 PetscInt i, ncnt = 0, nlocal; 7651 7652 PetscFunctionBegin; 7653 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7654 PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero"); 7655 PetscCall(MatGetLocalSize(mat, &nlocal, NULL)); 7656 for (i = 0; i < nblocks; i++) ncnt += bsizes[i]; 7657 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); 7658 PetscCall(PetscFree(mat->bsizes)); 7659 mat->nblocks = nblocks; 7660 PetscCall(PetscMalloc1(nblocks, &mat->bsizes)); 7661 PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks)); 7662 PetscFunctionReturn(PETSC_SUCCESS); 7663 } 7664 7665 /*@C 7666 MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size 7667 7668 Logically Collective; No Fortran Support 7669 7670 Input Parameter: 7671 . mat - the matrix 7672 7673 Output Parameters: 7674 + nblocks - the number of blocks on this process 7675 - bsizes - the block sizes 7676 7677 Level: intermediate 7678 7679 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()` 7680 @*/ 7681 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes) 7682 { 7683 PetscFunctionBegin; 7684 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7685 *nblocks = mat->nblocks; 7686 *bsizes = mat->bsizes; 7687 PetscFunctionReturn(PETSC_SUCCESS); 7688 } 7689 7690 /*@ 7691 MatSetBlockSizes - Sets the matrix block row and column sizes. 7692 7693 Logically Collective 7694 7695 Input Parameters: 7696 + mat - the matrix 7697 . rbs - row block size 7698 - cbs - column block size 7699 7700 Level: intermediate 7701 7702 Notes: 7703 Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix. 7704 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7705 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7706 7707 For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes 7708 are compatible with the matrix local sizes. 7709 7710 The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`. 7711 7712 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()` 7713 @*/ 7714 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs) 7715 { 7716 PetscFunctionBegin; 7717 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7718 PetscValidLogicalCollectiveInt(mat, rbs, 2); 7719 PetscValidLogicalCollectiveInt(mat, cbs, 3); 7720 PetscTryTypeMethod(mat, setblocksizes, rbs, cbs); 7721 if (mat->rmap->refcnt) { 7722 ISLocalToGlobalMapping l2g = NULL; 7723 PetscLayout nmap = NULL; 7724 7725 PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap)); 7726 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g)); 7727 PetscCall(PetscLayoutDestroy(&mat->rmap)); 7728 mat->rmap = nmap; 7729 mat->rmap->mapping = l2g; 7730 } 7731 if (mat->cmap->refcnt) { 7732 ISLocalToGlobalMapping l2g = NULL; 7733 PetscLayout nmap = NULL; 7734 7735 PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap)); 7736 if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g)); 7737 PetscCall(PetscLayoutDestroy(&mat->cmap)); 7738 mat->cmap = nmap; 7739 mat->cmap->mapping = l2g; 7740 } 7741 PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs)); 7742 PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs)); 7743 PetscFunctionReturn(PETSC_SUCCESS); 7744 } 7745 7746 /*@ 7747 MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices 7748 7749 Logically Collective 7750 7751 Input Parameters: 7752 + mat - the matrix 7753 . fromRow - matrix from which to copy row block size 7754 - fromCol - matrix from which to copy column block size (can be same as fromRow) 7755 7756 Level: developer 7757 7758 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()` 7759 @*/ 7760 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol) 7761 { 7762 PetscFunctionBegin; 7763 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7764 PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2); 7765 PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3); 7766 if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs)); 7767 if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs)); 7768 PetscFunctionReturn(PETSC_SUCCESS); 7769 } 7770 7771 /*@ 7772 MatResidual - Default routine to calculate the residual r = b - Ax 7773 7774 Collective 7775 7776 Input Parameters: 7777 + mat - the matrix 7778 . b - the right-hand-side 7779 - x - the approximate solution 7780 7781 Output Parameter: 7782 . r - location to store the residual 7783 7784 Level: developer 7785 7786 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()` 7787 @*/ 7788 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r) 7789 { 7790 PetscFunctionBegin; 7791 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7792 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 7793 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 7794 PetscValidHeaderSpecific(r, VEC_CLASSID, 4); 7795 PetscValidType(mat, 1); 7796 MatCheckPreallocated(mat, 1); 7797 PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0)); 7798 if (!mat->ops->residual) { 7799 PetscCall(MatMult(mat, x, r)); 7800 PetscCall(VecAYPX(r, -1.0, b)); 7801 } else { 7802 PetscUseTypeMethod(mat, residual, b, x, r); 7803 } 7804 PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0)); 7805 PetscFunctionReturn(PETSC_SUCCESS); 7806 } 7807 7808 /*MC 7809 MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix 7810 7811 Synopsis: 7812 MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 7813 7814 Not Collective 7815 7816 Input Parameters: 7817 + A - the matrix 7818 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7819 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7820 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7821 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7822 always used. 7823 7824 Output Parameters: 7825 + n - number of local rows in the (possibly compressed) matrix 7826 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 7827 . ja - the column indices 7828 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7829 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7830 7831 Level: developer 7832 7833 Note: 7834 Use `MatRestoreRowIJF90()` when you no longer need access to the data 7835 7836 .seealso: [](chapter_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()` 7837 M*/ 7838 7839 /*MC 7840 MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()` 7841 7842 Synopsis: 7843 MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 7844 7845 Not Collective 7846 7847 Input Parameters: 7848 + A - the matrix 7849 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7850 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7851 inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7852 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7853 always used. 7854 . n - number of local rows in the (possibly compressed) matrix 7855 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 7856 . ja - the column indices 7857 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7858 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7859 7860 Level: developer 7861 7862 .seealso: [](chapter_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()` 7863 M*/ 7864 7865 /*@C 7866 MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix 7867 7868 Collective 7869 7870 Input Parameters: 7871 + mat - the matrix 7872 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7873 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7874 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7875 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7876 always used. 7877 7878 Output Parameters: 7879 + n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed 7880 . 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 7881 . ja - the column indices, use `NULL` if not needed 7882 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7883 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7884 7885 Level: developer 7886 7887 Notes: 7888 You CANNOT change any of the ia[] or ja[] values. 7889 7890 Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values. 7891 7892 Fortran Notes: 7893 Use 7894 .vb 7895 PetscInt, pointer :: ia(:),ja(:) 7896 call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr) 7897 ! Access the ith and jth entries via ia(i) and ja(j) 7898 .ve 7899 `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()` 7900 7901 .seealso: [](chapter_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()` 7902 @*/ 7903 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7904 { 7905 PetscFunctionBegin; 7906 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7907 PetscValidType(mat, 1); 7908 if (n) PetscValidIntPointer(n, 5); 7909 if (ia) PetscValidPointer(ia, 6); 7910 if (ja) PetscValidPointer(ja, 7); 7911 if (done) PetscValidBoolPointer(done, 8); 7912 MatCheckPreallocated(mat, 1); 7913 if (!mat->ops->getrowij && done) *done = PETSC_FALSE; 7914 else { 7915 if (done) *done = PETSC_TRUE; 7916 PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0)); 7917 PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done); 7918 PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0)); 7919 } 7920 PetscFunctionReturn(PETSC_SUCCESS); 7921 } 7922 7923 /*@C 7924 MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices. 7925 7926 Collective 7927 7928 Input Parameters: 7929 + mat - the matrix 7930 . shift - 1 or zero indicating we want the indices starting at 0 or 1 7931 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be 7932 symmetrized 7933 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7934 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7935 always used. 7936 . n - number of columns in the (possibly compressed) matrix 7937 . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix 7938 - ja - the row indices 7939 7940 Output Parameter: 7941 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned 7942 7943 Level: developer 7944 7945 .seealso: [](chapter_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 7946 @*/ 7947 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7948 { 7949 PetscFunctionBegin; 7950 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7951 PetscValidType(mat, 1); 7952 PetscValidIntPointer(n, 5); 7953 if (ia) PetscValidPointer(ia, 6); 7954 if (ja) PetscValidPointer(ja, 7); 7955 PetscValidBoolPointer(done, 8); 7956 MatCheckPreallocated(mat, 1); 7957 if (!mat->ops->getcolumnij) *done = PETSC_FALSE; 7958 else { 7959 *done = PETSC_TRUE; 7960 PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 7961 } 7962 PetscFunctionReturn(PETSC_SUCCESS); 7963 } 7964 7965 /*@C 7966 MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`. 7967 7968 Collective 7969 7970 Input Parameters: 7971 + mat - the matrix 7972 . shift - 1 or zero indicating we want the indices starting at 0 or 1 7973 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7974 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7975 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7976 always used. 7977 . n - size of (possibly compressed) matrix 7978 . ia - the row pointers 7979 - ja - the column indices 7980 7981 Output Parameter: 7982 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 7983 7984 Level: developer 7985 7986 Note: 7987 This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental 7988 us of the array after it has been restored. If you pass `NULL`, it will 7989 not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid. 7990 7991 Fortran Note: 7992 `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()` 7993 7994 .seealso: [](chapter_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()` 7995 @*/ 7996 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7997 { 7998 PetscFunctionBegin; 7999 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8000 PetscValidType(mat, 1); 8001 if (ia) PetscValidPointer(ia, 6); 8002 if (ja) PetscValidPointer(ja, 7); 8003 if (done) PetscValidBoolPointer(done, 8); 8004 MatCheckPreallocated(mat, 1); 8005 8006 if (!mat->ops->restorerowij && done) *done = PETSC_FALSE; 8007 else { 8008 if (done) *done = PETSC_TRUE; 8009 PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8010 if (n) *n = 0; 8011 if (ia) *ia = NULL; 8012 if (ja) *ja = NULL; 8013 } 8014 PetscFunctionReturn(PETSC_SUCCESS); 8015 } 8016 8017 /*@C 8018 MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`. 8019 8020 Collective 8021 8022 Input Parameters: 8023 + mat - the matrix 8024 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8025 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8026 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8027 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8028 always used. 8029 8030 Output Parameters: 8031 + n - size of (possibly compressed) matrix 8032 . ia - the column pointers 8033 . ja - the row indices 8034 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8035 8036 Level: developer 8037 8038 .seealso: [](chapter_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()` 8039 @*/ 8040 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8041 { 8042 PetscFunctionBegin; 8043 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8044 PetscValidType(mat, 1); 8045 if (ia) PetscValidPointer(ia, 6); 8046 if (ja) PetscValidPointer(ja, 7); 8047 PetscValidBoolPointer(done, 8); 8048 MatCheckPreallocated(mat, 1); 8049 8050 if (!mat->ops->restorecolumnij) *done = PETSC_FALSE; 8051 else { 8052 *done = PETSC_TRUE; 8053 PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8054 if (n) *n = 0; 8055 if (ia) *ia = NULL; 8056 if (ja) *ja = NULL; 8057 } 8058 PetscFunctionReturn(PETSC_SUCCESS); 8059 } 8060 8061 /*@C 8062 MatColoringPatch -Used inside matrix coloring routines that use `MatGetRowIJ()` and/or `MatGetColumnIJ()`. 8063 8064 Collective 8065 8066 Input Parameters: 8067 + mat - the matrix 8068 . ncolors - maximum color value 8069 . n - number of entries in colorarray 8070 - colorarray - array indicating color for each column 8071 8072 Output Parameter: 8073 . iscoloring - coloring generated using colorarray information 8074 8075 Level: developer 8076 8077 .seealso: [](chapter_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()` 8078 @*/ 8079 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring) 8080 { 8081 PetscFunctionBegin; 8082 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8083 PetscValidType(mat, 1); 8084 PetscValidIntPointer(colorarray, 4); 8085 PetscValidPointer(iscoloring, 5); 8086 MatCheckPreallocated(mat, 1); 8087 8088 if (!mat->ops->coloringpatch) { 8089 PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring)); 8090 } else { 8091 PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring); 8092 } 8093 PetscFunctionReturn(PETSC_SUCCESS); 8094 } 8095 8096 /*@ 8097 MatSetUnfactored - Resets a factored matrix to be treated as unfactored. 8098 8099 Logically Collective 8100 8101 Input Parameter: 8102 . mat - the factored matrix to be reset 8103 8104 Level: developer 8105 8106 Notes: 8107 This routine should be used only with factored matrices formed by in-place 8108 factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE` 8109 format). This option can save memory, for example, when solving nonlinear 8110 systems with a matrix-free Newton-Krylov method and a matrix-based, in-place 8111 ILU(0) preconditioner. 8112 8113 One can specify in-place ILU(0) factorization by calling 8114 .vb 8115 PCType(pc,PCILU); 8116 PCFactorSeUseInPlace(pc); 8117 .ve 8118 or by using the options -pc_type ilu -pc_factor_in_place 8119 8120 In-place factorization ILU(0) can also be used as a local 8121 solver for the blocks within the block Jacobi or additive Schwarz 8122 methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc 8123 for details on setting local solver options. 8124 8125 Most users should employ the `KSP` interface for linear solvers 8126 instead of working directly with matrix algebra routines such as this. 8127 See, e.g., `KSPCreate()`. 8128 8129 .seealso: [](chapter_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()` 8130 @*/ 8131 PetscErrorCode MatSetUnfactored(Mat mat) 8132 { 8133 PetscFunctionBegin; 8134 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8135 PetscValidType(mat, 1); 8136 MatCheckPreallocated(mat, 1); 8137 mat->factortype = MAT_FACTOR_NONE; 8138 if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS); 8139 PetscUseTypeMethod(mat, setunfactored); 8140 PetscFunctionReturn(PETSC_SUCCESS); 8141 } 8142 8143 /*MC 8144 MatDenseGetArrayF90 - Accesses a matrix array from Fortran 8145 8146 Synopsis: 8147 MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8148 8149 Not Collective 8150 8151 Input Parameter: 8152 . x - matrix 8153 8154 Output Parameters: 8155 + xx_v - the Fortran pointer to the array 8156 - ierr - error code 8157 8158 Example of Usage: 8159 .vb 8160 PetscScalar, pointer xx_v(:,:) 8161 .... 8162 call MatDenseGetArrayF90(x,xx_v,ierr) 8163 a = xx_v(3) 8164 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8165 .ve 8166 8167 Level: advanced 8168 8169 .seealso: [](chapter_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()` 8170 M*/ 8171 8172 /*MC 8173 MatDenseRestoreArrayF90 - Restores a matrix array that has been 8174 accessed with `MatDenseGetArrayF90()`. 8175 8176 Synopsis: 8177 MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8178 8179 Not Collective 8180 8181 Input Parameters: 8182 + x - matrix 8183 - xx_v - the Fortran90 pointer to the array 8184 8185 Output Parameter: 8186 . ierr - error code 8187 8188 Example of Usage: 8189 .vb 8190 PetscScalar, pointer xx_v(:,:) 8191 .... 8192 call MatDenseGetArrayF90(x,xx_v,ierr) 8193 a = xx_v(3) 8194 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8195 .ve 8196 8197 Level: advanced 8198 8199 .seealso: [](chapter_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()` 8200 M*/ 8201 8202 /*MC 8203 MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran. 8204 8205 Synopsis: 8206 MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8207 8208 Not Collective 8209 8210 Input Parameter: 8211 . x - matrix 8212 8213 Output Parameters: 8214 + xx_v - the Fortran pointer to the array 8215 - ierr - error code 8216 8217 Example of Usage: 8218 .vb 8219 PetscScalar, pointer xx_v(:) 8220 .... 8221 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8222 a = xx_v(3) 8223 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8224 .ve 8225 8226 Level: advanced 8227 8228 .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()` 8229 M*/ 8230 8231 /*MC 8232 MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been 8233 accessed with `MatSeqAIJGetArrayF90()`. 8234 8235 Synopsis: 8236 MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8237 8238 Not Collective 8239 8240 Input Parameters: 8241 + x - matrix 8242 - xx_v - the Fortran90 pointer to the array 8243 8244 Output Parameter: 8245 . ierr - error code 8246 8247 Example of Usage: 8248 .vb 8249 PetscScalar, pointer xx_v(:) 8250 .... 8251 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8252 a = xx_v(3) 8253 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8254 .ve 8255 8256 Level: advanced 8257 8258 .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()` 8259 M*/ 8260 8261 /*@ 8262 MatCreateSubMatrix - Gets a single submatrix on the same number of processors 8263 as the original matrix. 8264 8265 Collective 8266 8267 Input Parameters: 8268 + mat - the original matrix 8269 . isrow - parallel `IS` containing the rows this processor should obtain 8270 . 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. 8271 - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 8272 8273 Output Parameter: 8274 . newmat - the new submatrix, of the same type as the original matrix 8275 8276 Level: advanced 8277 8278 Notes: 8279 The submatrix will be able to be multiplied with vectors using the same layout as `iscol`. 8280 8281 Some matrix types place restrictions on the row and column indices, such 8282 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; 8283 for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row. 8284 8285 The index sets may not have duplicate entries. 8286 8287 The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`, 8288 the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls 8289 to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX` 8290 will reuse the matrix generated the first time. You should call `MatDestroy()` on `newmat` when 8291 you are finished using it. 8292 8293 The communicator of the newly obtained matrix is ALWAYS the same as the communicator of 8294 the input matrix. 8295 8296 If `iscol` is `NULL` then all columns are obtained (not supported in Fortran). 8297 8298 Example usage: 8299 Consider the following 8x8 matrix with 34 non-zero values, that is 8300 assembled across 3 processors. Let's assume that proc0 owns 3 rows, 8301 proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 8302 as follows 8303 .vb 8304 1 2 0 | 0 3 0 | 0 4 8305 Proc0 0 5 6 | 7 0 0 | 8 0 8306 9 0 10 | 11 0 0 | 12 0 8307 ------------------------------------- 8308 13 0 14 | 15 16 17 | 0 0 8309 Proc1 0 18 0 | 19 20 21 | 0 0 8310 0 0 0 | 22 23 0 | 24 0 8311 ------------------------------------- 8312 Proc2 25 26 27 | 0 0 28 | 29 0 8313 30 0 0 | 31 32 33 | 0 34 8314 .ve 8315 8316 Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6]. The resulting submatrix is 8317 8318 .vb 8319 2 0 | 0 3 0 | 0 8320 Proc0 5 6 | 7 0 0 | 8 8321 ------------------------------- 8322 Proc1 18 0 | 19 20 21 | 0 8323 ------------------------------- 8324 Proc2 26 27 | 0 0 28 | 29 8325 0 0 | 31 32 33 | 0 8326 .ve 8327 8328 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()` 8329 @*/ 8330 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat) 8331 { 8332 PetscMPIInt size; 8333 Mat *local; 8334 IS iscoltmp; 8335 PetscBool flg; 8336 8337 PetscFunctionBegin; 8338 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8339 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 8340 if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 8341 PetscValidPointer(newmat, 5); 8342 if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5); 8343 PetscValidType(mat, 1); 8344 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8345 PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX"); 8346 8347 MatCheckPreallocated(mat, 1); 8348 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8349 8350 if (!iscol || isrow == iscol) { 8351 PetscBool stride; 8352 PetscMPIInt grabentirematrix = 0, grab; 8353 PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride)); 8354 if (stride) { 8355 PetscInt first, step, n, rstart, rend; 8356 PetscCall(ISStrideGetInfo(isrow, &first, &step)); 8357 if (step == 1) { 8358 PetscCall(MatGetOwnershipRange(mat, &rstart, &rend)); 8359 if (rstart == first) { 8360 PetscCall(ISGetLocalSize(isrow, &n)); 8361 if (n == rend - rstart) grabentirematrix = 1; 8362 } 8363 } 8364 } 8365 PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat))); 8366 if (grab) { 8367 PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n")); 8368 if (cll == MAT_INITIAL_MATRIX) { 8369 *newmat = mat; 8370 PetscCall(PetscObjectReference((PetscObject)mat)); 8371 } 8372 PetscFunctionReturn(PETSC_SUCCESS); 8373 } 8374 } 8375 8376 if (!iscol) { 8377 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp)); 8378 } else { 8379 iscoltmp = iscol; 8380 } 8381 8382 /* if original matrix is on just one processor then use submatrix generated */ 8383 if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) { 8384 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat)); 8385 goto setproperties; 8386 } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) { 8387 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local)); 8388 *newmat = *local; 8389 PetscCall(PetscFree(local)); 8390 goto setproperties; 8391 } else if (!mat->ops->createsubmatrix) { 8392 /* Create a new matrix type that implements the operation using the full matrix */ 8393 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8394 switch (cll) { 8395 case MAT_INITIAL_MATRIX: 8396 PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat)); 8397 break; 8398 case MAT_REUSE_MATRIX: 8399 PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp)); 8400 break; 8401 default: 8402 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX"); 8403 } 8404 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8405 goto setproperties; 8406 } 8407 8408 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8409 PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat); 8410 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8411 8412 setproperties: 8413 PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg)); 8414 if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat)); 8415 if (!iscol) PetscCall(ISDestroy(&iscoltmp)); 8416 if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat)); 8417 PetscFunctionReturn(PETSC_SUCCESS); 8418 } 8419 8420 /*@ 8421 MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix 8422 8423 Not Collective 8424 8425 Input Parameters: 8426 + A - the matrix we wish to propagate options from 8427 - B - the matrix we wish to propagate options to 8428 8429 Level: beginner 8430 8431 Note: 8432 Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL` 8433 8434 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, MatIsStructurallySymmetricKnown()` 8435 @*/ 8436 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B) 8437 { 8438 PetscFunctionBegin; 8439 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8440 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 8441 B->symmetry_eternal = A->symmetry_eternal; 8442 B->structural_symmetry_eternal = A->structural_symmetry_eternal; 8443 B->symmetric = A->symmetric; 8444 B->structurally_symmetric = A->structurally_symmetric; 8445 B->spd = A->spd; 8446 B->hermitian = A->hermitian; 8447 PetscFunctionReturn(PETSC_SUCCESS); 8448 } 8449 8450 /*@ 8451 MatStashSetInitialSize - sets the sizes of the matrix stash, that is 8452 used during the assembly process to store values that belong to 8453 other processors. 8454 8455 Not Collective 8456 8457 Input Parameters: 8458 + mat - the matrix 8459 . size - the initial size of the stash. 8460 - bsize - the initial size of the block-stash(if used). 8461 8462 Options Database Keys: 8463 + -matstash_initial_size <size> or <size0,size1,...sizep-1> 8464 - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1> 8465 8466 Level: intermediate 8467 8468 Notes: 8469 The block-stash is used for values set with `MatSetValuesBlocked()` while 8470 the stash is used for values set with `MatSetValues()` 8471 8472 Run with the option -info and look for output of the form 8473 MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs. 8474 to determine the appropriate value, MM, to use for size and 8475 MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs. 8476 to determine the value, BMM to use for bsize 8477 8478 .seealso: [](chapter_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()` 8479 @*/ 8480 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize) 8481 { 8482 PetscFunctionBegin; 8483 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8484 PetscValidType(mat, 1); 8485 PetscCall(MatStashSetInitialSize_Private(&mat->stash, size)); 8486 PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize)); 8487 PetscFunctionReturn(PETSC_SUCCESS); 8488 } 8489 8490 /*@ 8491 MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of 8492 the matrix 8493 8494 Neighbor-wise Collective 8495 8496 Input Parameters: 8497 + mat - the matrix 8498 . x - the vector to be multiplied by the interpolation operator 8499 - y - the vector to be added to the result 8500 8501 Output Parameter: 8502 . w - the resulting vector 8503 8504 Level: intermediate 8505 8506 Notes: 8507 `w` may be the same vector as `y`. 8508 8509 This allows one to use either the restriction or interpolation (its transpose) 8510 matrix to do the interpolation 8511 8512 .seealso: [](chapter_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8513 @*/ 8514 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w) 8515 { 8516 PetscInt M, N, Ny; 8517 8518 PetscFunctionBegin; 8519 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8520 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8521 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8522 PetscValidHeaderSpecific(w, VEC_CLASSID, 4); 8523 PetscCall(MatGetSize(A, &M, &N)); 8524 PetscCall(VecGetSize(y, &Ny)); 8525 if (M == Ny) { 8526 PetscCall(MatMultAdd(A, x, y, w)); 8527 } else { 8528 PetscCall(MatMultTransposeAdd(A, x, y, w)); 8529 } 8530 PetscFunctionReturn(PETSC_SUCCESS); 8531 } 8532 8533 /*@ 8534 MatInterpolate - y = A*x or A'*x depending on the shape of 8535 the matrix 8536 8537 Neighbor-wise Collective 8538 8539 Input Parameters: 8540 + mat - the matrix 8541 - x - the vector to be interpolated 8542 8543 Output Parameter: 8544 . y - the resulting vector 8545 8546 Level: intermediate 8547 8548 Note: 8549 This allows one to use either the restriction or interpolation (its transpose) 8550 matrix to do the interpolation 8551 8552 .seealso: [](chapter_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8553 @*/ 8554 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y) 8555 { 8556 PetscInt M, N, Ny; 8557 8558 PetscFunctionBegin; 8559 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8560 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8561 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8562 PetscCall(MatGetSize(A, &M, &N)); 8563 PetscCall(VecGetSize(y, &Ny)); 8564 if (M == Ny) { 8565 PetscCall(MatMult(A, x, y)); 8566 } else { 8567 PetscCall(MatMultTranspose(A, x, y)); 8568 } 8569 PetscFunctionReturn(PETSC_SUCCESS); 8570 } 8571 8572 /*@ 8573 MatRestrict - y = A*x or A'*x 8574 8575 Neighbor-wise Collective 8576 8577 Input Parameters: 8578 + mat - the matrix 8579 - x - the vector to be restricted 8580 8581 Output Parameter: 8582 . y - the resulting vector 8583 8584 Level: intermediate 8585 8586 Note: 8587 This allows one to use either the restriction or interpolation (its transpose) 8588 matrix to do the restriction 8589 8590 .seealso: [](chapter_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG` 8591 @*/ 8592 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y) 8593 { 8594 PetscInt M, N, Ny; 8595 8596 PetscFunctionBegin; 8597 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8598 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8599 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8600 PetscCall(MatGetSize(A, &M, &N)); 8601 PetscCall(VecGetSize(y, &Ny)); 8602 if (M == Ny) { 8603 PetscCall(MatMult(A, x, y)); 8604 } else { 8605 PetscCall(MatMultTranspose(A, x, y)); 8606 } 8607 PetscFunctionReturn(PETSC_SUCCESS); 8608 } 8609 8610 /*@ 8611 MatMatInterpolateAdd - Y = W + A*X or W + A'*X 8612 8613 Neighbor-wise Collective 8614 8615 Input Parameters: 8616 + mat - the matrix 8617 . x - the input dense matrix to be multiplied 8618 - w - the input dense matrix to be added to the result 8619 8620 Output Parameter: 8621 . y - the output dense matrix 8622 8623 Level: intermediate 8624 8625 Note: 8626 This allows one to use either the restriction or interpolation (its transpose) 8627 matrix to do the interpolation. y matrix can be reused if already created with the proper sizes, 8628 otherwise it will be recreated. y must be initialized to `NULL` if not supplied. 8629 8630 .seealso: [](chapter_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG` 8631 @*/ 8632 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y) 8633 { 8634 PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0; 8635 PetscBool trans = PETSC_TRUE; 8636 MatReuse reuse = MAT_INITIAL_MATRIX; 8637 8638 PetscFunctionBegin; 8639 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8640 PetscValidHeaderSpecific(x, MAT_CLASSID, 2); 8641 PetscValidType(x, 2); 8642 if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3); 8643 if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4); 8644 PetscCall(MatGetSize(A, &M, &N)); 8645 PetscCall(MatGetSize(x, &Mx, &Nx)); 8646 if (N == Mx) trans = PETSC_FALSE; 8647 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); 8648 Mo = trans ? N : M; 8649 if (*y) { 8650 PetscCall(MatGetSize(*y, &My, &Ny)); 8651 if (Mo == My && Nx == Ny) { 8652 reuse = MAT_REUSE_MATRIX; 8653 } else { 8654 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); 8655 PetscCall(MatDestroy(y)); 8656 } 8657 } 8658 8659 if (w && *y == w) { /* this is to minimize changes in PCMG */ 8660 PetscBool flg; 8661 8662 PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w)); 8663 if (w) { 8664 PetscInt My, Ny, Mw, Nw; 8665 8666 PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg)); 8667 PetscCall(MatGetSize(*y, &My, &Ny)); 8668 PetscCall(MatGetSize(w, &Mw, &Nw)); 8669 if (!flg || My != Mw || Ny != Nw) w = NULL; 8670 } 8671 if (!w) { 8672 PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w)); 8673 PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w)); 8674 PetscCall(PetscObjectDereference((PetscObject)w)); 8675 } else { 8676 PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN)); 8677 } 8678 } 8679 if (!trans) { 8680 PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8681 } else { 8682 PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8683 } 8684 if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN)); 8685 PetscFunctionReturn(PETSC_SUCCESS); 8686 } 8687 8688 /*@ 8689 MatMatInterpolate - Y = A*X or A'*X 8690 8691 Neighbor-wise Collective 8692 8693 Input Parameters: 8694 + mat - the matrix 8695 - x - the input dense matrix 8696 8697 Output Parameter: 8698 . y - the output dense matrix 8699 8700 Level: intermediate 8701 8702 Note: 8703 This allows one to use either the restriction or interpolation (its transpose) 8704 matrix to do the interpolation. y matrix can be reused if already created with the proper sizes, 8705 otherwise it will be recreated. y must be initialized to `NULL` if not supplied. 8706 8707 .seealso: [](chapter_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG` 8708 @*/ 8709 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y) 8710 { 8711 PetscFunctionBegin; 8712 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8713 PetscFunctionReturn(PETSC_SUCCESS); 8714 } 8715 8716 /*@ 8717 MatMatRestrict - Y = A*X or A'*X 8718 8719 Neighbor-wise Collective 8720 8721 Input Parameters: 8722 + mat - the matrix 8723 - x - the input dense matrix 8724 8725 Output Parameter: 8726 . y - the output dense matrix 8727 8728 Level: intermediate 8729 8730 Note: 8731 This allows one to use either the restriction or interpolation (its transpose) 8732 matrix to do the restriction. y matrix can be reused if already created with the proper sizes, 8733 otherwise it will be recreated. y must be initialized to `NULL` if not supplied. 8734 8735 .seealso: [](chapter_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG` 8736 @*/ 8737 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y) 8738 { 8739 PetscFunctionBegin; 8740 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8741 PetscFunctionReturn(PETSC_SUCCESS); 8742 } 8743 8744 /*@ 8745 MatGetNullSpace - retrieves the null space of a matrix. 8746 8747 Logically Collective 8748 8749 Input Parameters: 8750 + mat - the matrix 8751 - nullsp - the null space object 8752 8753 Level: developer 8754 8755 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace` 8756 @*/ 8757 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp) 8758 { 8759 PetscFunctionBegin; 8760 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8761 PetscValidPointer(nullsp, 2); 8762 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp; 8763 PetscFunctionReturn(PETSC_SUCCESS); 8764 } 8765 8766 /*@ 8767 MatSetNullSpace - attaches a null space to a matrix. 8768 8769 Logically Collective 8770 8771 Input Parameters: 8772 + mat - the matrix 8773 - nullsp - the null space object 8774 8775 Level: advanced 8776 8777 Notes: 8778 This null space is used by the `KSP` linear solvers to solve singular systems. 8779 8780 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` 8781 8782 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 8783 to zero but the linear system will still be solved in a least squares sense. 8784 8785 The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that 8786 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). 8787 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 8788 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 8789 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). 8790 This \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix. 8791 8792 If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called 8793 `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this 8794 routine also automatically calls `MatSetTransposeNullSpace()`. 8795 8796 The user should call `MatNullSpaceDestroy()`. 8797 8798 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, 8799 `KSPSetPCSide()` 8800 @*/ 8801 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp) 8802 { 8803 PetscFunctionBegin; 8804 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8805 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8806 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8807 PetscCall(MatNullSpaceDestroy(&mat->nullsp)); 8808 mat->nullsp = nullsp; 8809 if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp)); 8810 PetscFunctionReturn(PETSC_SUCCESS); 8811 } 8812 8813 /*@ 8814 MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix. 8815 8816 Logically Collective 8817 8818 Input Parameters: 8819 + mat - the matrix 8820 - nullsp - the null space object 8821 8822 Level: developer 8823 8824 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()` 8825 @*/ 8826 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp) 8827 { 8828 PetscFunctionBegin; 8829 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8830 PetscValidType(mat, 1); 8831 PetscValidPointer(nullsp, 2); 8832 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp; 8833 PetscFunctionReturn(PETSC_SUCCESS); 8834 } 8835 8836 /*@ 8837 MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix 8838 8839 Logically Collective 8840 8841 Input Parameters: 8842 + mat - the matrix 8843 - nullsp - the null space object 8844 8845 Level: advanced 8846 8847 Notes: 8848 This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning. 8849 8850 See `MatSetNullSpace()` 8851 8852 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()` 8853 @*/ 8854 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp) 8855 { 8856 PetscFunctionBegin; 8857 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8858 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8859 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8860 PetscCall(MatNullSpaceDestroy(&mat->transnullsp)); 8861 mat->transnullsp = nullsp; 8862 PetscFunctionReturn(PETSC_SUCCESS); 8863 } 8864 8865 /*@ 8866 MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions 8867 This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix. 8868 8869 Logically Collective 8870 8871 Input Parameters: 8872 + mat - the matrix 8873 - nullsp - the null space object 8874 8875 Level: advanced 8876 8877 Notes: 8878 Overwrites any previous near null space that may have been attached 8879 8880 You can remove the null space by calling this routine with an nullsp of `NULL` 8881 8882 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()` 8883 @*/ 8884 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp) 8885 { 8886 PetscFunctionBegin; 8887 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8888 PetscValidType(mat, 1); 8889 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8890 MatCheckPreallocated(mat, 1); 8891 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8892 PetscCall(MatNullSpaceDestroy(&mat->nearnullsp)); 8893 mat->nearnullsp = nullsp; 8894 PetscFunctionReturn(PETSC_SUCCESS); 8895 } 8896 8897 /*@ 8898 MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()` 8899 8900 Not Collective 8901 8902 Input Parameter: 8903 . mat - the matrix 8904 8905 Output Parameter: 8906 . nullsp - the null space object, `NULL` if not set 8907 8908 Level: advanced 8909 8910 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()` 8911 @*/ 8912 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp) 8913 { 8914 PetscFunctionBegin; 8915 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8916 PetscValidType(mat, 1); 8917 PetscValidPointer(nullsp, 2); 8918 MatCheckPreallocated(mat, 1); 8919 *nullsp = mat->nearnullsp; 8920 PetscFunctionReturn(PETSC_SUCCESS); 8921 } 8922 8923 /*@C 8924 MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix. 8925 8926 Collective 8927 8928 Input Parameters: 8929 + mat - the matrix 8930 . row - row/column permutation 8931 - info - information on desired factorization process 8932 8933 Level: developer 8934 8935 Notes: 8936 Probably really in-place only when level of fill is zero, otherwise allocates 8937 new space to store factored matrix and deletes previous memory. 8938 8939 Most users should employ the `KSP` interface for linear solvers 8940 instead of working directly with matrix algebra routines such as this. 8941 See, e.g., `KSPCreate()`. 8942 8943 Developer Note: 8944 The Fortran interface is not autogenerated as the 8945 interface definition cannot be generated correctly [due to `MatFactorInfo`] 8946 8947 .seealso: [](chapter_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 8948 @*/ 8949 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info) 8950 { 8951 PetscFunctionBegin; 8952 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8953 PetscValidType(mat, 1); 8954 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 8955 PetscValidPointer(info, 3); 8956 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 8957 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 8958 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8959 MatCheckPreallocated(mat, 1); 8960 PetscUseTypeMethod(mat, iccfactor, row, info); 8961 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 8962 PetscFunctionReturn(PETSC_SUCCESS); 8963 } 8964 8965 /*@ 8966 MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the 8967 ghosted ones. 8968 8969 Not Collective 8970 8971 Input Parameters: 8972 + mat - the matrix 8973 - diag - the diagonal values, including ghost ones 8974 8975 Level: developer 8976 8977 Notes: 8978 Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices 8979 8980 This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()` 8981 8982 .seealso: [](chapter_matrices), `Mat`, `MatDiagonalScale()` 8983 @*/ 8984 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag) 8985 { 8986 PetscMPIInt size; 8987 8988 PetscFunctionBegin; 8989 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8990 PetscValidHeaderSpecific(diag, VEC_CLASSID, 2); 8991 PetscValidType(mat, 1); 8992 8993 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled"); 8994 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 8995 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8996 if (size == 1) { 8997 PetscInt n, m; 8998 PetscCall(VecGetSize(diag, &n)); 8999 PetscCall(MatGetSize(mat, NULL, &m)); 9000 PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions"); 9001 PetscCall(MatDiagonalScale(mat, NULL, diag)); 9002 } else { 9003 PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag)); 9004 } 9005 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 9006 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9007 PetscFunctionReturn(PETSC_SUCCESS); 9008 } 9009 9010 /*@ 9011 MatGetInertia - Gets the inertia from a factored matrix 9012 9013 Collective 9014 9015 Input Parameter: 9016 . mat - the matrix 9017 9018 Output Parameters: 9019 + nneg - number of negative eigenvalues 9020 . nzero - number of zero eigenvalues 9021 - npos - number of positive eigenvalues 9022 9023 Level: advanced 9024 9025 Note: 9026 Matrix must have been factored by `MatCholeskyFactor()` 9027 9028 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()` 9029 @*/ 9030 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos) 9031 { 9032 PetscFunctionBegin; 9033 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9034 PetscValidType(mat, 1); 9035 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9036 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled"); 9037 PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos); 9038 PetscFunctionReturn(PETSC_SUCCESS); 9039 } 9040 9041 /*@C 9042 MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors 9043 9044 Neighbor-wise Collective 9045 9046 Input Parameters: 9047 + mat - the factored matrix obtained with `MatGetFactor()` 9048 - b - the right-hand-side vectors 9049 9050 Output Parameter: 9051 . x - the result vectors 9052 9053 Level: developer 9054 9055 Note: 9056 The vectors `b` and `x` cannot be the same. I.e., one cannot 9057 call `MatSolves`(A,x,x). 9058 9059 .seealso: [](chapter_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()` 9060 @*/ 9061 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x) 9062 { 9063 PetscFunctionBegin; 9064 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9065 PetscValidType(mat, 1); 9066 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 9067 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9068 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 9069 9070 MatCheckPreallocated(mat, 1); 9071 PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0)); 9072 PetscUseTypeMethod(mat, solves, b, x); 9073 PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0)); 9074 PetscFunctionReturn(PETSC_SUCCESS); 9075 } 9076 9077 /*@ 9078 MatIsSymmetric - Test whether a matrix is symmetric 9079 9080 Collective 9081 9082 Input Parameters: 9083 + A - the matrix to test 9084 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose) 9085 9086 Output Parameter: 9087 . flg - the result 9088 9089 Level: intermediate 9090 9091 Notes: 9092 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9093 9094 If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()` 9095 9096 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9097 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9098 9099 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`, 9100 `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()` 9101 @*/ 9102 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg) 9103 { 9104 PetscFunctionBegin; 9105 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9106 PetscValidBoolPointer(flg, 3); 9107 9108 if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE; 9109 else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE; 9110 else { 9111 PetscUseTypeMethod(A, issymmetric, tol, flg); 9112 if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg)); 9113 } 9114 PetscFunctionReturn(PETSC_SUCCESS); 9115 } 9116 9117 /*@ 9118 MatIsHermitian - Test whether a matrix is Hermitian 9119 9120 Collective 9121 9122 Input Parameters: 9123 + A - the matrix to test 9124 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian) 9125 9126 Output Parameter: 9127 . flg - the result 9128 9129 Level: intermediate 9130 9131 Notes: 9132 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9133 9134 If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()` 9135 9136 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9137 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`) 9138 9139 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, 9140 `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()` 9141 @*/ 9142 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg) 9143 { 9144 PetscFunctionBegin; 9145 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9146 PetscValidBoolPointer(flg, 3); 9147 9148 if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE; 9149 else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE; 9150 else { 9151 PetscUseTypeMethod(A, ishermitian, tol, flg); 9152 if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg)); 9153 } 9154 PetscFunctionReturn(PETSC_SUCCESS); 9155 } 9156 9157 /*@ 9158 MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state 9159 9160 Not Collective 9161 9162 Input Parameter: 9163 . A - the matrix to check 9164 9165 Output Parameters: 9166 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid) 9167 - flg - the result (only valid if set is `PETSC_TRUE`) 9168 9169 Level: advanced 9170 9171 Notes: 9172 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()` 9173 if you want it explicitly checked 9174 9175 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9176 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9177 9178 .seealso: [](chapter_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9179 @*/ 9180 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9181 { 9182 PetscFunctionBegin; 9183 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9184 PetscValidBoolPointer(set, 2); 9185 PetscValidBoolPointer(flg, 3); 9186 if (A->symmetric != PETSC_BOOL3_UNKNOWN) { 9187 *set = PETSC_TRUE; 9188 *flg = PetscBool3ToBool(A->symmetric); 9189 } else { 9190 *set = PETSC_FALSE; 9191 } 9192 PetscFunctionReturn(PETSC_SUCCESS); 9193 } 9194 9195 /*@ 9196 MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state 9197 9198 Not Collective 9199 9200 Input Parameter: 9201 . A - the matrix to check 9202 9203 Output Parameters: 9204 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid) 9205 - flg - the result (only valid if set is `PETSC_TRUE`) 9206 9207 Level: advanced 9208 9209 Notes: 9210 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). 9211 9212 One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD 9213 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`) 9214 9215 .seealso: [](chapter_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9216 @*/ 9217 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg) 9218 { 9219 PetscFunctionBegin; 9220 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9221 PetscValidBoolPointer(set, 2); 9222 PetscValidBoolPointer(flg, 3); 9223 if (A->spd != PETSC_BOOL3_UNKNOWN) { 9224 *set = PETSC_TRUE; 9225 *flg = PetscBool3ToBool(A->spd); 9226 } else { 9227 *set = PETSC_FALSE; 9228 } 9229 PetscFunctionReturn(PETSC_SUCCESS); 9230 } 9231 9232 /*@ 9233 MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state 9234 9235 Not Collective 9236 9237 Input Parameter: 9238 . A - the matrix to check 9239 9240 Output Parameters: 9241 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid) 9242 - flg - the result (only valid if set is `PETSC_TRUE`) 9243 9244 Level: advanced 9245 9246 Notes: 9247 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()` 9248 if you want it explicitly checked 9249 9250 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9251 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9252 9253 .seealso: [](chapter_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()` 9254 @*/ 9255 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg) 9256 { 9257 PetscFunctionBegin; 9258 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9259 PetscValidBoolPointer(set, 2); 9260 PetscValidBoolPointer(flg, 3); 9261 if (A->hermitian != PETSC_BOOL3_UNKNOWN) { 9262 *set = PETSC_TRUE; 9263 *flg = PetscBool3ToBool(A->hermitian); 9264 } else { 9265 *set = PETSC_FALSE; 9266 } 9267 PetscFunctionReturn(PETSC_SUCCESS); 9268 } 9269 9270 /*@ 9271 MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric 9272 9273 Collective 9274 9275 Input Parameter: 9276 . A - the matrix to test 9277 9278 Output Parameter: 9279 . flg - the result 9280 9281 Level: intermediate 9282 9283 Notes: 9284 If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()` 9285 9286 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 9287 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9288 9289 .seealso: [](chapter_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()` 9290 @*/ 9291 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg) 9292 { 9293 PetscFunctionBegin; 9294 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9295 PetscValidBoolPointer(flg, 2); 9296 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9297 *flg = PetscBool3ToBool(A->structurally_symmetric); 9298 } else { 9299 PetscUseTypeMethod(A, isstructurallysymmetric, flg); 9300 PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg)); 9301 } 9302 PetscFunctionReturn(PETSC_SUCCESS); 9303 } 9304 9305 /*@ 9306 MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state 9307 9308 Not Collective 9309 9310 Input Parameter: 9311 . A - the matrix to check 9312 9313 Output Parameters: 9314 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid) 9315 - flg - the result (only valid if set is PETSC_TRUE) 9316 9317 Level: advanced 9318 9319 Notes: 9320 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 9321 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9322 9323 Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation) 9324 9325 .seealso: [](chapter_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9326 @*/ 9327 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9328 { 9329 PetscFunctionBegin; 9330 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9331 PetscValidBoolPointer(set, 2); 9332 PetscValidBoolPointer(flg, 3); 9333 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9334 *set = PETSC_TRUE; 9335 *flg = PetscBool3ToBool(A->structurally_symmetric); 9336 } else { 9337 *set = PETSC_FALSE; 9338 } 9339 PetscFunctionReturn(PETSC_SUCCESS); 9340 } 9341 9342 /*@ 9343 MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need 9344 to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process 9345 9346 Not Collective 9347 9348 Input Parameter: 9349 . mat - the matrix 9350 9351 Output Parameters: 9352 + nstash - the size of the stash 9353 . reallocs - the number of additional mallocs incurred. 9354 . bnstash - the size of the block stash 9355 - breallocs - the number of additional mallocs incurred.in the block stash 9356 9357 Level: advanced 9358 9359 .seealso: [](chapter_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()` 9360 @*/ 9361 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs) 9362 { 9363 PetscFunctionBegin; 9364 PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs)); 9365 PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs)); 9366 PetscFunctionReturn(PETSC_SUCCESS); 9367 } 9368 9369 /*@C 9370 MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same 9371 parallel layout, `PetscLayout` for rows and columns 9372 9373 Collective 9374 9375 Input Parameter: 9376 . mat - the matrix 9377 9378 Output Parameters: 9379 + right - (optional) vector that the matrix can be multiplied against 9380 - left - (optional) vector that the matrix vector product can be stored in 9381 9382 Level: advanced 9383 9384 Notes: 9385 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()`. 9386 9387 These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed 9388 9389 .seealso: [](chapter_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()` 9390 @*/ 9391 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left) 9392 { 9393 PetscFunctionBegin; 9394 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9395 PetscValidType(mat, 1); 9396 if (mat->ops->getvecs) { 9397 PetscUseTypeMethod(mat, getvecs, right, left); 9398 } else { 9399 PetscInt rbs, cbs; 9400 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 9401 if (right) { 9402 PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup"); 9403 PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), right)); 9404 PetscCall(VecSetSizes(*right, mat->cmap->n, PETSC_DETERMINE)); 9405 PetscCall(VecSetBlockSize(*right, cbs)); 9406 PetscCall(VecSetType(*right, mat->defaultvectype)); 9407 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9408 if (mat->boundtocpu && mat->bindingpropagates) { 9409 PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE)); 9410 PetscCall(VecBindToCPU(*right, PETSC_TRUE)); 9411 } 9412 #endif 9413 PetscCall(PetscLayoutReference(mat->cmap, &(*right)->map)); 9414 } 9415 if (left) { 9416 PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup"); 9417 PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), left)); 9418 PetscCall(VecSetSizes(*left, mat->rmap->n, PETSC_DETERMINE)); 9419 PetscCall(VecSetBlockSize(*left, rbs)); 9420 PetscCall(VecSetType(*left, mat->defaultvectype)); 9421 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9422 if (mat->boundtocpu && mat->bindingpropagates) { 9423 PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE)); 9424 PetscCall(VecBindToCPU(*left, PETSC_TRUE)); 9425 } 9426 #endif 9427 PetscCall(PetscLayoutReference(mat->rmap, &(*left)->map)); 9428 } 9429 } 9430 PetscFunctionReturn(PETSC_SUCCESS); 9431 } 9432 9433 /*@C 9434 MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure 9435 with default values. 9436 9437 Not Collective 9438 9439 Input Parameter: 9440 . info - the `MatFactorInfo` data structure 9441 9442 Level: developer 9443 9444 Notes: 9445 The solvers are generally used through the `KSP` and `PC` objects, for example 9446 `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC` 9447 9448 Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed 9449 9450 Developer Note: 9451 The Fortran interface is not autogenerated as the 9452 interface definition cannot be generated correctly [due to `MatFactorInfo`] 9453 9454 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo` 9455 @*/ 9456 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info) 9457 { 9458 PetscFunctionBegin; 9459 PetscCall(PetscMemzero(info, sizeof(MatFactorInfo))); 9460 PetscFunctionReturn(PETSC_SUCCESS); 9461 } 9462 9463 /*@ 9464 MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed 9465 9466 Collective 9467 9468 Input Parameters: 9469 + mat - the factored matrix 9470 - is - the index set defining the Schur indices (0-based) 9471 9472 Level: advanced 9473 9474 Notes: 9475 Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system. 9476 9477 You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call. 9478 9479 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9480 9481 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`, 9482 `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9483 @*/ 9484 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is) 9485 { 9486 PetscErrorCode (*f)(Mat, IS); 9487 9488 PetscFunctionBegin; 9489 PetscValidType(mat, 1); 9490 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9491 PetscValidType(is, 2); 9492 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 9493 PetscCheckSameComm(mat, 1, is, 2); 9494 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 9495 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f)); 9496 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO"); 9497 PetscCall(MatDestroy(&mat->schur)); 9498 PetscCall((*f)(mat, is)); 9499 PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created"); 9500 PetscFunctionReturn(PETSC_SUCCESS); 9501 } 9502 9503 /*@ 9504 MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step 9505 9506 Logically Collective 9507 9508 Input Parameters: 9509 + F - the factored matrix obtained by calling `MatGetFactor()` 9510 . S - location where to return the Schur complement, can be `NULL` 9511 - status - the status of the Schur complement matrix, can be `NULL` 9512 9513 Level: advanced 9514 9515 Notes: 9516 You must call `MatFactorSetSchurIS()` before calling this routine. 9517 9518 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9519 9520 The routine provides a copy of the Schur matrix stored within the solver data structures. 9521 The caller must destroy the object when it is no longer needed. 9522 If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse. 9523 9524 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) 9525 9526 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9527 9528 Developer Note: 9529 The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc 9530 matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix. 9531 9532 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9533 @*/ 9534 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9535 { 9536 PetscFunctionBegin; 9537 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9538 if (S) PetscValidPointer(S, 2); 9539 if (status) PetscValidPointer(status, 3); 9540 if (S) { 9541 PetscErrorCode (*f)(Mat, Mat *); 9542 9543 PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f)); 9544 if (f) { 9545 PetscCall((*f)(F, S)); 9546 } else { 9547 PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S)); 9548 } 9549 } 9550 if (status) *status = F->schur_status; 9551 PetscFunctionReturn(PETSC_SUCCESS); 9552 } 9553 9554 /*@ 9555 MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix 9556 9557 Logically Collective 9558 9559 Input Parameters: 9560 + F - the factored matrix obtained by calling `MatGetFactor()` 9561 . *S - location where to return the Schur complement, can be `NULL` 9562 - status - the status of the Schur complement matrix, can be `NULL` 9563 9564 Level: advanced 9565 9566 Notes: 9567 You must call `MatFactorSetSchurIS()` before calling this routine. 9568 9569 Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS` 9570 9571 The routine returns a the Schur Complement stored within the data structures of the solver. 9572 9573 If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement. 9574 9575 The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed. 9576 9577 Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix 9578 9579 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9580 9581 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9582 @*/ 9583 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9584 { 9585 PetscFunctionBegin; 9586 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9587 if (S) PetscValidPointer(S, 2); 9588 if (status) PetscValidPointer(status, 3); 9589 if (S) *S = F->schur; 9590 if (status) *status = F->schur_status; 9591 PetscFunctionReturn(PETSC_SUCCESS); 9592 } 9593 9594 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F) 9595 { 9596 Mat S = F->schur; 9597 9598 PetscFunctionBegin; 9599 switch (F->schur_status) { 9600 case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through 9601 case MAT_FACTOR_SCHUR_INVERTED: 9602 if (S) { 9603 S->ops->solve = NULL; 9604 S->ops->matsolve = NULL; 9605 S->ops->solvetranspose = NULL; 9606 S->ops->matsolvetranspose = NULL; 9607 S->ops->solveadd = NULL; 9608 S->ops->solvetransposeadd = NULL; 9609 S->factortype = MAT_FACTOR_NONE; 9610 PetscCall(PetscFree(S->solvertype)); 9611 } 9612 case MAT_FACTOR_SCHUR_FACTORED: // fall-through 9613 break; 9614 default: 9615 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9616 } 9617 PetscFunctionReturn(PETSC_SUCCESS); 9618 } 9619 9620 /*@ 9621 MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()` 9622 9623 Logically Collective 9624 9625 Input Parameters: 9626 + F - the factored matrix obtained by calling `MatGetFactor()` 9627 . *S - location where the Schur complement is stored 9628 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`) 9629 9630 Level: advanced 9631 9632 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9633 @*/ 9634 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status) 9635 { 9636 PetscFunctionBegin; 9637 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9638 if (S) { 9639 PetscValidHeaderSpecific(*S, MAT_CLASSID, 2); 9640 *S = NULL; 9641 } 9642 F->schur_status = status; 9643 PetscCall(MatFactorUpdateSchurStatus_Private(F)); 9644 PetscFunctionReturn(PETSC_SUCCESS); 9645 } 9646 9647 /*@ 9648 MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step 9649 9650 Logically Collective 9651 9652 Input Parameters: 9653 + F - the factored matrix obtained by calling `MatGetFactor()` 9654 . rhs - location where the right hand side of the Schur complement system is stored 9655 - sol - location where the solution of the Schur complement system has to be returned 9656 9657 Level: advanced 9658 9659 Notes: 9660 The sizes of the vectors should match the size of the Schur complement 9661 9662 Must be called after `MatFactorSetSchurIS()` 9663 9664 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()` 9665 @*/ 9666 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol) 9667 { 9668 PetscFunctionBegin; 9669 PetscValidType(F, 1); 9670 PetscValidType(rhs, 2); 9671 PetscValidType(sol, 3); 9672 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9673 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9674 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9675 PetscCheckSameComm(F, 1, rhs, 2); 9676 PetscCheckSameComm(F, 1, sol, 3); 9677 PetscCall(MatFactorFactorizeSchurComplement(F)); 9678 switch (F->schur_status) { 9679 case MAT_FACTOR_SCHUR_FACTORED: 9680 PetscCall(MatSolveTranspose(F->schur, rhs, sol)); 9681 break; 9682 case MAT_FACTOR_SCHUR_INVERTED: 9683 PetscCall(MatMultTranspose(F->schur, rhs, sol)); 9684 break; 9685 default: 9686 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9687 } 9688 PetscFunctionReturn(PETSC_SUCCESS); 9689 } 9690 9691 /*@ 9692 MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step 9693 9694 Logically Collective 9695 9696 Input Parameters: 9697 + F - the factored matrix obtained by calling `MatGetFactor()` 9698 . rhs - location where the right hand side of the Schur complement system is stored 9699 - sol - location where the solution of the Schur complement system has to be returned 9700 9701 Level: advanced 9702 9703 Notes: 9704 The sizes of the vectors should match the size of the Schur complement 9705 9706 Must be called after `MatFactorSetSchurIS()` 9707 9708 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()` 9709 @*/ 9710 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol) 9711 { 9712 PetscFunctionBegin; 9713 PetscValidType(F, 1); 9714 PetscValidType(rhs, 2); 9715 PetscValidType(sol, 3); 9716 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9717 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9718 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9719 PetscCheckSameComm(F, 1, rhs, 2); 9720 PetscCheckSameComm(F, 1, sol, 3); 9721 PetscCall(MatFactorFactorizeSchurComplement(F)); 9722 switch (F->schur_status) { 9723 case MAT_FACTOR_SCHUR_FACTORED: 9724 PetscCall(MatSolve(F->schur, rhs, sol)); 9725 break; 9726 case MAT_FACTOR_SCHUR_INVERTED: 9727 PetscCall(MatMult(F->schur, rhs, sol)); 9728 break; 9729 default: 9730 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9731 } 9732 PetscFunctionReturn(PETSC_SUCCESS); 9733 } 9734 9735 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat); 9736 #if PetscDefined(HAVE_CUDA) 9737 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat); 9738 #endif 9739 9740 /* Schur status updated in the interface */ 9741 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F) 9742 { 9743 Mat S = F->schur; 9744 9745 PetscFunctionBegin; 9746 if (S) { 9747 PetscMPIInt size; 9748 PetscBool isdense, isdensecuda; 9749 9750 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size)); 9751 PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented"); 9752 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense)); 9753 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda)); 9754 PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name); 9755 PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0)); 9756 if (isdense) { 9757 PetscCall(MatSeqDenseInvertFactors_Private(S)); 9758 } else if (isdensecuda) { 9759 #if defined(PETSC_HAVE_CUDA) 9760 PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S)); 9761 #endif 9762 } 9763 // HIP?????????????? 9764 PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0)); 9765 } 9766 PetscFunctionReturn(PETSC_SUCCESS); 9767 } 9768 9769 /*@ 9770 MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step 9771 9772 Logically Collective 9773 9774 Input Parameter: 9775 . F - the factored matrix obtained by calling `MatGetFactor()` 9776 9777 Level: advanced 9778 9779 Notes: 9780 Must be called after `MatFactorSetSchurIS()`. 9781 9782 Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it. 9783 9784 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()` 9785 @*/ 9786 PetscErrorCode MatFactorInvertSchurComplement(Mat F) 9787 { 9788 PetscFunctionBegin; 9789 PetscValidType(F, 1); 9790 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9791 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS); 9792 PetscCall(MatFactorFactorizeSchurComplement(F)); 9793 PetscCall(MatFactorInvertSchurComplement_Private(F)); 9794 F->schur_status = MAT_FACTOR_SCHUR_INVERTED; 9795 PetscFunctionReturn(PETSC_SUCCESS); 9796 } 9797 9798 /*@ 9799 MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step 9800 9801 Logically Collective 9802 9803 Input Parameter: 9804 . F - the factored matrix obtained by calling `MatGetFactor()` 9805 9806 Level: advanced 9807 9808 Note: 9809 Must be called after `MatFactorSetSchurIS()` 9810 9811 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()` 9812 @*/ 9813 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F) 9814 { 9815 MatFactorInfo info; 9816 9817 PetscFunctionBegin; 9818 PetscValidType(F, 1); 9819 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9820 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS); 9821 PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0)); 9822 PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo))); 9823 if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */ 9824 PetscCall(MatCholeskyFactor(F->schur, NULL, &info)); 9825 } else { 9826 PetscCall(MatLUFactor(F->schur, NULL, NULL, &info)); 9827 } 9828 PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0)); 9829 F->schur_status = MAT_FACTOR_SCHUR_FACTORED; 9830 PetscFunctionReturn(PETSC_SUCCESS); 9831 } 9832 9833 /*@ 9834 MatPtAP - Creates the matrix product C = P^T * A * P 9835 9836 Neighbor-wise Collective 9837 9838 Input Parameters: 9839 + A - the matrix 9840 . P - the projection matrix 9841 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9842 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate 9843 if the result is a dense matrix this is irrelevant 9844 9845 Output Parameter: 9846 . C - the product matrix 9847 9848 Level: intermediate 9849 9850 Notes: 9851 C will be created and must be destroyed by the user with `MatDestroy()`. 9852 9853 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9854 9855 Developer Note: 9856 For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`. 9857 9858 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()` 9859 @*/ 9860 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C) 9861 { 9862 PetscFunctionBegin; 9863 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 9864 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9865 9866 if (scall == MAT_INITIAL_MATRIX) { 9867 PetscCall(MatProductCreate(A, P, NULL, C)); 9868 PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP)); 9869 PetscCall(MatProductSetAlgorithm(*C, "default")); 9870 PetscCall(MatProductSetFill(*C, fill)); 9871 9872 (*C)->product->api_user = PETSC_TRUE; 9873 PetscCall(MatProductSetFromOptions(*C)); 9874 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); 9875 PetscCall(MatProductSymbolic(*C)); 9876 } else { /* scall == MAT_REUSE_MATRIX */ 9877 PetscCall(MatProductReplaceMats(A, P, NULL, *C)); 9878 } 9879 9880 PetscCall(MatProductNumeric(*C)); 9881 (*C)->symmetric = A->symmetric; 9882 (*C)->spd = A->spd; 9883 PetscFunctionReturn(PETSC_SUCCESS); 9884 } 9885 9886 /*@ 9887 MatRARt - Creates the matrix product C = R * A * R^T 9888 9889 Neighbor-wise Collective 9890 9891 Input Parameters: 9892 + A - the matrix 9893 . R - the projection matrix 9894 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9895 - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate 9896 if the result is a dense matrix this is irrelevant 9897 9898 Output Parameter: 9899 . C - the product matrix 9900 9901 Level: intermediate 9902 9903 Notes: 9904 C will be created and must be destroyed by the user with `MatDestroy()`. 9905 9906 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9907 9908 This routine is currently only implemented for pairs of `MATAIJ` matrices and classes 9909 which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes, 9910 parallel MatRARt is implemented via explicit transpose of R, which could be very expensive. 9911 We recommend using MatPtAP(). 9912 9913 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()` 9914 @*/ 9915 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C) 9916 { 9917 PetscFunctionBegin; 9918 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 9919 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9920 9921 if (scall == MAT_INITIAL_MATRIX) { 9922 PetscCall(MatProductCreate(A, R, NULL, C)); 9923 PetscCall(MatProductSetType(*C, MATPRODUCT_RARt)); 9924 PetscCall(MatProductSetAlgorithm(*C, "default")); 9925 PetscCall(MatProductSetFill(*C, fill)); 9926 9927 (*C)->product->api_user = PETSC_TRUE; 9928 PetscCall(MatProductSetFromOptions(*C)); 9929 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); 9930 PetscCall(MatProductSymbolic(*C)); 9931 } else { /* scall == MAT_REUSE_MATRIX */ 9932 PetscCall(MatProductReplaceMats(A, R, NULL, *C)); 9933 } 9934 9935 PetscCall(MatProductNumeric(*C)); 9936 if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 9937 PetscFunctionReturn(PETSC_SUCCESS); 9938 } 9939 9940 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C) 9941 { 9942 PetscFunctionBegin; 9943 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9944 9945 if (scall == MAT_INITIAL_MATRIX) { 9946 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype])); 9947 PetscCall(MatProductCreate(A, B, NULL, C)); 9948 PetscCall(MatProductSetType(*C, ptype)); 9949 PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT)); 9950 PetscCall(MatProductSetFill(*C, fill)); 9951 9952 (*C)->product->api_user = PETSC_TRUE; 9953 PetscCall(MatProductSetFromOptions(*C)); 9954 PetscCall(MatProductSymbolic(*C)); 9955 } else { /* scall == MAT_REUSE_MATRIX */ 9956 Mat_Product *product = (*C)->product; 9957 PetscBool isdense; 9958 9959 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, "")); 9960 if (isdense && product && product->type != ptype) { 9961 PetscCall(MatProductClear(*C)); 9962 product = NULL; 9963 } 9964 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype])); 9965 if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */ 9966 PetscCheck(isdense, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first"); 9967 PetscCall(MatProductCreate_Private(A, B, NULL, *C)); 9968 product = (*C)->product; 9969 product->fill = fill; 9970 product->api_user = PETSC_TRUE; 9971 product->clear = PETSC_TRUE; 9972 9973 PetscCall(MatProductSetType(*C, ptype)); 9974 PetscCall(MatProductSetFromOptions(*C)); 9975 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); 9976 PetscCall(MatProductSymbolic(*C)); 9977 } else { /* user may change input matrices A or B when REUSE */ 9978 PetscCall(MatProductReplaceMats(A, B, NULL, *C)); 9979 } 9980 } 9981 PetscCall(MatProductNumeric(*C)); 9982 PetscFunctionReturn(PETSC_SUCCESS); 9983 } 9984 9985 /*@ 9986 MatMatMult - Performs matrix-matrix multiplication C=A*B. 9987 9988 Neighbor-wise Collective 9989 9990 Input Parameters: 9991 + A - the left matrix 9992 . B - the right matrix 9993 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9994 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate 9995 if the result is a dense matrix this is irrelevant 9996 9997 Output Parameter: 9998 . C - the product matrix 9999 10000 Notes: 10001 Unless scall is `MAT_REUSE_MATRIX` C will be created. 10002 10003 `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 10004 call to this function with `MAT_INITIAL_MATRIX`. 10005 10006 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed. 10007 10008 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`, 10009 rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse. 10010 10011 Example of Usage: 10012 .vb 10013 MatProductCreate(A,B,NULL,&C); 10014 MatProductSetType(C,MATPRODUCT_AB); 10015 MatProductSymbolic(C); 10016 MatProductNumeric(C); // compute C=A * B 10017 MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1 10018 MatProductNumeric(C); 10019 MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1 10020 MatProductNumeric(C); 10021 .ve 10022 10023 Level: intermediate 10024 10025 .seealso: [](chapter_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()` 10026 @*/ 10027 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10028 { 10029 PetscFunctionBegin; 10030 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C)); 10031 PetscFunctionReturn(PETSC_SUCCESS); 10032 } 10033 10034 /*@ 10035 MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T. 10036 10037 Neighbor-wise Collective 10038 10039 Input Parameters: 10040 + A - the left matrix 10041 . B - the right matrix 10042 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10043 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 10044 10045 Output Parameter: 10046 . C - the product matrix 10047 10048 Level: intermediate 10049 10050 Notes: 10051 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10052 10053 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call 10054 10055 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10056 actually needed. 10057 10058 This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class, 10059 and for pairs of `MATMPIDENSE` matrices. 10060 10061 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt` 10062 10063 Options Database Keys: 10064 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the 10065 first redundantly copies the transposed B matrix on each process and requiers O(log P) communication complexity; 10066 the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity. 10067 10068 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductCreate()`, `MatProductAlgorithm`, `MatProductType`, `MATPRODUCT_ABt` 10069 @*/ 10070 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10071 { 10072 PetscFunctionBegin; 10073 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C)); 10074 if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10075 PetscFunctionReturn(PETSC_SUCCESS); 10076 } 10077 10078 /*@ 10079 MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B. 10080 10081 Neighbor-wise Collective 10082 10083 Input Parameters: 10084 + A - the left matrix 10085 . B - the right matrix 10086 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10087 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 10088 10089 Output Parameter: 10090 . C - the product matrix 10091 10092 Level: intermediate 10093 10094 Notes: 10095 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10096 10097 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call. 10098 10099 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB` 10100 10101 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10102 actually needed. 10103 10104 This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes 10105 which inherit from `MATSEQAIJ`. C will be of the same type as the input matrices. 10106 10107 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()` 10108 @*/ 10109 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10110 { 10111 PetscFunctionBegin; 10112 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C)); 10113 PetscFunctionReturn(PETSC_SUCCESS); 10114 } 10115 10116 /*@ 10117 MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C. 10118 10119 Neighbor-wise Collective 10120 10121 Input Parameters: 10122 + A - the left matrix 10123 . B - the middle matrix 10124 . C - the right matrix 10125 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10126 - 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 10127 if the result is a dense matrix this is irrelevant 10128 10129 Output Parameter: 10130 . D - the product matrix 10131 10132 Level: intermediate 10133 10134 Notes: 10135 Unless scall is `MAT_REUSE_MATRIX` D will be created. 10136 10137 `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call 10138 10139 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC` 10140 10141 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10142 actually needed. 10143 10144 If you have many matrices with the same non-zero structure to multiply, you 10145 should use `MAT_REUSE_MATRIX` in all calls but the first 10146 10147 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()` 10148 @*/ 10149 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D) 10150 { 10151 PetscFunctionBegin; 10152 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6); 10153 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10154 10155 if (scall == MAT_INITIAL_MATRIX) { 10156 PetscCall(MatProductCreate(A, B, C, D)); 10157 PetscCall(MatProductSetType(*D, MATPRODUCT_ABC)); 10158 PetscCall(MatProductSetAlgorithm(*D, "default")); 10159 PetscCall(MatProductSetFill(*D, fill)); 10160 10161 (*D)->product->api_user = PETSC_TRUE; 10162 PetscCall(MatProductSetFromOptions(*D)); 10163 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, 10164 ((PetscObject)C)->type_name); 10165 PetscCall(MatProductSymbolic(*D)); 10166 } else { /* user may change input matrices when REUSE */ 10167 PetscCall(MatProductReplaceMats(A, B, C, *D)); 10168 } 10169 PetscCall(MatProductNumeric(*D)); 10170 PetscFunctionReturn(PETSC_SUCCESS); 10171 } 10172 10173 /*@ 10174 MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators. 10175 10176 Collective 10177 10178 Input Parameters: 10179 + mat - the matrix 10180 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices) 10181 . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used) 10182 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10183 10184 Output Parameter: 10185 . matredundant - redundant matrix 10186 10187 Level: advanced 10188 10189 Notes: 10190 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 10191 original matrix has not changed from that last call to MatCreateRedundantMatrix(). 10192 10193 This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before 10194 calling it. 10195 10196 `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be. 10197 10198 .seealso: [](chapter_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubComm` 10199 @*/ 10200 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant) 10201 { 10202 MPI_Comm comm; 10203 PetscMPIInt size; 10204 PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs; 10205 Mat_Redundant *redund = NULL; 10206 PetscSubcomm psubcomm = NULL; 10207 MPI_Comm subcomm_in = subcomm; 10208 Mat *matseq; 10209 IS isrow, iscol; 10210 PetscBool newsubcomm = PETSC_FALSE; 10211 10212 PetscFunctionBegin; 10213 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10214 if (nsubcomm && reuse == MAT_REUSE_MATRIX) { 10215 PetscValidPointer(*matredundant, 5); 10216 PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5); 10217 } 10218 10219 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10220 if (size == 1 || nsubcomm == 1) { 10221 if (reuse == MAT_INITIAL_MATRIX) { 10222 PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant)); 10223 } else { 10224 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"); 10225 PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN)); 10226 } 10227 PetscFunctionReturn(PETSC_SUCCESS); 10228 } 10229 10230 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10231 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10232 MatCheckPreallocated(mat, 1); 10233 10234 PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0)); 10235 if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */ 10236 /* create psubcomm, then get subcomm */ 10237 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10238 PetscCallMPI(MPI_Comm_size(comm, &size)); 10239 PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size); 10240 10241 PetscCall(PetscSubcommCreate(comm, &psubcomm)); 10242 PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm)); 10243 PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS)); 10244 PetscCall(PetscSubcommSetFromOptions(psubcomm)); 10245 PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL)); 10246 newsubcomm = PETSC_TRUE; 10247 PetscCall(PetscSubcommDestroy(&psubcomm)); 10248 } 10249 10250 /* get isrow, iscol and a local sequential matrix matseq[0] */ 10251 if (reuse == MAT_INITIAL_MATRIX) { 10252 mloc_sub = PETSC_DECIDE; 10253 nloc_sub = PETSC_DECIDE; 10254 if (bs < 1) { 10255 PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M)); 10256 PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N)); 10257 } else { 10258 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M)); 10259 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N)); 10260 } 10261 PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm)); 10262 rstart = rend - mloc_sub; 10263 PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow)); 10264 PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol)); 10265 } else { /* reuse == MAT_REUSE_MATRIX */ 10266 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"); 10267 /* retrieve subcomm */ 10268 PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm)); 10269 redund = (*matredundant)->redundant; 10270 isrow = redund->isrow; 10271 iscol = redund->iscol; 10272 matseq = redund->matseq; 10273 } 10274 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq)); 10275 10276 /* get matredundant over subcomm */ 10277 if (reuse == MAT_INITIAL_MATRIX) { 10278 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant)); 10279 10280 /* create a supporting struct and attach it to C for reuse */ 10281 PetscCall(PetscNew(&redund)); 10282 (*matredundant)->redundant = redund; 10283 redund->isrow = isrow; 10284 redund->iscol = iscol; 10285 redund->matseq = matseq; 10286 if (newsubcomm) { 10287 redund->subcomm = subcomm; 10288 } else { 10289 redund->subcomm = MPI_COMM_NULL; 10290 } 10291 } else { 10292 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant)); 10293 } 10294 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 10295 if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) { 10296 PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE)); 10297 PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE)); 10298 } 10299 #endif 10300 PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0)); 10301 PetscFunctionReturn(PETSC_SUCCESS); 10302 } 10303 10304 /*@C 10305 MatGetMultiProcBlock - Create multiple 'parallel submatrices' from 10306 a given `Mat`. Each submatrix can span multiple procs. 10307 10308 Collective 10309 10310 Input Parameters: 10311 + mat - the matrix 10312 . subcomm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))` 10313 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10314 10315 Output Parameter: 10316 . subMat - parallel sub-matrices each spanning a given `subcomm` 10317 10318 Level: advanced 10319 10320 Notes: 10321 The submatrix partition across processors is dictated by `subComm` a 10322 communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm` 10323 is not restricted to be grouped with consecutive original ranks. 10324 10325 Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices 10326 map directly to the layout of the original matrix [wrt the local 10327 row,col partitioning]. So the original 'DiagonalMat' naturally maps 10328 into the 'DiagonalMat' of the `subMat`, hence it is used directly from 10329 the `subMat`. However the offDiagMat looses some columns - and this is 10330 reconstructed with `MatSetValues()` 10331 10332 This is used by `PCBJACOBI` when a single block spans multiple MPI ranks 10333 10334 .seealso: [](chapter_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI` 10335 @*/ 10336 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) 10337 { 10338 PetscMPIInt commsize, subCommSize; 10339 10340 PetscFunctionBegin; 10341 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize)); 10342 PetscCallMPI(MPI_Comm_size(subComm, &subCommSize)); 10343 PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize); 10344 10345 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"); 10346 PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10347 PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat); 10348 PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10349 PetscFunctionReturn(PETSC_SUCCESS); 10350 } 10351 10352 /*@ 10353 MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering 10354 10355 Not Collective 10356 10357 Input Parameters: 10358 + mat - matrix to extract local submatrix from 10359 . isrow - local row indices for submatrix 10360 - iscol - local column indices for submatrix 10361 10362 Output Parameter: 10363 . submat - the submatrix 10364 10365 Level: intermediate 10366 10367 Notes: 10368 `submat` should be disposed of with `MatRestoreLocalSubMatrix()`. 10369 10370 Depending on the format of `mat`, the returned submat may not implement `MatMult()`. Its communicator may be 10371 the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of `mat`'s. 10372 10373 `submat` always implements `MatSetValuesLocal()`. If `isrow` and `iscol` have the same block size, then 10374 `MatSetValuesBlockedLocal()` will also be implemented. 10375 10376 `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`. 10377 Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided. 10378 10379 .seealso: [](chapter_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()` 10380 @*/ 10381 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10382 { 10383 PetscFunctionBegin; 10384 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10385 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10386 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10387 PetscCheckSameComm(isrow, 2, iscol, 3); 10388 PetscValidPointer(submat, 4); 10389 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call"); 10390 10391 if (mat->ops->getlocalsubmatrix) { 10392 PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat); 10393 } else { 10394 PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat)); 10395 } 10396 PetscFunctionReturn(PETSC_SUCCESS); 10397 } 10398 10399 /*@ 10400 MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()` 10401 10402 Not Collective 10403 10404 Input Parameters: 10405 + mat - matrix to extract local submatrix from 10406 . isrow - local row indices for submatrix 10407 . iscol - local column indices for submatrix 10408 - submat - the submatrix 10409 10410 Level: intermediate 10411 10412 .seealso: [](chapter_matrices), `Mat`, `MatGetLocalSubMatrix()` 10413 @*/ 10414 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10415 { 10416 PetscFunctionBegin; 10417 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10418 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10419 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10420 PetscCheckSameComm(isrow, 2, iscol, 3); 10421 PetscValidPointer(submat, 4); 10422 if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4); 10423 10424 if (mat->ops->restorelocalsubmatrix) { 10425 PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat); 10426 } else { 10427 PetscCall(MatDestroy(submat)); 10428 } 10429 *submat = NULL; 10430 PetscFunctionReturn(PETSC_SUCCESS); 10431 } 10432 10433 /*@ 10434 MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix 10435 10436 Collective 10437 10438 Input Parameter: 10439 . mat - the matrix 10440 10441 Output Parameter: 10442 . is - if any rows have zero diagonals this contains the list of them 10443 10444 Level: developer 10445 10446 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10447 @*/ 10448 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is) 10449 { 10450 PetscFunctionBegin; 10451 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10452 PetscValidType(mat, 1); 10453 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10454 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10455 10456 if (!mat->ops->findzerodiagonals) { 10457 Vec diag; 10458 const PetscScalar *a; 10459 PetscInt *rows; 10460 PetscInt rStart, rEnd, r, nrow = 0; 10461 10462 PetscCall(MatCreateVecs(mat, &diag, NULL)); 10463 PetscCall(MatGetDiagonal(mat, diag)); 10464 PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd)); 10465 PetscCall(VecGetArrayRead(diag, &a)); 10466 for (r = 0; r < rEnd - rStart; ++r) 10467 if (a[r] == 0.0) ++nrow; 10468 PetscCall(PetscMalloc1(nrow, &rows)); 10469 nrow = 0; 10470 for (r = 0; r < rEnd - rStart; ++r) 10471 if (a[r] == 0.0) rows[nrow++] = r + rStart; 10472 PetscCall(VecRestoreArrayRead(diag, &a)); 10473 PetscCall(VecDestroy(&diag)); 10474 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is)); 10475 } else { 10476 PetscUseTypeMethod(mat, findzerodiagonals, is); 10477 } 10478 PetscFunctionReturn(PETSC_SUCCESS); 10479 } 10480 10481 /*@ 10482 MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size) 10483 10484 Collective 10485 10486 Input Parameter: 10487 . mat - the matrix 10488 10489 Output Parameter: 10490 . is - contains the list of rows with off block diagonal entries 10491 10492 Level: developer 10493 10494 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10495 @*/ 10496 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is) 10497 { 10498 PetscFunctionBegin; 10499 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10500 PetscValidType(mat, 1); 10501 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10502 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10503 10504 PetscUseTypeMethod(mat, findoffblockdiagonalentries, is); 10505 PetscFunctionReturn(PETSC_SUCCESS); 10506 } 10507 10508 /*@C 10509 MatInvertBlockDiagonal - Inverts the block diagonal entries. 10510 10511 Collective; No Fortran Support 10512 10513 Input Parameter: 10514 . mat - the matrix 10515 10516 Output Parameter: 10517 . values - the block inverses in column major order (FORTRAN-like) 10518 10519 Level: advanced 10520 10521 Notes: 10522 The size of the blocks is determined by the block size of the matrix. 10523 10524 The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case 10525 10526 The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size 10527 10528 .seealso: [](chapter_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()` 10529 @*/ 10530 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values) 10531 { 10532 PetscFunctionBegin; 10533 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10534 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10535 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10536 PetscUseTypeMethod(mat, invertblockdiagonal, values); 10537 PetscFunctionReturn(PETSC_SUCCESS); 10538 } 10539 10540 /*@C 10541 MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries. 10542 10543 Collective; No Fortran Support 10544 10545 Input Parameters: 10546 + mat - the matrix 10547 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()` 10548 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()` 10549 10550 Output Parameter: 10551 . values - the block inverses in column major order (FORTRAN-like) 10552 10553 Level: advanced 10554 10555 Notes: 10556 Use `MatInvertBlockDiagonal()` if all blocks have the same size 10557 10558 The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case 10559 10560 .seealso: [](chapter_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()` 10561 @*/ 10562 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values) 10563 { 10564 PetscFunctionBegin; 10565 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10566 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10567 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10568 PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values); 10569 PetscFunctionReturn(PETSC_SUCCESS); 10570 } 10571 10572 /*@ 10573 MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A 10574 10575 Collective 10576 10577 Input Parameters: 10578 + A - the matrix 10579 - C - matrix with inverted block diagonal of `A`. This matrix should be created and may have its type set. 10580 10581 Level: advanced 10582 10583 Note: 10584 The blocksize of the matrix is used to determine the blocks on the diagonal of `C` 10585 10586 .seealso: [](chapter_matrices), `Mat`, `MatInvertBlockDiagonal()` 10587 @*/ 10588 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C) 10589 { 10590 const PetscScalar *vals; 10591 PetscInt *dnnz; 10592 PetscInt m, rstart, rend, bs, i, j; 10593 10594 PetscFunctionBegin; 10595 PetscCall(MatInvertBlockDiagonal(A, &vals)); 10596 PetscCall(MatGetBlockSize(A, &bs)); 10597 PetscCall(MatGetLocalSize(A, &m, NULL)); 10598 PetscCall(MatSetLayouts(C, A->rmap, A->cmap)); 10599 PetscCall(PetscMalloc1(m / bs, &dnnz)); 10600 for (j = 0; j < m / bs; j++) dnnz[j] = 1; 10601 PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL)); 10602 PetscCall(PetscFree(dnnz)); 10603 PetscCall(MatGetOwnershipRange(C, &rstart, &rend)); 10604 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE)); 10605 for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES)); 10606 PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 10607 PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 10608 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE)); 10609 PetscFunctionReturn(PETSC_SUCCESS); 10610 } 10611 10612 /*@C 10613 MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created 10614 via `MatTransposeColoringCreate()`. 10615 10616 Collective 10617 10618 Input Parameter: 10619 . c - coloring context 10620 10621 Level: intermediate 10622 10623 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringCreate()` 10624 @*/ 10625 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c) 10626 { 10627 MatTransposeColoring matcolor = *c; 10628 10629 PetscFunctionBegin; 10630 if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS); 10631 if (--((PetscObject)matcolor)->refct > 0) { 10632 matcolor = NULL; 10633 PetscFunctionReturn(PETSC_SUCCESS); 10634 } 10635 10636 PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow)); 10637 PetscCall(PetscFree(matcolor->rows)); 10638 PetscCall(PetscFree(matcolor->den2sp)); 10639 PetscCall(PetscFree(matcolor->colorforcol)); 10640 PetscCall(PetscFree(matcolor->columns)); 10641 if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart)); 10642 PetscCall(PetscHeaderDestroy(c)); 10643 PetscFunctionReturn(PETSC_SUCCESS); 10644 } 10645 10646 /*@C 10647 MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which 10648 a `MatTransposeColoring` context has been created, computes a dense B^T by applying 10649 `MatTransposeColoring` to sparse B. 10650 10651 Collective 10652 10653 Input Parameters: 10654 + coloring - coloring context created with `MatTransposeColoringCreate()` 10655 - B - sparse matrix 10656 10657 Output Parameter: 10658 . Btdense - dense matrix B^T 10659 10660 Level: developer 10661 10662 Note: 10663 These are used internally for some implementations of `MatRARt()` 10664 10665 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()` 10666 @*/ 10667 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense) 10668 { 10669 PetscFunctionBegin; 10670 PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10671 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 10672 PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3); 10673 10674 PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense)); 10675 PetscFunctionReturn(PETSC_SUCCESS); 10676 } 10677 10678 /*@C 10679 MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which 10680 a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense 10681 in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix 10682 `Csp` from `Cden`. 10683 10684 Collective 10685 10686 Input Parameters: 10687 + matcoloring - coloring context created with `MatTransposeColoringCreate()` 10688 - Cden - matrix product of a sparse matrix and a dense matrix Btdense 10689 10690 Output Parameter: 10691 . Csp - sparse matrix 10692 10693 Level: developer 10694 10695 Note: 10696 These are used internally for some implementations of `MatRARt()` 10697 10698 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()` 10699 @*/ 10700 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp) 10701 { 10702 PetscFunctionBegin; 10703 PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10704 PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2); 10705 PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3); 10706 10707 PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp)); 10708 PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY)); 10709 PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY)); 10710 PetscFunctionReturn(PETSC_SUCCESS); 10711 } 10712 10713 /*@C 10714 MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T. 10715 10716 Collective 10717 10718 Input Parameters: 10719 + mat - the matrix product C 10720 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()` 10721 10722 Output Parameter: 10723 . color - the new coloring context 10724 10725 Level: intermediate 10726 10727 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`, 10728 `MatTransColoringApplyDenToSp()` 10729 @*/ 10730 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color) 10731 { 10732 MatTransposeColoring c; 10733 MPI_Comm comm; 10734 10735 PetscFunctionBegin; 10736 PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10737 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10738 PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL)); 10739 10740 c->ctype = iscoloring->ctype; 10741 PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c); 10742 10743 *color = c; 10744 PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10745 PetscFunctionReturn(PETSC_SUCCESS); 10746 } 10747 10748 /*@ 10749 MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the 10750 matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the 10751 same, otherwise it will be larger 10752 10753 Not Collective 10754 10755 Input Parameter: 10756 . A - the matrix 10757 10758 Output Parameter: 10759 . state - the current state 10760 10761 Level: intermediate 10762 10763 Notes: 10764 You can only compare states from two different calls to the SAME matrix, you cannot compare calls between 10765 different matrices 10766 10767 Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix 10768 10769 Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers. 10770 10771 .seealso: [](chapter_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()` 10772 @*/ 10773 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state) 10774 { 10775 PetscFunctionBegin; 10776 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10777 *state = mat->nonzerostate; 10778 PetscFunctionReturn(PETSC_SUCCESS); 10779 } 10780 10781 /*@ 10782 MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential 10783 matrices from each processor 10784 10785 Collective 10786 10787 Input Parameters: 10788 + comm - the communicators the parallel matrix will live on 10789 . seqmat - the input sequential matrices 10790 . n - number of local columns (or `PETSC_DECIDE`) 10791 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10792 10793 Output Parameter: 10794 . mpimat - the parallel matrix generated 10795 10796 Level: developer 10797 10798 Note: 10799 The number of columns of the matrix in EACH processor MUST be the same. 10800 10801 .seealso: [](chapter_matrices), `Mat` 10802 @*/ 10803 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat) 10804 { 10805 PetscMPIInt size; 10806 10807 PetscFunctionBegin; 10808 PetscCallMPI(MPI_Comm_size(comm, &size)); 10809 if (size == 1) { 10810 if (reuse == MAT_INITIAL_MATRIX) { 10811 PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat)); 10812 } else { 10813 PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN)); 10814 } 10815 PetscFunctionReturn(PETSC_SUCCESS); 10816 } 10817 10818 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"); 10819 10820 PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0)); 10821 PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat)); 10822 PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0)); 10823 PetscFunctionReturn(PETSC_SUCCESS); 10824 } 10825 10826 /*@ 10827 MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent ranks' ownership ranges. 10828 10829 Collective 10830 10831 Input Parameters: 10832 + A - the matrix to create subdomains from 10833 - N - requested number of subdomains 10834 10835 Output Parameters: 10836 + n - number of subdomains resulting on this rank 10837 - iss - `IS` list with indices of subdomains on this rank 10838 10839 Level: advanced 10840 10841 Note: 10842 The number of subdomains must be smaller than the communicator size 10843 10844 .seealso: [](chapter_matrices), `Mat`, `IS` 10845 @*/ 10846 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[]) 10847 { 10848 MPI_Comm comm, subcomm; 10849 PetscMPIInt size, rank, color; 10850 PetscInt rstart, rend, k; 10851 10852 PetscFunctionBegin; 10853 PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 10854 PetscCallMPI(MPI_Comm_size(comm, &size)); 10855 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 10856 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); 10857 *n = 1; 10858 k = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */ 10859 color = rank / k; 10860 PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm)); 10861 PetscCall(PetscMalloc1(1, iss)); 10862 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 10863 PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0])); 10864 PetscCallMPI(MPI_Comm_free(&subcomm)); 10865 PetscFunctionReturn(PETSC_SUCCESS); 10866 } 10867 10868 /*@ 10869 MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection. 10870 10871 If the interpolation and restriction operators are the same, uses `MatPtAP()`. 10872 If they are not the same, uses `MatMatMatMult()`. 10873 10874 Once the coarse grid problem is constructed, correct for interpolation operators 10875 that are not of full rank, which can legitimately happen in the case of non-nested 10876 geometric multigrid. 10877 10878 Input Parameters: 10879 + restrct - restriction operator 10880 . dA - fine grid matrix 10881 . interpolate - interpolation operator 10882 . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10883 - fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate 10884 10885 Output Parameter: 10886 . A - the Galerkin coarse matrix 10887 10888 Options Database Key: 10889 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used 10890 10891 Level: developer 10892 10893 .seealso: [](chapter_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()` 10894 @*/ 10895 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A) 10896 { 10897 IS zerorows; 10898 Vec diag; 10899 10900 PetscFunctionBegin; 10901 PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10902 /* Construct the coarse grid matrix */ 10903 if (interpolate == restrct) { 10904 PetscCall(MatPtAP(dA, interpolate, reuse, fill, A)); 10905 } else { 10906 PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A)); 10907 } 10908 10909 /* If the interpolation matrix is not of full rank, A will have zero rows. 10910 This can legitimately happen in the case of non-nested geometric multigrid. 10911 In that event, we set the rows of the matrix to the rows of the identity, 10912 ignoring the equations (as the RHS will also be zero). */ 10913 10914 PetscCall(MatFindZeroRows(*A, &zerorows)); 10915 10916 if (zerorows != NULL) { /* if there are any zero rows */ 10917 PetscCall(MatCreateVecs(*A, &diag, NULL)); 10918 PetscCall(MatGetDiagonal(*A, diag)); 10919 PetscCall(VecISSet(diag, zerorows, 1.0)); 10920 PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES)); 10921 PetscCall(VecDestroy(&diag)); 10922 PetscCall(ISDestroy(&zerorows)); 10923 } 10924 PetscFunctionReturn(PETSC_SUCCESS); 10925 } 10926 10927 /*@C 10928 MatSetOperation - Allows user to set a matrix operation for any matrix type 10929 10930 Logically Collective 10931 10932 Input Parameters: 10933 + mat - the matrix 10934 . op - the name of the operation 10935 - f - the function that provides the operation 10936 10937 Level: developer 10938 10939 Usage: 10940 .vb 10941 extern PetscErrorCode usermult(Mat, Vec, Vec); 10942 10943 PetscCall(MatCreateXXX(comm, ..., &A)); 10944 PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFunction)usermult)); 10945 .ve 10946 10947 Notes: 10948 See the file `include/petscmat.h` for a complete list of matrix 10949 operations, which all have the form MATOP_<OPERATION>, where 10950 <OPERATION> is the name (in all capital letters) of the 10951 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 10952 10953 All user-provided functions (except for `MATOP_DESTROY`) should have the same calling 10954 sequence as the usual matrix interface routines, since they 10955 are intended to be accessed via the usual matrix interface 10956 routines, e.g., 10957 .vb 10958 MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec) 10959 .ve 10960 10961 In particular each function MUST return `PETSC_SUCCESS` on success and 10962 nonzero on failure. 10963 10964 This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type. 10965 10966 .seealso: [](chapter_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()` 10967 @*/ 10968 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void)) 10969 { 10970 PetscFunctionBegin; 10971 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10972 if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view; 10973 (((void (**)(void))mat->ops)[op]) = f; 10974 PetscFunctionReturn(PETSC_SUCCESS); 10975 } 10976 10977 /*@C 10978 MatGetOperation - Gets a matrix operation for any matrix type. 10979 10980 Not Collective 10981 10982 Input Parameters: 10983 + mat - the matrix 10984 - op - the name of the operation 10985 10986 Output Parameter: 10987 . f - the function that provides the operation 10988 10989 Level: developer 10990 10991 Usage: 10992 .vb 10993 PetscErrorCode (*usermult)(Mat, Vec, Vec); 10994 MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult); 10995 .ve 10996 10997 Notes: 10998 See the file include/petscmat.h for a complete list of matrix 10999 operations, which all have the form MATOP_<OPERATION>, where 11000 <OPERATION> is the name (in all capital letters) of the 11001 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11002 11003 This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type. 11004 11005 .seealso: [](chapter_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()` 11006 @*/ 11007 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void)) 11008 { 11009 PetscFunctionBegin; 11010 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11011 *f = (((void (**)(void))mat->ops)[op]); 11012 PetscFunctionReturn(PETSC_SUCCESS); 11013 } 11014 11015 /*@ 11016 MatHasOperation - Determines whether the given matrix supports the particular operation. 11017 11018 Not Collective 11019 11020 Input Parameters: 11021 + mat - the matrix 11022 - op - the operation, for example, `MATOP_GET_DIAGONAL` 11023 11024 Output Parameter: 11025 . has - either `PETSC_TRUE` or `PETSC_FALSE` 11026 11027 Level: advanced 11028 11029 Note: 11030 See `MatSetOperation()` for additional discussion on naming convention and usage of `op`. 11031 11032 .seealso: [](chapter_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()` 11033 @*/ 11034 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has) 11035 { 11036 PetscFunctionBegin; 11037 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11038 PetscValidBoolPointer(has, 3); 11039 if (mat->ops->hasoperation) { 11040 PetscUseTypeMethod(mat, hasoperation, op, has); 11041 } else { 11042 if (((void **)mat->ops)[op]) *has = PETSC_TRUE; 11043 else { 11044 *has = PETSC_FALSE; 11045 if (op == MATOP_CREATE_SUBMATRIX) { 11046 PetscMPIInt size; 11047 11048 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 11049 if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has)); 11050 } 11051 } 11052 } 11053 PetscFunctionReturn(PETSC_SUCCESS); 11054 } 11055 11056 /*@ 11057 MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent 11058 11059 Collective 11060 11061 Input Parameter: 11062 . mat - the matrix 11063 11064 Output Parameter: 11065 . cong - either `PETSC_TRUE` or `PETSC_FALSE` 11066 11067 Level: beginner 11068 11069 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout` 11070 @*/ 11071 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong) 11072 { 11073 PetscFunctionBegin; 11074 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11075 PetscValidType(mat, 1); 11076 PetscValidBoolPointer(cong, 2); 11077 if (!mat->rmap || !mat->cmap) { 11078 *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE; 11079 PetscFunctionReturn(PETSC_SUCCESS); 11080 } 11081 if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */ 11082 PetscCall(PetscLayoutSetUp(mat->rmap)); 11083 PetscCall(PetscLayoutSetUp(mat->cmap)); 11084 PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong)); 11085 if (*cong) mat->congruentlayouts = 1; 11086 else mat->congruentlayouts = 0; 11087 } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE; 11088 PetscFunctionReturn(PETSC_SUCCESS); 11089 } 11090 11091 PetscErrorCode MatSetInf(Mat A) 11092 { 11093 PetscFunctionBegin; 11094 PetscUseTypeMethod(A, setinf); 11095 PetscFunctionReturn(PETSC_SUCCESS); 11096 } 11097 11098 /*@C 11099 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 11100 and possibly removes small values from the graph structure. 11101 11102 Collective 11103 11104 Input Parameters: 11105 + A - the matrix 11106 . sym - `PETSC_TRUE` indicates that the graph should be symmetrized 11107 . scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry 11108 - filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value 11109 11110 Output Parameter: 11111 . graph - the resulting graph 11112 11113 Level: advanced 11114 11115 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `PCGAMG` 11116 @*/ 11117 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph) 11118 { 11119 PetscFunctionBegin; 11120 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11121 PetscValidType(A, 1); 11122 PetscValidLogicalCollectiveBool(A, scale, 3); 11123 PetscValidPointer(graph, 5); 11124 PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph); 11125 PetscFunctionReturn(PETSC_SUCCESS); 11126 } 11127 11128 /*@ 11129 MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place, 11130 meaning the same memory is used for the matrix, and no new memory is allocated. 11131 11132 Collective 11133 11134 Input Parameter: 11135 . A - the matrix 11136 11137 Level: intermediate 11138 11139 Developer Note: 11140 The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end 11141 of the arrays in the data structure are unneeded. 11142 11143 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatChop()` 11144 @*/ 11145 PetscErrorCode MatEliminateZeros(Mat A) 11146 { 11147 PetscFunctionBegin; 11148 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11149 PetscUseTypeMethod(A, eliminatezeros); 11150 PetscFunctionReturn(PETSC_SUCCESS); 11151 } 11152