1 /* 2 This is where the abstract matrix operations are defined 3 Portions of this code are under: 4 Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved. 5 */ 6 7 #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/ 8 #include <petsc/private/isimpl.h> 9 #include <petsc/private/vecimpl.h> 10 11 /* Logging support */ 12 PetscClassId MAT_CLASSID; 13 PetscClassId MAT_COLORING_CLASSID; 14 PetscClassId MAT_FDCOLORING_CLASSID; 15 PetscClassId MAT_TRANSPOSECOLORING_CLASSID; 16 17 PetscLogEvent MAT_Mult, MAT_MultAdd, MAT_MultTranspose; 18 PetscLogEvent MAT_MultTransposeAdd, MAT_Solve, MAT_Solves, MAT_SolveAdd, MAT_SolveTranspose, MAT_MatSolve, MAT_MatTrSolve; 19 PetscLogEvent MAT_SolveTransposeAdd, MAT_SOR, MAT_ForwardSolve, MAT_BackwardSolve, MAT_LUFactor, MAT_LUFactorSymbolic; 20 PetscLogEvent MAT_LUFactorNumeric, MAT_CholeskyFactor, MAT_CholeskyFactorSymbolic, MAT_CholeskyFactorNumeric, MAT_ILUFactor; 21 PetscLogEvent MAT_ILUFactorSymbolic, MAT_ICCFactorSymbolic, MAT_Copy, MAT_Convert, MAT_Scale, MAT_AssemblyBegin; 22 PetscLogEvent MAT_QRFactorNumeric, MAT_QRFactorSymbolic, MAT_QRFactor; 23 PetscLogEvent MAT_AssemblyEnd, MAT_SetValues, MAT_GetValues, MAT_GetRow, MAT_GetRowIJ, MAT_CreateSubMats, MAT_GetOrdering, MAT_RedundantMat, MAT_GetSeqNonzeroStructure; 24 PetscLogEvent MAT_IncreaseOverlap, MAT_Partitioning, MAT_PartitioningND, MAT_Coarsen, MAT_ZeroEntries, MAT_Load, MAT_View, MAT_AXPY, MAT_FDColoringCreate; 25 PetscLogEvent MAT_FDColoringSetUp, MAT_FDColoringApply, MAT_Transpose, MAT_FDColoringFunction, MAT_CreateSubMat; 26 PetscLogEvent MAT_TransposeColoringCreate; 27 PetscLogEvent MAT_MatMult, MAT_MatMultSymbolic, MAT_MatMultNumeric; 28 PetscLogEvent MAT_PtAP, MAT_PtAPSymbolic, MAT_PtAPNumeric, MAT_RARt, MAT_RARtSymbolic, MAT_RARtNumeric; 29 PetscLogEvent MAT_MatTransposeMult, MAT_MatTransposeMultSymbolic, MAT_MatTransposeMultNumeric; 30 PetscLogEvent MAT_TransposeMatMult, MAT_TransposeMatMultSymbolic, MAT_TransposeMatMultNumeric; 31 PetscLogEvent MAT_MatMatMult, MAT_MatMatMultSymbolic, MAT_MatMatMultNumeric; 32 PetscLogEvent MAT_MultHermitianTranspose, MAT_MultHermitianTransposeAdd; 33 PetscLogEvent MAT_Getsymtransreduced, MAT_GetBrowsOfAcols; 34 PetscLogEvent MAT_GetBrowsOfAocols, MAT_Getlocalmat, MAT_Getlocalmatcondensed, MAT_Seqstompi, MAT_Seqstompinum, MAT_Seqstompisym; 35 PetscLogEvent MAT_GetMultiProcBlock; 36 PetscLogEvent MAT_CUSPARSECopyToGPU, MAT_CUSPARSECopyFromGPU, MAT_CUSPARSEGenerateTranspose, MAT_CUSPARSESolveAnalysis; 37 PetscLogEvent MAT_HIPSPARSECopyToGPU, MAT_HIPSPARSECopyFromGPU, MAT_HIPSPARSEGenerateTranspose, MAT_HIPSPARSESolveAnalysis; 38 PetscLogEvent MAT_PreallCOO, MAT_SetVCOO; 39 PetscLogEvent MAT_SetValuesBatch; 40 PetscLogEvent MAT_ViennaCLCopyToGPU; 41 PetscLogEvent MAT_CUDACopyToGPU; 42 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU; 43 PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom; 44 PetscLogEvent MAT_FactorFactS, MAT_FactorInvS; 45 PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights; 46 PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR; 47 48 const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL}; 49 50 /*@ 51 MatSetRandom - Sets all components of a matrix to random numbers. 52 53 Logically Collective 54 55 Input Parameters: 56 + x - the matrix 57 - rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or `NULL` and 58 it will create one internally. 59 60 Example: 61 .vb 62 PetscRandomCreate(PETSC_COMM_WORLD,&rctx); 63 MatSetRandom(x,rctx); 64 PetscRandomDestroy(rctx); 65 .ve 66 67 Level: intermediate 68 69 Notes: 70 For sparse matrices that have been preallocated but not been assembled it randomly selects appropriate locations, 71 72 for sparse matrices that already have locations it fills the locations with random numbers. 73 74 It generates an error if used on sparse matrices that have not been preallocated. 75 76 .seealso: [](ch_matrices), `Mat`, `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomDestroy()` 77 @*/ 78 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx) 79 { 80 PetscRandom randObj = NULL; 81 82 PetscFunctionBegin; 83 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 84 if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2); 85 PetscValidType(x, 1); 86 MatCheckPreallocated(x, 1); 87 88 if (!rctx) { 89 MPI_Comm comm; 90 PetscCall(PetscObjectGetComm((PetscObject)x, &comm)); 91 PetscCall(PetscRandomCreate(comm, &randObj)); 92 PetscCall(PetscRandomSetType(randObj, x->defaultrandtype)); 93 PetscCall(PetscRandomSetFromOptions(randObj)); 94 rctx = randObj; 95 } 96 PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0)); 97 PetscUseTypeMethod(x, setrandom, rctx); 98 PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0)); 99 100 PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY)); 101 PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY)); 102 PetscCall(PetscRandomDestroy(&randObj)); 103 PetscFunctionReturn(PETSC_SUCCESS); 104 } 105 106 /*@ 107 MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in 108 109 Logically Collective 110 111 Input Parameter: 112 . mat - the factored matrix 113 114 Output Parameters: 115 + pivot - the pivot value computed 116 - row - the row that the zero pivot occurred. This row value must be interpreted carefully due to row reorderings and which processes 117 the share the matrix 118 119 Level: advanced 120 121 Notes: 122 This routine does not work for factorizations done with external packages. 123 124 This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT` 125 126 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 127 128 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, 129 `MAT_FACTOR_NUMERIC_ZEROPIVOT` 130 @*/ 131 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row) 132 { 133 PetscFunctionBegin; 134 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 135 PetscValidRealPointer(pivot, 2); 136 PetscValidIntPointer(row, 3); 137 *pivot = mat->factorerror_zeropivot_value; 138 *row = mat->factorerror_zeropivot_row; 139 PetscFunctionReturn(PETSC_SUCCESS); 140 } 141 142 /*@ 143 MatFactorGetError - gets the error code from a factorization 144 145 Logically Collective 146 147 Input Parameter: 148 . mat - the factored matrix 149 150 Output Parameter: 151 . err - the error code 152 153 Level: advanced 154 155 Note: 156 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 157 158 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, 159 `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, `MatFactorError` 160 @*/ 161 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err) 162 { 163 PetscFunctionBegin; 164 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 165 PetscValidPointer(err, 2); 166 *err = mat->factorerrortype; 167 PetscFunctionReturn(PETSC_SUCCESS); 168 } 169 170 /*@ 171 MatFactorClearError - clears the error code in a factorization 172 173 Logically Collective 174 175 Input Parameter: 176 . mat - the factored matrix 177 178 Level: developer 179 180 Note: 181 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 182 183 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`, 184 `MatGetErrorCode()`, `MatFactorError` 185 @*/ 186 PetscErrorCode MatFactorClearError(Mat mat) 187 { 188 PetscFunctionBegin; 189 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 190 mat->factorerrortype = MAT_FACTOR_NOERROR; 191 mat->factorerror_zeropivot_value = 0.0; 192 mat->factorerror_zeropivot_row = 0; 193 PetscFunctionReturn(PETSC_SUCCESS); 194 } 195 196 PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero) 197 { 198 Vec r, l; 199 const PetscScalar *al; 200 PetscInt i, nz, gnz, N, n; 201 202 PetscFunctionBegin; 203 PetscCall(MatCreateVecs(mat, &r, &l)); 204 if (!cols) { /* nonzero rows */ 205 PetscCall(MatGetSize(mat, &N, NULL)); 206 PetscCall(MatGetLocalSize(mat, &n, NULL)); 207 PetscCall(VecSet(l, 0.0)); 208 PetscCall(VecSetRandom(r, NULL)); 209 PetscCall(MatMult(mat, r, l)); 210 PetscCall(VecGetArrayRead(l, &al)); 211 } else { /* nonzero columns */ 212 PetscCall(MatGetSize(mat, NULL, &N)); 213 PetscCall(MatGetLocalSize(mat, NULL, &n)); 214 PetscCall(VecSet(r, 0.0)); 215 PetscCall(VecSetRandom(l, NULL)); 216 PetscCall(MatMultTranspose(mat, l, r)); 217 PetscCall(VecGetArrayRead(r, &al)); 218 } 219 if (tol <= 0.0) { 220 for (i = 0, nz = 0; i < n; i++) 221 if (al[i] != 0.0) nz++; 222 } else { 223 for (i = 0, nz = 0; i < n; i++) 224 if (PetscAbsScalar(al[i]) > tol) nz++; 225 } 226 PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 227 if (gnz != N) { 228 PetscInt *nzr; 229 PetscCall(PetscMalloc1(nz, &nzr)); 230 if (nz) { 231 if (tol < 0) { 232 for (i = 0, nz = 0; i < n; i++) 233 if (al[i] != 0.0) nzr[nz++] = i; 234 } else { 235 for (i = 0, nz = 0; i < n; i++) 236 if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i; 237 } 238 } 239 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero)); 240 } else *nonzero = NULL; 241 if (!cols) { /* nonzero rows */ 242 PetscCall(VecRestoreArrayRead(l, &al)); 243 } else { 244 PetscCall(VecRestoreArrayRead(r, &al)); 245 } 246 PetscCall(VecDestroy(&l)); 247 PetscCall(VecDestroy(&r)); 248 PetscFunctionReturn(PETSC_SUCCESS); 249 } 250 251 /*@ 252 MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix 253 254 Input Parameter: 255 . mat - the matrix 256 257 Output Parameter: 258 . keptrows - the rows that are not completely zero 259 260 Level: intermediate 261 262 Note: 263 `keptrows` is set to `NULL` if all rows are nonzero. 264 265 .seealso: [](ch_matrices), `Mat`, `MatFindZeroRows()` 266 @*/ 267 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows) 268 { 269 PetscFunctionBegin; 270 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 271 PetscValidType(mat, 1); 272 PetscValidPointer(keptrows, 2); 273 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 274 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 275 if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows); 276 else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows)); 277 PetscFunctionReturn(PETSC_SUCCESS); 278 } 279 280 /*@ 281 MatFindZeroRows - Locate all rows that are completely zero in the matrix 282 283 Input Parameter: 284 . mat - the matrix 285 286 Output Parameter: 287 . zerorows - the rows that are completely zero 288 289 Level: intermediate 290 291 Note: 292 `zerorows` is set to `NULL` if no rows are zero. 293 294 .seealso: [](ch_matrices), `Mat`, `MatFindNonzeroRows()` 295 @*/ 296 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows) 297 { 298 IS keptrows; 299 PetscInt m, n; 300 301 PetscFunctionBegin; 302 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 303 PetscValidType(mat, 1); 304 PetscValidPointer(zerorows, 2); 305 PetscCall(MatFindNonzeroRows(mat, &keptrows)); 306 /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows. 307 In keeping with this convention, we set zerorows to NULL if there are no zero 308 rows. */ 309 if (keptrows == NULL) { 310 *zerorows = NULL; 311 } else { 312 PetscCall(MatGetOwnershipRange(mat, &m, &n)); 313 PetscCall(ISComplement(keptrows, m, n, zerorows)); 314 PetscCall(ISDestroy(&keptrows)); 315 } 316 PetscFunctionReturn(PETSC_SUCCESS); 317 } 318 319 /*@ 320 MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling 321 322 Not Collective 323 324 Input Parameter: 325 . A - the matrix 326 327 Output Parameter: 328 . a - the diagonal part (which is a SEQUENTIAL matrix) 329 330 Level: advanced 331 332 Notes: 333 See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix. 334 335 Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation. 336 337 .seealso: [](ch_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ` 338 @*/ 339 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a) 340 { 341 PetscFunctionBegin; 342 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 343 PetscValidType(A, 1); 344 PetscValidPointer(a, 2); 345 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 346 if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a); 347 else { 348 PetscMPIInt size; 349 350 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 351 PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name); 352 *a = A; 353 } 354 PetscFunctionReturn(PETSC_SUCCESS); 355 } 356 357 /*@ 358 MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries. 359 360 Collective 361 362 Input Parameter: 363 . mat - the matrix 364 365 Output Parameter: 366 . trace - the sum of the diagonal entries 367 368 Level: advanced 369 370 .seealso: [](ch_matrices), `Mat` 371 @*/ 372 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace) 373 { 374 Vec diag; 375 376 PetscFunctionBegin; 377 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 378 PetscValidScalarPointer(trace, 2); 379 PetscCall(MatCreateVecs(mat, &diag, NULL)); 380 PetscCall(MatGetDiagonal(mat, diag)); 381 PetscCall(VecSum(diag, trace)); 382 PetscCall(VecDestroy(&diag)); 383 PetscFunctionReturn(PETSC_SUCCESS); 384 } 385 386 /*@ 387 MatRealPart - Zeros out the imaginary part of the matrix 388 389 Logically Collective 390 391 Input Parameter: 392 . mat - the matrix 393 394 Level: advanced 395 396 .seealso: [](ch_matrices), `Mat`, `MatImaginaryPart()` 397 @*/ 398 PetscErrorCode MatRealPart(Mat mat) 399 { 400 PetscFunctionBegin; 401 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 402 PetscValidType(mat, 1); 403 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 404 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 405 MatCheckPreallocated(mat, 1); 406 PetscUseTypeMethod(mat, realpart); 407 PetscFunctionReturn(PETSC_SUCCESS); 408 } 409 410 /*@C 411 MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix 412 413 Collective 414 415 Input Parameter: 416 . mat - the matrix 417 418 Output Parameters: 419 + nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each block) 420 - ghosts - the global indices of the ghost points 421 422 Level: advanced 423 424 Note: 425 `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()` 426 427 .seealso: [](ch_matrices), `Mat`, `VecCreateGhost()` 428 @*/ 429 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[]) 430 { 431 PetscFunctionBegin; 432 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 433 PetscValidType(mat, 1); 434 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 435 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 436 if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts); 437 else { 438 if (nghosts) *nghosts = 0; 439 if (ghosts) *ghosts = NULL; 440 } 441 PetscFunctionReturn(PETSC_SUCCESS); 442 } 443 444 /*@ 445 MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part 446 447 Logically Collective 448 449 Input Parameter: 450 . mat - the matrix 451 452 Level: advanced 453 454 .seealso: [](ch_matrices), `Mat`, `MatRealPart()` 455 @*/ 456 PetscErrorCode MatImaginaryPart(Mat mat) 457 { 458 PetscFunctionBegin; 459 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 460 PetscValidType(mat, 1); 461 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 462 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 463 MatCheckPreallocated(mat, 1); 464 PetscUseTypeMethod(mat, imaginarypart); 465 PetscFunctionReturn(PETSC_SUCCESS); 466 } 467 468 /*@ 469 MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices) 470 471 Not Collective 472 473 Input Parameter: 474 . mat - the matrix 475 476 Output Parameters: 477 + missing - is any diagonal missing 478 - dd - first diagonal entry that is missing (optional) on this process 479 480 Level: advanced 481 482 .seealso: [](ch_matrices), `Mat` 483 @*/ 484 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd) 485 { 486 PetscFunctionBegin; 487 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 488 PetscValidType(mat, 1); 489 PetscValidBoolPointer(missing, 2); 490 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name); 491 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 492 PetscUseTypeMethod(mat, missingdiagonal, missing, dd); 493 PetscFunctionReturn(PETSC_SUCCESS); 494 } 495 496 /*@C 497 MatGetRow - Gets a row of a matrix. You MUST call `MatRestoreRow()` 498 for each row that you get to ensure that your application does 499 not bleed memory. 500 501 Not Collective 502 503 Input Parameters: 504 + mat - the matrix 505 - row - the row to get 506 507 Output Parameters: 508 + ncols - if not `NULL`, the number of nonzeros in the row 509 . cols - if not `NULL`, the column numbers 510 - vals - if not `NULL`, the values 511 512 Level: advanced 513 514 Notes: 515 This routine is provided for people who need to have direct access 516 to the structure of a matrix. We hope that we provide enough 517 high-level matrix routines that few users will need it. 518 519 `MatGetRow()` always returns 0-based column indices, regardless of 520 whether the internal representation is 0-based (default) or 1-based. 521 522 For better efficiency, set cols and/or vals to `NULL` if you do 523 not wish to extract these quantities. 524 525 The user can only examine the values extracted with `MatGetRow()`; 526 the values cannot be altered. To change the matrix entries, one 527 must use `MatSetValues()`. 528 529 You can only have one call to `MatGetRow()` outstanding for a particular 530 matrix at a time, per processor. `MatGetRow()` can only obtain rows 531 associated with the given processor, it cannot get rows from the 532 other processors; for that we suggest using `MatCreateSubMatrices()`, then 533 MatGetRow() on the submatrix. The row index passed to `MatGetRow()` 534 is in the global number of rows. 535 536 Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix. 537 538 Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly. 539 540 Fortran Notes: 541 The calling sequence is 542 .vb 543 MatGetRow(matrix,row,ncols,cols,values,ierr) 544 Mat matrix (input) 545 integer row (input) 546 integer ncols (output) 547 integer cols(maxcols) (output) 548 double precision (or double complex) values(maxcols) output 549 .ve 550 where maxcols >= maximum nonzeros in any row of the matrix. 551 552 Caution: 553 Do not try to change the contents of the output arrays (`cols` and `vals`). 554 In some cases, this may corrupt the matrix. 555 556 .seealso: [](ch_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()` 557 @*/ 558 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 559 { 560 PetscInt incols; 561 562 PetscFunctionBegin; 563 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 564 PetscValidType(mat, 1); 565 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 566 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 567 MatCheckPreallocated(mat, 1); 568 PetscCheck(row >= mat->rmap->rstart && row < mat->rmap->rend, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Only for local rows, %" PetscInt_FMT " not in [%" PetscInt_FMT ",%" PetscInt_FMT ")", row, mat->rmap->rstart, mat->rmap->rend); 569 PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0)); 570 PetscUseTypeMethod(mat, getrow, row, &incols, (PetscInt **)cols, (PetscScalar **)vals); 571 if (ncols) *ncols = incols; 572 PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0)); 573 PetscFunctionReturn(PETSC_SUCCESS); 574 } 575 576 /*@ 577 MatConjugate - replaces the matrix values with their complex conjugates 578 579 Logically Collective 580 581 Input Parameter: 582 . mat - the matrix 583 584 Level: advanced 585 586 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()` 587 @*/ 588 PetscErrorCode MatConjugate(Mat mat) 589 { 590 PetscFunctionBegin; 591 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 592 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 593 if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) { 594 PetscUseTypeMethod(mat, conjugate); 595 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 596 } 597 PetscFunctionReturn(PETSC_SUCCESS); 598 } 599 600 /*@C 601 MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`. 602 603 Not Collective 604 605 Input Parameters: 606 + mat - the matrix 607 . row - the row to get 608 . ncols - the number of nonzeros 609 . cols - the columns of the nonzeros 610 - vals - if nonzero the column values 611 612 Level: advanced 613 614 Notes: 615 This routine should be called after you have finished examining the entries. 616 617 This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental 618 us of the array after it has been restored. If you pass `NULL`, it will 619 not zero the pointers. Use of `cols` or `vals` after `MatRestoreRow()` is invalid. 620 621 Fortran Notes: 622 The calling sequence is 623 .vb 624 MatRestoreRow(matrix,row,ncols,cols,values,ierr) 625 Mat matrix (input) 626 integer row (input) 627 integer ncols (output) 628 integer cols(maxcols) (output) 629 double precision (or double complex) values(maxcols) output 630 .ve 631 Where maxcols >= maximum nonzeros in any row of the matrix. 632 633 In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()` 634 before another call to `MatGetRow()` can be made. 635 636 .seealso: [](ch_matrices), `Mat`, `MatGetRow()` 637 @*/ 638 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 639 { 640 PetscFunctionBegin; 641 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 642 if (ncols) PetscValidIntPointer(ncols, 3); 643 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 644 if (!mat->ops->restorerow) PetscFunctionReturn(PETSC_SUCCESS); 645 PetscUseTypeMethod(mat, restorerow, row, ncols, (PetscInt **)cols, (PetscScalar **)vals); 646 if (ncols) *ncols = 0; 647 if (cols) *cols = NULL; 648 if (vals) *vals = NULL; 649 PetscFunctionReturn(PETSC_SUCCESS); 650 } 651 652 /*@ 653 MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 654 You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag. 655 656 Not Collective 657 658 Input Parameter: 659 . mat - the matrix 660 661 Level: advanced 662 663 Note: 664 The flag is to ensure that users are aware that `MatGetRow()` only provides the upper triangular part of the row for the matrices in `MATSBAIJ` format. 665 666 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()` 667 @*/ 668 PetscErrorCode MatGetRowUpperTriangular(Mat mat) 669 { 670 PetscFunctionBegin; 671 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 672 PetscValidType(mat, 1); 673 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 674 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 675 MatCheckPreallocated(mat, 1); 676 if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS); 677 PetscUseTypeMethod(mat, getrowuppertriangular); 678 PetscFunctionReturn(PETSC_SUCCESS); 679 } 680 681 /*@ 682 MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 683 684 Not Collective 685 686 Input Parameter: 687 . mat - the matrix 688 689 Level: advanced 690 691 Note: 692 This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`. 693 694 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()` 695 @*/ 696 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat) 697 { 698 PetscFunctionBegin; 699 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 700 PetscValidType(mat, 1); 701 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 702 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 703 MatCheckPreallocated(mat, 1); 704 if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS); 705 PetscUseTypeMethod(mat, restorerowuppertriangular); 706 PetscFunctionReturn(PETSC_SUCCESS); 707 } 708 709 /*@C 710 MatSetOptionsPrefix - Sets the prefix used for searching for all 711 `Mat` options in the database. 712 713 Logically Collective 714 715 Input Parameters: 716 + A - the matrix 717 - prefix - the prefix to prepend to all option names 718 719 Level: advanced 720 721 Notes: 722 A hyphen (-) must NOT be given at the beginning of the prefix name. 723 The first character of all runtime options is AUTOMATICALLY the hyphen. 724 725 This is NOT used for options for the factorization of the matrix. Normally the 726 prefix is automatically passed in from the PC calling the factorization. To set 727 it directly use `MatSetOptionsPrefixFactor()` 728 729 .seealso: [](ch_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()` 730 @*/ 731 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[]) 732 { 733 PetscFunctionBegin; 734 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 735 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix)); 736 PetscFunctionReturn(PETSC_SUCCESS); 737 } 738 739 /*@C 740 MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for 741 for matrices created with `MatGetFactor()` 742 743 Logically Collective 744 745 Input Parameters: 746 + A - the matrix 747 - prefix - the prefix to prepend to all option names for the factored matrix 748 749 Level: developer 750 751 Notes: 752 A hyphen (-) must NOT be given at the beginning of the prefix name. 753 The first character of all runtime options is AUTOMATICALLY the hyphen. 754 755 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 756 it directly when not using `KSP`/`PC` use `MatSetOptionsPrefixFactor()` 757 758 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()` 759 @*/ 760 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[]) 761 { 762 PetscFunctionBegin; 763 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 764 if (prefix) { 765 PetscValidCharPointer(prefix, 2); 766 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 767 if (prefix != A->factorprefix) { 768 PetscCall(PetscFree(A->factorprefix)); 769 PetscCall(PetscStrallocpy(prefix, &A->factorprefix)); 770 } 771 } else PetscCall(PetscFree(A->factorprefix)); 772 PetscFunctionReturn(PETSC_SUCCESS); 773 } 774 775 /*@C 776 MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for 777 for matrices created with `MatGetFactor()` 778 779 Logically Collective 780 781 Input Parameters: 782 + A - the matrix 783 - prefix - the prefix to prepend to all option names for the factored matrix 784 785 Level: developer 786 787 Notes: 788 A hyphen (-) must NOT be given at the beginning of the prefix name. 789 The first character of all runtime options is AUTOMATICALLY the hyphen. 790 791 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 792 it directly when not using `KSP`/`PC` use `MatAppendOptionsPrefixFactor()` 793 794 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`, 795 `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`, 796 `MatSetOptionsPrefix()` 797 @*/ 798 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[]) 799 { 800 size_t len1, len2, new_len; 801 802 PetscFunctionBegin; 803 PetscValidHeader(A, 1); 804 if (!prefix) PetscFunctionReturn(PETSC_SUCCESS); 805 if (!A->factorprefix) { 806 PetscCall(MatSetOptionsPrefixFactor(A, prefix)); 807 PetscFunctionReturn(PETSC_SUCCESS); 808 } 809 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 810 811 PetscCall(PetscStrlen(A->factorprefix, &len1)); 812 PetscCall(PetscStrlen(prefix, &len2)); 813 new_len = len1 + len2 + 1; 814 PetscCall(PetscRealloc(new_len * sizeof(*(A->factorprefix)), &A->factorprefix)); 815 PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1)); 816 PetscFunctionReturn(PETSC_SUCCESS); 817 } 818 819 /*@C 820 MatAppendOptionsPrefix - Appends to the prefix used for searching for all 821 matrix options in the database. 822 823 Logically Collective 824 825 Input Parameters: 826 + A - the matrix 827 - prefix - the prefix to prepend to all option names 828 829 Level: advanced 830 831 Note: 832 A hyphen (-) must NOT be given at the beginning of the prefix name. 833 The first character of all runtime options is AUTOMATICALLY the hyphen. 834 835 .seealso: [](ch_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()` 836 @*/ 837 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[]) 838 { 839 PetscFunctionBegin; 840 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 841 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix)); 842 PetscFunctionReturn(PETSC_SUCCESS); 843 } 844 845 /*@C 846 MatGetOptionsPrefix - Gets the prefix used for searching for all 847 matrix options in the database. 848 849 Not Collective 850 851 Input Parameter: 852 . A - the matrix 853 854 Output Parameter: 855 . prefix - pointer to the prefix string used 856 857 Level: advanced 858 859 Fortran Notes: 860 The user should pass in a string `prefix` of 861 sufficient length to hold the prefix. 862 863 .seealso: [](ch_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()` 864 @*/ 865 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[]) 866 { 867 PetscFunctionBegin; 868 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 869 PetscValidPointer(prefix, 2); 870 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix)); 871 PetscFunctionReturn(PETSC_SUCCESS); 872 } 873 874 /*@ 875 MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by users. 876 877 Collective 878 879 Input Parameter: 880 . A - the matrix 881 882 Level: beginner 883 884 Notes: 885 The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`. 886 887 Users can reset the preallocation to access the original memory. 888 889 Currently only supported for `MATAIJ` matrices. 890 891 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()` 892 @*/ 893 PetscErrorCode MatResetPreallocation(Mat A) 894 { 895 PetscFunctionBegin; 896 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 897 PetscValidType(A, 1); 898 PetscCheck(A->insertmode == NOT_SET_VALUES, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot reset preallocation after setting some values but not yet calling MatAssemblyBegin()/MatAsssemblyEnd()"); 899 if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS); 900 PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A)); 901 PetscFunctionReturn(PETSC_SUCCESS); 902 } 903 904 /*@ 905 MatSetUp - Sets up the internal matrix data structures for later use. 906 907 Collective 908 909 Input Parameter: 910 . A - the matrix 911 912 Level: intermediate 913 914 Notes: 915 If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of 916 setting values in the matrix. 917 918 If a suitable preallocation routine is used, this function does not need to be called. 919 920 This routine is called internally by other matrix functions when needed so rarely needs to be called by users 921 922 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()` 923 @*/ 924 PetscErrorCode MatSetUp(Mat A) 925 { 926 PetscFunctionBegin; 927 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 928 if (!((PetscObject)A)->type_name) { 929 PetscMPIInt size; 930 931 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 932 PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ)); 933 } 934 if (!A->preallocated) PetscTryTypeMethod(A, setup); 935 PetscCall(PetscLayoutSetUp(A->rmap)); 936 PetscCall(PetscLayoutSetUp(A->cmap)); 937 A->preallocated = PETSC_TRUE; 938 PetscFunctionReturn(PETSC_SUCCESS); 939 } 940 941 #if defined(PETSC_HAVE_SAWS) 942 #include <petscviewersaws.h> 943 #endif 944 945 /* 946 If threadsafety is on extraneous matrices may be printed 947 948 This flag cannot be stored in the matrix because the original matrix in MatView() may assemble a new matrix which is passed into MatViewFromOptions() 949 */ 950 #if !defined(PETSC_HAVE_THREADSAFETY) 951 static PetscInt insidematview = 0; 952 #endif 953 954 /*@C 955 MatViewFromOptions - View properties of the matrix based on options set in the options database 956 957 Collective 958 959 Input Parameters: 960 + A - the matrix 961 . obj - optional additional object that provides the options prefix to use 962 - name - command line option 963 964 Options Database Key: 965 . -mat_view [viewertype]:... - the viewer and its options 966 967 Level: intermediate 968 969 Notes: 970 .vb 971 If no value is provided ascii:stdout is used 972 ascii[:[filename][:[format][:append]]] defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab, 973 for example ascii::ascii_info prints just the information about the object not all details 974 unless :append is given filename opens in write mode, overwriting what was already there 975 binary[:[filename][:[format][:append]]] defaults to the file binaryoutput 976 draw[:drawtype[:filename]] for example, draw:tikz, draw:tikz:figure.tex or draw:x 977 socket[:port] defaults to the standard output port 978 saws[:communicatorname] publishes object to the Scientific Application Webserver (SAWs) 979 .ve 980 981 .seealso: [](ch_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()` 982 @*/ 983 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[]) 984 { 985 PetscFunctionBegin; 986 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 987 #if !defined(PETSC_HAVE_THREADSAFETY) 988 if (insidematview) PetscFunctionReturn(PETSC_SUCCESS); 989 #endif 990 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 991 PetscFunctionReturn(PETSC_SUCCESS); 992 } 993 994 /*@C 995 MatView - display information about a matrix in a variety ways 996 997 Collective 998 999 Input Parameters: 1000 + mat - the matrix 1001 - viewer - visualization context 1002 1003 Options Database Keys: 1004 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 1005 . -mat_view ::ascii_info_detail - Prints more detailed info 1006 . -mat_view - Prints matrix in ASCII format 1007 . -mat_view ::ascii_matlab - Prints matrix in Matlab format 1008 . -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 1009 . -display <name> - Sets display name (default is host) 1010 . -draw_pause <sec> - Sets number of seconds to pause after display 1011 . -mat_view socket - Sends matrix to socket, can be accessed from Matlab (see Users-Manual: ch_matlab for details) 1012 . -viewer_socket_machine <machine> - - 1013 . -viewer_socket_port <port> - - 1014 . -mat_view binary - save matrix to file in binary format 1015 - -viewer_binary_filename <name> - - 1016 1017 Level: beginner 1018 1019 Notes: 1020 The available visualization contexts include 1021 + `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices 1022 . `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD` 1023 . `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm 1024 - `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure 1025 1026 The user can open alternative visualization contexts with 1027 + `PetscViewerASCIIOpen()` - Outputs matrix to a specified file 1028 . `PetscViewerBinaryOpen()` - Outputs matrix in binary to a 1029 specified file; corresponding input uses `MatLoad()` 1030 . `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to 1031 an X window display 1032 - `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer. 1033 Currently only the `MATSEQDENSE` and `MATAIJ` 1034 matrix types support the Socket viewer. 1035 1036 The user can call `PetscViewerPushFormat()` to specify the output 1037 format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`, 1038 `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`). Available formats include 1039 + `PETSC_VIEWER_DEFAULT` - default, prints matrix contents 1040 . `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in Matlab format 1041 . `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros 1042 . `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse 1043 format common among all matrix types 1044 . `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific 1045 format (which is in many cases the same as the default) 1046 . `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix 1047 size and structure (not the matrix entries) 1048 - `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about 1049 the matrix structure 1050 1051 The ASCII viewers are only recommended for small matrices on at most a moderate number of processes, 1052 the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format. 1053 1054 In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer). 1055 1056 See the manual page for `MatLoad()` for the exact format of the binary file when the binary 1057 viewer is used. 1058 1059 See share/petsc/matlab/PetscBinaryRead.m for a Matlab code that can read in the binary file when the binary 1060 viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python. 1061 1062 One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure, 1063 and then use the following mouse functions. 1064 .vb 1065 left mouse: zoom in 1066 middle mouse: zoom out 1067 right mouse: continue with the simulation 1068 .ve 1069 1070 .seealso: [](ch_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`, 1071 `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()` 1072 @*/ 1073 PetscErrorCode MatView(Mat mat, PetscViewer viewer) 1074 { 1075 PetscInt rows, cols, rbs, cbs; 1076 PetscBool isascii, isstring, issaws; 1077 PetscViewerFormat format; 1078 PetscMPIInt size; 1079 1080 PetscFunctionBegin; 1081 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1082 PetscValidType(mat, 1); 1083 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer)); 1084 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1085 PetscCheckSameComm(mat, 1, viewer, 2); 1086 1087 PetscCall(PetscViewerGetFormat(viewer, &format)); 1088 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 1089 if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS); 1090 1091 #if !defined(PETSC_HAVE_THREADSAFETY) 1092 insidematview++; 1093 #endif 1094 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 1095 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 1096 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws)); 1097 PetscCheck((isascii && (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL)) || !mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "No viewers for factored matrix except ASCII, info, or info_detail"); 1098 1099 PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0)); 1100 if (isascii) { 1101 if (!mat->preallocated) { 1102 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n")); 1103 #if !defined(PETSC_HAVE_THREADSAFETY) 1104 insidematview--; 1105 #endif 1106 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1107 PetscFunctionReturn(PETSC_SUCCESS); 1108 } 1109 if (!mat->assembled) { 1110 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n")); 1111 #if !defined(PETSC_HAVE_THREADSAFETY) 1112 insidematview--; 1113 #endif 1114 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1115 PetscFunctionReturn(PETSC_SUCCESS); 1116 } 1117 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer)); 1118 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1119 MatNullSpace nullsp, transnullsp; 1120 1121 PetscCall(PetscViewerASCIIPushTab(viewer)); 1122 PetscCall(MatGetSize(mat, &rows, &cols)); 1123 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1124 if (rbs != 1 || cbs != 1) { 1125 if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs)); 1126 else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs)); 1127 } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols)); 1128 if (mat->factortype) { 1129 MatSolverType solver; 1130 PetscCall(MatFactorGetSolverType(mat, &solver)); 1131 PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver)); 1132 } 1133 if (mat->ops->getinfo) { 1134 MatInfo info; 1135 PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info)); 1136 PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated)); 1137 if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs)); 1138 } 1139 PetscCall(MatGetNullSpace(mat, &nullsp)); 1140 PetscCall(MatGetTransposeNullSpace(mat, &transnullsp)); 1141 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached null space\n")); 1142 if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached transposed null space\n")); 1143 PetscCall(MatGetNearNullSpace(mat, &nullsp)); 1144 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached near null space\n")); 1145 PetscCall(PetscViewerASCIIPushTab(viewer)); 1146 PetscCall(MatProductView(mat, viewer)); 1147 PetscCall(PetscViewerASCIIPopTab(viewer)); 1148 } 1149 } else if (issaws) { 1150 #if defined(PETSC_HAVE_SAWS) 1151 PetscMPIInt rank; 1152 1153 PetscCall(PetscObjectName((PetscObject)mat)); 1154 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 1155 if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer)); 1156 #endif 1157 } else if (isstring) { 1158 const char *type; 1159 PetscCall(MatGetType(mat, &type)); 1160 PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type)); 1161 PetscTryTypeMethod(mat, view, viewer); 1162 } 1163 if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) { 1164 PetscCall(PetscViewerASCIIPushTab(viewer)); 1165 PetscUseTypeMethod(mat, viewnative, viewer); 1166 PetscCall(PetscViewerASCIIPopTab(viewer)); 1167 } else if (mat->ops->view) { 1168 PetscCall(PetscViewerASCIIPushTab(viewer)); 1169 PetscUseTypeMethod(mat, view, viewer); 1170 PetscCall(PetscViewerASCIIPopTab(viewer)); 1171 } 1172 if (isascii) { 1173 PetscCall(PetscViewerGetFormat(viewer, &format)); 1174 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer)); 1175 } 1176 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1177 #if !defined(PETSC_HAVE_THREADSAFETY) 1178 insidematview--; 1179 #endif 1180 PetscFunctionReturn(PETSC_SUCCESS); 1181 } 1182 1183 #if defined(PETSC_USE_DEBUG) 1184 #include <../src/sys/totalview/tv_data_display.h> 1185 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat) 1186 { 1187 TV_add_row("Local rows", "int", &mat->rmap->n); 1188 TV_add_row("Local columns", "int", &mat->cmap->n); 1189 TV_add_row("Global rows", "int", &mat->rmap->N); 1190 TV_add_row("Global columns", "int", &mat->cmap->N); 1191 TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name); 1192 return TV_format_OK; 1193 } 1194 #endif 1195 1196 /*@C 1197 MatLoad - Loads a matrix that has been stored in binary/HDF5 format 1198 with `MatView()`. The matrix format is determined from the options database. 1199 Generates a parallel MPI matrix if the communicator has more than one 1200 processor. The default matrix type is `MATAIJ`. 1201 1202 Collective 1203 1204 Input Parameters: 1205 + mat - the newly loaded matrix, this needs to have been created with `MatCreate()` 1206 or some related function before a call to `MatLoad()` 1207 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer 1208 1209 Options Database Keys: 1210 Used with block matrix formats (`MATSEQBAIJ`, ...) to specify 1211 block size 1212 . -matload_block_size <bs> - set block size 1213 1214 Level: beginner 1215 1216 Notes: 1217 If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the 1218 `Mat` before calling this routine if you wish to set it from the options database. 1219 1220 `MatLoad()` automatically loads into the options database any options 1221 given in the file filename.info where filename is the name of the file 1222 that was passed to the `PetscViewerBinaryOpen()`. The options in the info 1223 file will be ignored if you use the -viewer_binary_skip_info option. 1224 1225 If the type or size of mat is not set before a call to `MatLoad()`, PETSc 1226 sets the default matrix type AIJ and sets the local and global sizes. 1227 If type and/or size is already set, then the same are used. 1228 1229 In parallel, each processor can load a subset of rows (or the 1230 entire matrix). This routine is especially useful when a large 1231 matrix is stored on disk and only part of it is desired on each 1232 processor. For example, a parallel solver may access only some of 1233 the rows from each processor. The algorithm used here reads 1234 relatively small blocks of data rather than reading the entire 1235 matrix and then subsetting it. 1236 1237 Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`. 1238 Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`, 1239 or the sequence like 1240 .vb 1241 `PetscViewer` v; 1242 `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v); 1243 `PetscViewerSetType`(v,`PETSCVIEWERBINARY`); 1244 `PetscViewerSetFromOptions`(v); 1245 `PetscViewerFileSetMode`(v,`FILE_MODE_READ`); 1246 `PetscViewerFileSetName`(v,"datafile"); 1247 .ve 1248 The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option 1249 $ -viewer_type {binary, hdf5} 1250 1251 See the example src/ksp/ksp/tutorials/ex27.c with the first approach, 1252 and src/mat/tutorials/ex10.c with the second approach. 1253 1254 In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks 1255 is read onto MPI rank 0 and then shipped to its destination MPI rank, one after another. 1256 Multiple objects, both matrices and vectors, can be stored within the same file. 1257 Their `PetscObject` name is ignored; they are loaded in the order of their storage. 1258 1259 Most users should not need to know the details of the binary storage 1260 format, since `MatLoad()` and `MatView()` completely hide these details. 1261 But for anyone who is interested, the standard binary matrix storage 1262 format is 1263 1264 .vb 1265 PetscInt MAT_FILE_CLASSID 1266 PetscInt number of rows 1267 PetscInt number of columns 1268 PetscInt total number of nonzeros 1269 PetscInt *number nonzeros in each row 1270 PetscInt *column indices of all nonzeros (starting index is zero) 1271 PetscScalar *values of all nonzeros 1272 .ve 1273 If PETSc was not configured with `--with-64-bit-indices` then only `MATMPIAIJ` matrices with more than `PETSC_INT_MAX` non-zeros can be 1274 stored or loaded (each MPI process part of the matrix must have less than `PETSC_INT_MAX` nonzeros). Since the total nonzero count in this 1275 case will not fit in a (32-bit) `PetscInt` the value `PETSC_INT_MAX` is used for the header entry `total number of nonzeros`. 1276 1277 PETSc automatically does the byte swapping for 1278 machines that store the bytes reversed. Thus if you write your own binary 1279 read/write routines you have to swap the bytes; see `PetscBinaryRead()` 1280 and `PetscBinaryWrite()` to see how this may be done. 1281 1282 In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used. 1283 Each processor's chunk is loaded independently by its owning MPI process. 1284 Multiple objects, both matrices and vectors, can be stored within the same file. 1285 They are looked up by their PetscObject name. 1286 1287 As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use 1288 by default the same structure and naming of the AIJ arrays and column count 1289 within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g. 1290 $ save example.mat A b -v7.3 1291 can be directly read by this routine (see Reference 1 for details). 1292 1293 Depending on your MATLAB version, this format might be a default, 1294 otherwise you can set it as default in Preferences. 1295 1296 Unless -nocompression flag is used to save the file in MATLAB, 1297 PETSc must be configured with ZLIB package. 1298 1299 See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c 1300 1301 This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5` 1302 1303 Corresponding `MatView()` is not yet implemented. 1304 1305 The loaded matrix is actually a transpose of the original one in MATLAB, 1306 unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above). 1307 With this format, matrix is automatically transposed by PETSc, 1308 unless the matrix is marked as SPD or symmetric 1309 (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`). 1310 1311 References: 1312 . * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version 1313 1314 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()` 1315 @*/ 1316 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer) 1317 { 1318 PetscBool flg; 1319 1320 PetscFunctionBegin; 1321 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1322 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1323 1324 if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ)); 1325 1326 flg = PETSC_FALSE; 1327 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL)); 1328 if (flg) { 1329 PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE)); 1330 PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE)); 1331 } 1332 flg = PETSC_FALSE; 1333 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL)); 1334 if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE)); 1335 1336 PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0)); 1337 PetscUseTypeMethod(mat, load, viewer); 1338 PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0)); 1339 PetscFunctionReturn(PETSC_SUCCESS); 1340 } 1341 1342 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant) 1343 { 1344 Mat_Redundant *redund = *redundant; 1345 1346 PetscFunctionBegin; 1347 if (redund) { 1348 if (redund->matseq) { /* via MatCreateSubMatrices() */ 1349 PetscCall(ISDestroy(&redund->isrow)); 1350 PetscCall(ISDestroy(&redund->iscol)); 1351 PetscCall(MatDestroySubMatrices(1, &redund->matseq)); 1352 } else { 1353 PetscCall(PetscFree2(redund->send_rank, redund->recv_rank)); 1354 PetscCall(PetscFree(redund->sbuf_j)); 1355 PetscCall(PetscFree(redund->sbuf_a)); 1356 for (PetscInt i = 0; i < redund->nrecvs; i++) { 1357 PetscCall(PetscFree(redund->rbuf_j[i])); 1358 PetscCall(PetscFree(redund->rbuf_a[i])); 1359 } 1360 PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a)); 1361 } 1362 1363 if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm)); 1364 PetscCall(PetscFree(redund)); 1365 } 1366 PetscFunctionReturn(PETSC_SUCCESS); 1367 } 1368 1369 /*@C 1370 MatDestroy - Frees space taken by a matrix. 1371 1372 Collective 1373 1374 Input Parameter: 1375 . A - the matrix 1376 1377 Level: beginner 1378 1379 Developer Notes: 1380 Some special arrays of matrices are not destroyed in this routine but instead by the routines called by 1381 `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines. 1382 `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes 1383 if changes are needed here. 1384 1385 .seealso: [](ch_matrices), `Mat`, `MatCreate()` 1386 @*/ 1387 PetscErrorCode MatDestroy(Mat *A) 1388 { 1389 PetscFunctionBegin; 1390 if (!*A) PetscFunctionReturn(PETSC_SUCCESS); 1391 PetscValidHeaderSpecific(*A, MAT_CLASSID, 1); 1392 if (--((PetscObject)(*A))->refct > 0) { 1393 *A = NULL; 1394 PetscFunctionReturn(PETSC_SUCCESS); 1395 } 1396 1397 /* if memory was published with SAWs then destroy it */ 1398 PetscCall(PetscObjectSAWsViewOff((PetscObject)*A)); 1399 PetscTryTypeMethod((*A), destroy); 1400 1401 PetscCall(PetscFree((*A)->factorprefix)); 1402 PetscCall(PetscFree((*A)->defaultvectype)); 1403 PetscCall(PetscFree((*A)->defaultrandtype)); 1404 PetscCall(PetscFree((*A)->bsizes)); 1405 PetscCall(PetscFree((*A)->solvertype)); 1406 for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i])); 1407 if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL; 1408 PetscCall(MatDestroy_Redundant(&(*A)->redundant)); 1409 PetscCall(MatProductClear(*A)); 1410 PetscCall(MatNullSpaceDestroy(&(*A)->nullsp)); 1411 PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp)); 1412 PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp)); 1413 PetscCall(MatDestroy(&(*A)->schur)); 1414 PetscCall(PetscLayoutDestroy(&(*A)->rmap)); 1415 PetscCall(PetscLayoutDestroy(&(*A)->cmap)); 1416 PetscCall(PetscHeaderDestroy(A)); 1417 PetscFunctionReturn(PETSC_SUCCESS); 1418 } 1419 1420 /*@C 1421 MatSetValues - Inserts or adds a block of values into a matrix. 1422 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1423 MUST be called after all calls to `MatSetValues()` have been completed. 1424 1425 Not Collective 1426 1427 Input Parameters: 1428 + mat - the matrix 1429 . v - a logically two-dimensional array of values 1430 . m - the number of rows 1431 . idxm - the global indices of the rows 1432 . n - the number of columns 1433 . idxn - the global indices of the columns 1434 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1435 1436 Level: beginner 1437 1438 Notes: 1439 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1440 1441 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1442 options cannot be mixed without intervening calls to the assembly 1443 routines. 1444 1445 `MatSetValues()` uses 0-based row and column numbers in Fortran 1446 as well as in C. 1447 1448 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1449 simply ignored. This allows easily inserting element stiffness matrices 1450 with homogeneous Dirchlet boundary conditions that you don't want represented 1451 in the matrix. 1452 1453 Efficiency Alert: 1454 The routine `MatSetValuesBlocked()` may offer much better efficiency 1455 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1456 1457 Developer Notes: 1458 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1459 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1460 1461 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1462 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1463 @*/ 1464 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1465 { 1466 PetscFunctionBeginHot; 1467 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1468 PetscValidType(mat, 1); 1469 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1470 PetscValidIntPointer(idxm, 3); 1471 PetscValidIntPointer(idxn, 5); 1472 MatCheckPreallocated(mat, 1); 1473 1474 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1475 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1476 1477 if (PetscDefined(USE_DEBUG)) { 1478 PetscInt i, j; 1479 1480 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1481 for (i = 0; i < m; i++) { 1482 for (j = 0; j < n; j++) { 1483 if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j])) 1484 #if defined(PETSC_USE_COMPLEX) 1485 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Inserting %g+i%g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")", (double)PetscRealPart(v[i * n + j]), (double)PetscImaginaryPart(v[i * n + j]), idxm[i], idxn[j]); 1486 #else 1487 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Inserting %g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")", (double)v[i * n + j], idxm[i], idxn[j]); 1488 #endif 1489 } 1490 } 1491 for (i = 0; i < m; i++) PetscCheck(idxm[i] < mat->rmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot insert in row %" PetscInt_FMT ", maximum is %" PetscInt_FMT, idxm[i], mat->rmap->N - 1); 1492 for (i = 0; i < n; i++) PetscCheck(idxn[i] < mat->cmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot insert in column %" PetscInt_FMT ", maximum is %" PetscInt_FMT, idxn[i], mat->cmap->N - 1); 1493 } 1494 1495 if (mat->assembled) { 1496 mat->was_assembled = PETSC_TRUE; 1497 mat->assembled = PETSC_FALSE; 1498 } 1499 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1500 PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv); 1501 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1502 PetscFunctionReturn(PETSC_SUCCESS); 1503 } 1504 1505 /*@C 1506 MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns 1507 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1508 MUST be called after all calls to `MatSetValues()` have been completed. 1509 1510 Not Collective 1511 1512 Input Parameters: 1513 + mat - the matrix 1514 . v - a logically two-dimensional array of values 1515 . ism - the rows to provide 1516 . isn - the columns to provide 1517 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1518 1519 Level: beginner 1520 1521 Notes: 1522 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1523 1524 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1525 options cannot be mixed without intervening calls to the assembly 1526 routines. 1527 1528 `MatSetValues()` uses 0-based row and column numbers in Fortran 1529 as well as in C. 1530 1531 Negative indices may be passed in `ism` and `isn`, these rows and columns are 1532 simply ignored. This allows easily inserting element stiffness matrices 1533 with homogeneous Dirchlet boundary conditions that you don't want represented 1534 in the matrix. 1535 1536 Efficiency Alert: 1537 The routine `MatSetValuesBlocked()` may offer much better efficiency 1538 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1539 1540 This is currently not optimized for any particular `ISType` 1541 1542 Developer Notes: 1543 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1544 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1545 1546 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1547 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1548 @*/ 1549 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv) 1550 { 1551 PetscInt m, n; 1552 const PetscInt *rows, *cols; 1553 1554 PetscFunctionBeginHot; 1555 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1556 PetscCall(ISGetIndices(ism, &rows)); 1557 PetscCall(ISGetIndices(isn, &cols)); 1558 PetscCall(ISGetLocalSize(ism, &m)); 1559 PetscCall(ISGetLocalSize(isn, &n)); 1560 PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv)); 1561 PetscCall(ISRestoreIndices(ism, &rows)); 1562 PetscCall(ISRestoreIndices(isn, &cols)); 1563 PetscFunctionReturn(PETSC_SUCCESS); 1564 } 1565 1566 /*@ 1567 MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1568 values into a matrix 1569 1570 Not Collective 1571 1572 Input Parameters: 1573 + mat - the matrix 1574 . row - the (block) row to set 1575 - v - a logically two-dimensional array of values 1576 1577 Level: intermediate 1578 1579 Notes: 1580 The values, `v`, are column-oriented (for the block version) and sorted 1581 1582 All the nonzeros in the row must be provided 1583 1584 The matrix must have previously had its column indices set, likely by having been assembled. 1585 1586 The row must belong to this process 1587 1588 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1589 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()` 1590 @*/ 1591 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[]) 1592 { 1593 PetscInt globalrow; 1594 1595 PetscFunctionBegin; 1596 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1597 PetscValidType(mat, 1); 1598 PetscValidScalarPointer(v, 3); 1599 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow)); 1600 PetscCall(MatSetValuesRow(mat, globalrow, v)); 1601 PetscFunctionReturn(PETSC_SUCCESS); 1602 } 1603 1604 /*@ 1605 MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1606 values into a matrix 1607 1608 Not Collective 1609 1610 Input Parameters: 1611 + mat - the matrix 1612 . row - the (block) row to set 1613 - v - a logically two-dimensional (column major) array of values for block matrices with blocksize larger than one, otherwise a one dimensional array of values 1614 1615 Level: advanced 1616 1617 Notes: 1618 The values, `v`, are column-oriented for the block version. 1619 1620 All the nonzeros in the row must be provided 1621 1622 THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used. 1623 1624 The row must belong to this process 1625 1626 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1627 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1628 @*/ 1629 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[]) 1630 { 1631 PetscFunctionBeginHot; 1632 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1633 PetscValidType(mat, 1); 1634 MatCheckPreallocated(mat, 1); 1635 PetscValidScalarPointer(v, 3); 1636 PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values"); 1637 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1638 mat->insertmode = INSERT_VALUES; 1639 1640 if (mat->assembled) { 1641 mat->was_assembled = PETSC_TRUE; 1642 mat->assembled = PETSC_FALSE; 1643 } 1644 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1645 PetscUseTypeMethod(mat, setvaluesrow, row, v); 1646 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1647 PetscFunctionReturn(PETSC_SUCCESS); 1648 } 1649 1650 /*@ 1651 MatSetValuesStencil - Inserts or adds a block of values into a matrix. 1652 Using structured grid indexing 1653 1654 Not Collective 1655 1656 Input Parameters: 1657 + mat - the matrix 1658 . m - number of rows being entered 1659 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered 1660 . n - number of columns being entered 1661 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered 1662 . v - a logically two-dimensional array of values 1663 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values 1664 1665 Level: beginner 1666 1667 Notes: 1668 By default the values, `v`, are row-oriented. See `MatSetOption()` for other options. 1669 1670 Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1671 options cannot be mixed without intervening calls to the assembly 1672 routines. 1673 1674 The grid coordinates are across the entire grid, not just the local portion 1675 1676 `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran 1677 as well as in C. 1678 1679 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1680 1681 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1682 or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1683 1684 The columns and rows in the stencil passed in MUST be contained within the 1685 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1686 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1687 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1688 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1689 1690 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 1691 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 1692 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 1693 `DM_BOUNDARY_PERIODIC` boundary type. 1694 1695 For indices that don't mean anything for your case (like the k index when working in 2d) or the c index when you have 1696 a single value per point) you can skip filling those indices. 1697 1698 Inspired by the structured grid interface to the HYPRE package 1699 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1700 1701 Efficiency Alert: 1702 The routine `MatSetValuesBlockedStencil()` may offer much better efficiency 1703 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1704 1705 Fortran Notes: 1706 `idxm` and `idxn` should be declared as 1707 $ MatStencil idxm(4,m),idxn(4,n) 1708 and the values inserted using 1709 .vb 1710 idxm(MatStencil_i,1) = i 1711 idxm(MatStencil_j,1) = j 1712 idxm(MatStencil_k,1) = k 1713 idxm(MatStencil_c,1) = c 1714 etc 1715 .ve 1716 1717 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1718 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil` 1719 @*/ 1720 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1721 { 1722 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1723 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1724 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1725 1726 PetscFunctionBegin; 1727 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1728 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1729 PetscValidType(mat, 1); 1730 PetscValidPointer(idxm, 3); 1731 PetscValidPointer(idxn, 5); 1732 1733 if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 1734 jdxm = buf; 1735 jdxn = buf + m; 1736 } else { 1737 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1738 jdxm = bufm; 1739 jdxn = bufn; 1740 } 1741 for (i = 0; i < m; i++) { 1742 for (j = 0; j < 3 - sdim; j++) dxm++; 1743 tmp = *dxm++ - starts[0]; 1744 for (j = 0; j < dim - 1; j++) { 1745 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1746 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1747 } 1748 if (mat->stencil.noc) dxm++; 1749 jdxm[i] = tmp; 1750 } 1751 for (i = 0; i < n; i++) { 1752 for (j = 0; j < 3 - sdim; j++) dxn++; 1753 tmp = *dxn++ - starts[0]; 1754 for (j = 0; j < dim - 1; j++) { 1755 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1756 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1757 } 1758 if (mat->stencil.noc) dxn++; 1759 jdxn[i] = tmp; 1760 } 1761 PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv)); 1762 PetscCall(PetscFree2(bufm, bufn)); 1763 PetscFunctionReturn(PETSC_SUCCESS); 1764 } 1765 1766 /*@ 1767 MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix. 1768 Using structured grid indexing 1769 1770 Not Collective 1771 1772 Input Parameters: 1773 + mat - the matrix 1774 . m - number of rows being entered 1775 . idxm - grid coordinates for matrix rows being entered 1776 . n - number of columns being entered 1777 . idxn - grid coordinates for matrix columns being entered 1778 . v - a logically two-dimensional array of values 1779 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values 1780 1781 Level: beginner 1782 1783 Notes: 1784 By default the values, `v`, are row-oriented and unsorted. 1785 See `MatSetOption()` for other options. 1786 1787 Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1788 options cannot be mixed without intervening calls to the assembly 1789 routines. 1790 1791 The grid coordinates are across the entire grid, not just the local portion 1792 1793 `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran 1794 as well as in C. 1795 1796 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1797 1798 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1799 or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1800 1801 The columns and rows in the stencil passed in MUST be contained within the 1802 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1803 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1804 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1805 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1806 1807 Negative indices may be passed in idxm and idxn, these rows and columns are 1808 simply ignored. This allows easily inserting element stiffness matrices 1809 with homogeneous Dirchlet boundary conditions that you don't want represented 1810 in the matrix. 1811 1812 Inspired by the structured grid interface to the HYPRE package 1813 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1814 1815 Fortran Notes: 1816 `idxm` and `idxn` should be declared as 1817 $ MatStencil idxm(4,m),idxn(4,n) 1818 and the values inserted using 1819 .vb 1820 idxm(MatStencil_i,1) = i 1821 idxm(MatStencil_j,1) = j 1822 idxm(MatStencil_k,1) = k 1823 etc 1824 .ve 1825 1826 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1827 `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`, 1828 `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` 1829 @*/ 1830 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1831 { 1832 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1833 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1834 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1835 1836 PetscFunctionBegin; 1837 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1838 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1839 PetscValidType(mat, 1); 1840 PetscValidPointer(idxm, 3); 1841 PetscValidPointer(idxn, 5); 1842 PetscValidScalarPointer(v, 6); 1843 1844 if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 1845 jdxm = buf; 1846 jdxn = buf + m; 1847 } else { 1848 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1849 jdxm = bufm; 1850 jdxn = bufn; 1851 } 1852 for (i = 0; i < m; i++) { 1853 for (j = 0; j < 3 - sdim; j++) dxm++; 1854 tmp = *dxm++ - starts[0]; 1855 for (j = 0; j < sdim - 1; j++) { 1856 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1857 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1858 } 1859 dxm++; 1860 jdxm[i] = tmp; 1861 } 1862 for (i = 0; i < n; i++) { 1863 for (j = 0; j < 3 - sdim; j++) dxn++; 1864 tmp = *dxn++ - starts[0]; 1865 for (j = 0; j < sdim - 1; j++) { 1866 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1867 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1868 } 1869 dxn++; 1870 jdxn[i] = tmp; 1871 } 1872 PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv)); 1873 PetscCall(PetscFree2(bufm, bufn)); 1874 PetscFunctionReturn(PETSC_SUCCESS); 1875 } 1876 1877 /*@ 1878 MatSetStencil - Sets the grid information for setting values into a matrix via 1879 `MatSetValuesStencil()` 1880 1881 Not Collective 1882 1883 Input Parameters: 1884 + mat - the matrix 1885 . dim - dimension of the grid 1, 2, or 3 1886 . dims - number of grid points in x, y, and z direction, including ghost points on your processor 1887 . starts - starting point of ghost nodes on your processor in x, y, and z direction 1888 - dof - number of degrees of freedom per node 1889 1890 Level: beginner 1891 1892 Notes: 1893 Inspired by the structured grid interface to the HYPRE package 1894 (www.llnl.gov/CASC/hyper) 1895 1896 For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the 1897 user. 1898 1899 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1900 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()` 1901 @*/ 1902 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof) 1903 { 1904 PetscFunctionBegin; 1905 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1906 PetscValidIntPointer(dims, 3); 1907 PetscValidIntPointer(starts, 4); 1908 1909 mat->stencil.dim = dim + (dof > 1); 1910 for (PetscInt i = 0; i < dim; i++) { 1911 mat->stencil.dims[i] = dims[dim - i - 1]; /* copy the values in backwards */ 1912 mat->stencil.starts[i] = starts[dim - i - 1]; 1913 } 1914 mat->stencil.dims[dim] = dof; 1915 mat->stencil.starts[dim] = 0; 1916 mat->stencil.noc = (PetscBool)(dof == 1); 1917 PetscFunctionReturn(PETSC_SUCCESS); 1918 } 1919 1920 /*@C 1921 MatSetValuesBlocked - Inserts or adds a block of values into a matrix. 1922 1923 Not Collective 1924 1925 Input Parameters: 1926 + mat - the matrix 1927 . v - a logically two-dimensional array of values 1928 . m - the number of block rows 1929 . idxm - the global block indices 1930 . n - the number of block columns 1931 . idxn - the global block indices 1932 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values 1933 1934 Level: intermediate 1935 1936 Notes: 1937 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call 1938 MatXXXXSetPreallocation() or `MatSetUp()` before using this routine. 1939 1940 The `m` and `n` count the NUMBER of blocks in the row direction and column direction, 1941 NOT the total number of rows/columns; for example, if the block size is 2 and 1942 you are passing in values for rows 2,3,4,5 then m would be 2 (not 4). 1943 The values in idxm would be 1 2; that is the first index for each block divided by 1944 the block size. 1945 1946 You must call `MatSetBlockSize()` when constructing this matrix (before 1947 preallocating it). 1948 1949 By default the values, `v`, are row-oriented, so the layout of 1950 `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options. 1951 1952 Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES` 1953 options cannot be mixed without intervening calls to the assembly 1954 routines. 1955 1956 `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran 1957 as well as in C. 1958 1959 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1960 simply ignored. This allows easily inserting element stiffness matrices 1961 with homogeneous Dirchlet boundary conditions that you don't want represented 1962 in the matrix. 1963 1964 Each time an entry is set within a sparse matrix via `MatSetValues()`, 1965 internal searching must be done to determine where to place the 1966 data in the matrix storage space. By instead inserting blocks of 1967 entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is 1968 reduced. 1969 1970 Example: 1971 .vb 1972 Suppose m=n=2 and block size(bs) = 2 The array is 1973 1974 1 2 | 3 4 1975 5 6 | 7 8 1976 - - - | - - - 1977 9 10 | 11 12 1978 13 14 | 15 16 1979 1980 v[] should be passed in like 1981 v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] 1982 1983 If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then 1984 v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16] 1985 .ve 1986 1987 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()` 1988 @*/ 1989 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1990 { 1991 PetscFunctionBeginHot; 1992 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1993 PetscValidType(mat, 1); 1994 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1995 PetscValidIntPointer(idxm, 3); 1996 PetscValidIntPointer(idxn, 5); 1997 MatCheckPreallocated(mat, 1); 1998 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1999 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2000 if (PetscDefined(USE_DEBUG)) { 2001 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2002 PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2003 } 2004 if (PetscDefined(USE_DEBUG)) { 2005 PetscInt rbs, cbs, M, N, i; 2006 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 2007 PetscCall(MatGetSize(mat, &M, &N)); 2008 for (i = 0; i < m; i++) PetscCheck(idxm[i] * rbs < M, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row block index %" PetscInt_FMT " (index %" PetscInt_FMT ") greater than row length %" PetscInt_FMT, i, idxm[i], M); 2009 for (i = 0; i < n; i++) PetscCheck(idxn[i] * cbs < N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column block index %" PetscInt_FMT " (index %" PetscInt_FMT ") great than column length %" PetscInt_FMT, i, idxn[i], N); 2010 } 2011 if (mat->assembled) { 2012 mat->was_assembled = PETSC_TRUE; 2013 mat->assembled = PETSC_FALSE; 2014 } 2015 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2016 if (mat->ops->setvaluesblocked) { 2017 PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv); 2018 } else { 2019 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn; 2020 PetscInt i, j, bs, cbs; 2021 2022 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 2023 if (m * bs + n * cbs <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2024 iidxm = buf; 2025 iidxn = buf + m * bs; 2026 } else { 2027 PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc)); 2028 iidxm = bufr; 2029 iidxn = bufc; 2030 } 2031 for (i = 0; i < m; i++) { 2032 for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j; 2033 } 2034 if (m != n || bs != cbs || idxm != idxn) { 2035 for (i = 0; i < n; i++) { 2036 for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j; 2037 } 2038 } else iidxn = iidxm; 2039 PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv)); 2040 PetscCall(PetscFree2(bufr, bufc)); 2041 } 2042 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2043 PetscFunctionReturn(PETSC_SUCCESS); 2044 } 2045 2046 /*@C 2047 MatGetValues - Gets a block of local values from a matrix. 2048 2049 Not Collective; can only return values that are owned by the give process 2050 2051 Input Parameters: 2052 + mat - the matrix 2053 . v - a logically two-dimensional array for storing the values 2054 . m - the number of rows 2055 . idxm - the global indices of the rows 2056 . n - the number of columns 2057 - idxn - the global indices of the columns 2058 2059 Level: advanced 2060 2061 Notes: 2062 The user must allocate space (m*n `PetscScalar`s) for the values, `v`. 2063 The values, `v`, are then returned in a row-oriented format, 2064 analogous to that used by default in `MatSetValues()`. 2065 2066 `MatGetValues()` uses 0-based row and column numbers in 2067 Fortran as well as in C. 2068 2069 `MatGetValues()` requires that the matrix has been assembled 2070 with `MatAssemblyBegin()`/`MatAssemblyEnd()`. Thus, calls to 2071 `MatSetValues()` and `MatGetValues()` CANNOT be made in succession 2072 without intermediate matrix assembly. 2073 2074 Negative row or column indices will be ignored and those locations in `v` will be 2075 left unchanged. 2076 2077 For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI process. 2078 That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable 2079 from `MatGetOwnershipRange`(mat,&rstart,&rend). 2080 2081 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()` 2082 @*/ 2083 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) 2084 { 2085 PetscFunctionBegin; 2086 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2087 PetscValidType(mat, 1); 2088 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); 2089 PetscValidIntPointer(idxm, 3); 2090 PetscValidIntPointer(idxn, 5); 2091 PetscValidScalarPointer(v, 6); 2092 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2093 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2094 MatCheckPreallocated(mat, 1); 2095 2096 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2097 PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v); 2098 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2099 PetscFunctionReturn(PETSC_SUCCESS); 2100 } 2101 2102 /*@C 2103 MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices 2104 defined previously by `MatSetLocalToGlobalMapping()` 2105 2106 Not Collective 2107 2108 Input Parameters: 2109 + mat - the matrix 2110 . nrow - number of rows 2111 . irow - the row local indices 2112 . ncol - number of columns 2113 - icol - the column local indices 2114 2115 Output Parameter: 2116 . y - a logically two-dimensional array of values 2117 2118 Level: advanced 2119 2120 Notes: 2121 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine. 2122 2123 This routine can only return values that are owned by the requesting MPI process. That is, for standard matrix formats, rows that, in the global numbering, 2124 are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can 2125 determine if the resulting global row associated with the local row r is owned by the requesting MPI process by applying the `ISLocalToGlobalMapping` set 2126 with `MatSetLocalToGlobalMapping()`. 2127 2128 Developer Notes: 2129 This is labelled with C so does not automatically generate Fortran stubs and interfaces 2130 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2131 2132 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2133 `MatSetValuesLocal()`, `MatGetValues()` 2134 @*/ 2135 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[]) 2136 { 2137 PetscFunctionBeginHot; 2138 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2139 PetscValidType(mat, 1); 2140 MatCheckPreallocated(mat, 1); 2141 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */ 2142 PetscValidIntPointer(irow, 3); 2143 PetscValidIntPointer(icol, 5); 2144 if (PetscDefined(USE_DEBUG)) { 2145 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2146 PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2147 } 2148 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2149 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2150 if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y); 2151 else { 2152 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm; 2153 if ((nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2154 irowm = buf; 2155 icolm = buf + nrow; 2156 } else { 2157 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2158 irowm = bufr; 2159 icolm = bufc; 2160 } 2161 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping())."); 2162 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping())."); 2163 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm)); 2164 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm)); 2165 PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y)); 2166 PetscCall(PetscFree2(bufr, bufc)); 2167 } 2168 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2169 PetscFunctionReturn(PETSC_SUCCESS); 2170 } 2171 2172 /*@ 2173 MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and 2174 the same size. Currently, this can only be called once and creates the given matrix. 2175 2176 Not Collective 2177 2178 Input Parameters: 2179 + mat - the matrix 2180 . nb - the number of blocks 2181 . bs - the number of rows (and columns) in each block 2182 . rows - a concatenation of the rows for each block 2183 - v - a concatenation of logically two-dimensional arrays of values 2184 2185 Level: advanced 2186 2187 Note: 2188 `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values 2189 2190 In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix. 2191 2192 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 2193 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()` 2194 @*/ 2195 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[]) 2196 { 2197 PetscFunctionBegin; 2198 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2199 PetscValidType(mat, 1); 2200 PetscValidIntPointer(rows, 4); 2201 PetscValidScalarPointer(v, 5); 2202 PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2203 2204 PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0)); 2205 if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v); 2206 else { 2207 for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES)); 2208 } 2209 PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0)); 2210 PetscFunctionReturn(PETSC_SUCCESS); 2211 } 2212 2213 /*@ 2214 MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by 2215 the routine `MatSetValuesLocal()` to allow users to insert matrix entries 2216 using a local (per-processor) numbering. 2217 2218 Not Collective 2219 2220 Input Parameters: 2221 + x - the matrix 2222 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()` 2223 - cmapping - column mapping 2224 2225 Level: intermediate 2226 2227 Note: 2228 If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix 2229 2230 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()` 2231 @*/ 2232 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping) 2233 { 2234 PetscFunctionBegin; 2235 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 2236 PetscValidType(x, 1); 2237 if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2); 2238 if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3); 2239 if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping); 2240 else { 2241 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping)); 2242 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping)); 2243 } 2244 PetscFunctionReturn(PETSC_SUCCESS); 2245 } 2246 2247 /*@ 2248 MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()` 2249 2250 Not Collective 2251 2252 Input Parameter: 2253 . A - the matrix 2254 2255 Output Parameters: 2256 + rmapping - row mapping 2257 - cmapping - column mapping 2258 2259 Level: advanced 2260 2261 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()` 2262 @*/ 2263 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping) 2264 { 2265 PetscFunctionBegin; 2266 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2267 PetscValidType(A, 1); 2268 if (rmapping) { 2269 PetscValidPointer(rmapping, 2); 2270 *rmapping = A->rmap->mapping; 2271 } 2272 if (cmapping) { 2273 PetscValidPointer(cmapping, 3); 2274 *cmapping = A->cmap->mapping; 2275 } 2276 PetscFunctionReturn(PETSC_SUCCESS); 2277 } 2278 2279 /*@ 2280 MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix 2281 2282 Logically Collective 2283 2284 Input Parameters: 2285 + A - the matrix 2286 . rmap - row layout 2287 - cmap - column layout 2288 2289 Level: advanced 2290 2291 Note: 2292 The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called. 2293 2294 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()` 2295 @*/ 2296 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap) 2297 { 2298 PetscFunctionBegin; 2299 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2300 PetscCall(PetscLayoutReference(rmap, &A->rmap)); 2301 PetscCall(PetscLayoutReference(cmap, &A->cmap)); 2302 PetscFunctionReturn(PETSC_SUCCESS); 2303 } 2304 2305 /*@ 2306 MatGetLayouts - Gets the `PetscLayout` objects for rows and columns 2307 2308 Not Collective 2309 2310 Input Parameter: 2311 . A - the matrix 2312 2313 Output Parameters: 2314 + rmap - row layout 2315 - cmap - column layout 2316 2317 Level: advanced 2318 2319 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()` 2320 @*/ 2321 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap) 2322 { 2323 PetscFunctionBegin; 2324 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2325 PetscValidType(A, 1); 2326 if (rmap) { 2327 PetscValidPointer(rmap, 2); 2328 *rmap = A->rmap; 2329 } 2330 if (cmap) { 2331 PetscValidPointer(cmap, 3); 2332 *cmap = A->cmap; 2333 } 2334 PetscFunctionReturn(PETSC_SUCCESS); 2335 } 2336 2337 /*@C 2338 MatSetValuesLocal - Inserts or adds values into certain locations of a matrix, 2339 using a local numbering of the nodes. 2340 2341 Not Collective 2342 2343 Input Parameters: 2344 + mat - the matrix 2345 . nrow - number of rows 2346 . irow - the row local indices 2347 . ncol - number of columns 2348 . icol - the column local indices 2349 . y - a logically two-dimensional array of values 2350 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2351 2352 Level: intermediate 2353 2354 Notes: 2355 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 2356 `MatSetUp()` before using this routine 2357 2358 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine 2359 2360 Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2361 options cannot be mixed without intervening calls to the assembly 2362 routines. 2363 2364 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2365 MUST be called after all calls to `MatSetValuesLocal()` have been completed. 2366 2367 Developer Notes: 2368 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2369 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2370 2371 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2372 `MatGetValuesLocal()` 2373 @*/ 2374 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2375 { 2376 PetscFunctionBeginHot; 2377 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2378 PetscValidType(mat, 1); 2379 MatCheckPreallocated(mat, 1); 2380 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2381 PetscValidIntPointer(irow, 3); 2382 PetscValidIntPointer(icol, 5); 2383 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2384 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2385 if (PetscDefined(USE_DEBUG)) { 2386 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2387 PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2388 } 2389 2390 if (mat->assembled) { 2391 mat->was_assembled = PETSC_TRUE; 2392 mat->assembled = PETSC_FALSE; 2393 } 2394 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2395 if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv); 2396 else { 2397 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2398 const PetscInt *irowm, *icolm; 2399 2400 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2401 bufr = buf; 2402 bufc = buf + nrow; 2403 irowm = bufr; 2404 icolm = bufc; 2405 } else { 2406 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2407 irowm = bufr; 2408 icolm = bufc; 2409 } 2410 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr)); 2411 else irowm = irow; 2412 if (mat->cmap->mapping) { 2413 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2414 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc)); 2415 } else icolm = irowm; 2416 } else icolm = icol; 2417 PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv)); 2418 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2419 } 2420 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2421 PetscFunctionReturn(PETSC_SUCCESS); 2422 } 2423 2424 /*@C 2425 MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix, 2426 using a local ordering of the nodes a block at a time. 2427 2428 Not Collective 2429 2430 Input Parameters: 2431 + mat - the matrix 2432 . nrow - number of rows 2433 . irow - the row local indices 2434 . ncol - number of columns 2435 . icol - the column local indices 2436 . y - a logically two-dimensional array of values 2437 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2438 2439 Level: intermediate 2440 2441 Notes: 2442 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 2443 `MatSetUp()` before using this routine 2444 2445 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()` 2446 before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the 2447 2448 Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2449 options cannot be mixed without intervening calls to the assembly 2450 routines. 2451 2452 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2453 MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed. 2454 2455 Developer Notes: 2456 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2457 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2458 2459 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, 2460 `MatSetValuesLocal()`, `MatSetValuesBlocked()` 2461 @*/ 2462 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2463 { 2464 PetscFunctionBeginHot; 2465 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2466 PetscValidType(mat, 1); 2467 MatCheckPreallocated(mat, 1); 2468 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2469 PetscValidIntPointer(irow, 3); 2470 PetscValidIntPointer(icol, 5); 2471 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2472 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2473 if (PetscDefined(USE_DEBUG)) { 2474 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2475 PetscCheck(mat->ops->setvaluesblockedlocal || mat->ops->setvaluesblocked || mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2476 } 2477 2478 if (mat->assembled) { 2479 mat->was_assembled = PETSC_TRUE; 2480 mat->assembled = PETSC_FALSE; 2481 } 2482 if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */ 2483 PetscInt irbs, rbs; 2484 PetscCall(MatGetBlockSizes(mat, &rbs, NULL)); 2485 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs)); 2486 PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs); 2487 } 2488 if (PetscUnlikelyDebug(mat->cmap->mapping)) { 2489 PetscInt icbs, cbs; 2490 PetscCall(MatGetBlockSizes(mat, NULL, &cbs)); 2491 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs)); 2492 PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs); 2493 } 2494 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2495 if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv); 2496 else { 2497 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2498 const PetscInt *irowm, *icolm; 2499 2500 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2501 bufr = buf; 2502 bufc = buf + nrow; 2503 irowm = bufr; 2504 icolm = bufc; 2505 } else { 2506 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2507 irowm = bufr; 2508 icolm = bufc; 2509 } 2510 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr)); 2511 else irowm = irow; 2512 if (mat->cmap->mapping) { 2513 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2514 PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc)); 2515 } else icolm = irowm; 2516 } else icolm = icol; 2517 PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv)); 2518 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2519 } 2520 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2521 PetscFunctionReturn(PETSC_SUCCESS); 2522 } 2523 2524 /*@ 2525 MatMultDiagonalBlock - Computes the matrix-vector product, y = Dx. Where D is defined by the inode or block structure of the diagonal 2526 2527 Collective 2528 2529 Input Parameters: 2530 + mat - the matrix 2531 - x - the vector to be multiplied 2532 2533 Output Parameter: 2534 . y - the result 2535 2536 Level: developer 2537 2538 Note: 2539 The vectors `x` and `y` cannot be the same. I.e., one cannot 2540 call `MatMultDiagonalBlock`(A,y,y). 2541 2542 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2543 @*/ 2544 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y) 2545 { 2546 PetscFunctionBegin; 2547 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2548 PetscValidType(mat, 1); 2549 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2550 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2551 2552 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2553 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2554 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2555 MatCheckPreallocated(mat, 1); 2556 2557 PetscUseTypeMethod(mat, multdiagonalblock, x, y); 2558 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2559 PetscFunctionReturn(PETSC_SUCCESS); 2560 } 2561 2562 /*@ 2563 MatMult - Computes the matrix-vector product, y = Ax. 2564 2565 Neighbor-wise Collective 2566 2567 Input Parameters: 2568 + mat - the matrix 2569 - x - the vector to be multiplied 2570 2571 Output Parameter: 2572 . y - the result 2573 2574 Level: beginner 2575 2576 Note: 2577 The vectors `x` and `y` cannot be the same. I.e., one cannot 2578 call `MatMult`(A,y,y). 2579 2580 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2581 @*/ 2582 PetscErrorCode MatMult(Mat mat, Vec x, Vec y) 2583 { 2584 PetscFunctionBegin; 2585 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2586 PetscValidType(mat, 1); 2587 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2588 VecCheckAssembled(x); 2589 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2590 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2591 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2592 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2593 PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N); 2594 PetscCheck(mat->rmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, y->map->N); 2595 PetscCheck(mat->cmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, x->map->n); 2596 PetscCheck(mat->rmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, y->map->n); 2597 PetscCall(VecSetErrorIfLocked(y, 3)); 2598 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2599 MatCheckPreallocated(mat, 1); 2600 2601 PetscCall(VecLockReadPush(x)); 2602 PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0)); 2603 PetscUseTypeMethod(mat, mult, x, y); 2604 PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0)); 2605 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2606 PetscCall(VecLockReadPop(x)); 2607 PetscFunctionReturn(PETSC_SUCCESS); 2608 } 2609 2610 /*@ 2611 MatMultTranspose - Computes matrix transpose times a vector y = A^T * x. 2612 2613 Neighbor-wise Collective 2614 2615 Input Parameters: 2616 + mat - the matrix 2617 - x - the vector to be multiplied 2618 2619 Output Parameter: 2620 . y - the result 2621 2622 Level: beginner 2623 2624 Notes: 2625 The vectors `x` and `y` cannot be the same. I.e., one cannot 2626 call `MatMultTranspose`(A,y,y). 2627 2628 For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple, 2629 use `MatMultHermitianTranspose()` 2630 2631 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()` 2632 @*/ 2633 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y) 2634 { 2635 PetscErrorCode (*op)(Mat, Vec, Vec) = NULL; 2636 2637 PetscFunctionBegin; 2638 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2639 PetscValidType(mat, 1); 2640 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2641 VecCheckAssembled(x); 2642 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2643 2644 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2645 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2646 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2647 PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N); 2648 PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N); 2649 PetscCheck(mat->cmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, y->map->n); 2650 PetscCheck(mat->rmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, x->map->n); 2651 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2652 MatCheckPreallocated(mat, 1); 2653 2654 if (!mat->ops->multtranspose) { 2655 if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult; 2656 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s does not have a multiply transpose defined or is symmetric and does not have a multiply defined", ((PetscObject)mat)->type_name); 2657 } else op = mat->ops->multtranspose; 2658 PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0)); 2659 PetscCall(VecLockReadPush(x)); 2660 PetscCall((*op)(mat, x, y)); 2661 PetscCall(VecLockReadPop(x)); 2662 PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0)); 2663 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2664 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2665 PetscFunctionReturn(PETSC_SUCCESS); 2666 } 2667 2668 /*@ 2669 MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector. 2670 2671 Neighbor-wise Collective 2672 2673 Input Parameters: 2674 + mat - the matrix 2675 - x - the vector to be multiplied 2676 2677 Output Parameter: 2678 . y - the result 2679 2680 Level: beginner 2681 2682 Notes: 2683 The vectors `x` and `y` cannot be the same. I.e., one cannot 2684 call `MatMultHermitianTranspose`(A,y,y). 2685 2686 Also called the conjugate transpose, complex conjugate transpose, or adjoint. 2687 2688 For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical. 2689 2690 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()` 2691 @*/ 2692 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y) 2693 { 2694 PetscFunctionBegin; 2695 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2696 PetscValidType(mat, 1); 2697 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2698 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2699 2700 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2701 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2702 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2703 PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N); 2704 PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N); 2705 PetscCheck(mat->cmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, y->map->n); 2706 PetscCheck(mat->rmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, x->map->n); 2707 MatCheckPreallocated(mat, 1); 2708 2709 PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0)); 2710 #if defined(PETSC_USE_COMPLEX) 2711 if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) { 2712 PetscCall(VecLockReadPush(x)); 2713 if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y); 2714 else PetscUseTypeMethod(mat, mult, x, y); 2715 PetscCall(VecLockReadPop(x)); 2716 } else { 2717 Vec w; 2718 PetscCall(VecDuplicate(x, &w)); 2719 PetscCall(VecCopy(x, w)); 2720 PetscCall(VecConjugate(w)); 2721 PetscCall(MatMultTranspose(mat, w, y)); 2722 PetscCall(VecDestroy(&w)); 2723 PetscCall(VecConjugate(y)); 2724 } 2725 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2726 #else 2727 PetscCall(MatMultTranspose(mat, x, y)); 2728 #endif 2729 PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0)); 2730 PetscFunctionReturn(PETSC_SUCCESS); 2731 } 2732 2733 /*@ 2734 MatMultAdd - Computes v3 = v2 + A * v1. 2735 2736 Neighbor-wise Collective 2737 2738 Input Parameters: 2739 + mat - the matrix 2740 . v1 - the vector to be multiplied by `mat` 2741 - v2 - the vector to be added to the result 2742 2743 Output Parameter: 2744 . v3 - the result 2745 2746 Level: beginner 2747 2748 Note: 2749 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2750 call `MatMultAdd`(A,v1,v2,v1). 2751 2752 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()` 2753 @*/ 2754 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2755 { 2756 PetscFunctionBegin; 2757 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2758 PetscValidType(mat, 1); 2759 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2760 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2761 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2762 2763 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2764 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2765 PetscCheck(mat->cmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v1->map->N); 2766 /* PetscCheck(mat->rmap->N == v2->map->N,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v2->map->N); 2767 PetscCheck(mat->rmap->N == v3->map->N,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v3->map->N); */ 2768 PetscCheck(mat->rmap->n == v3->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, v3->map->n); 2769 PetscCheck(mat->rmap->n == v2->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, v2->map->n); 2770 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2771 MatCheckPreallocated(mat, 1); 2772 2773 PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3)); 2774 PetscCall(VecLockReadPush(v1)); 2775 PetscUseTypeMethod(mat, multadd, v1, v2, v3); 2776 PetscCall(VecLockReadPop(v1)); 2777 PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3)); 2778 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2779 PetscFunctionReturn(PETSC_SUCCESS); 2780 } 2781 2782 /*@ 2783 MatMultTransposeAdd - Computes v3 = v2 + A' * v1. 2784 2785 Neighbor-wise Collective 2786 2787 Input Parameters: 2788 + mat - the matrix 2789 . v1 - the vector to be multiplied by the transpose of the matrix 2790 - v2 - the vector to be added to the result 2791 2792 Output Parameter: 2793 . v3 - the result 2794 2795 Level: beginner 2796 2797 Note: 2798 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2799 call `MatMultTransposeAdd`(A,v1,v2,v1). 2800 2801 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2802 @*/ 2803 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2804 { 2805 PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd; 2806 2807 PetscFunctionBegin; 2808 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2809 PetscValidType(mat, 1); 2810 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2811 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2812 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2813 2814 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2815 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2816 PetscCheck(mat->rmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, v1->map->N); 2817 PetscCheck(mat->cmap->N == v2->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v2->map->N); 2818 PetscCheck(mat->cmap->N == v3->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v3->map->N); 2819 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2820 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2821 MatCheckPreallocated(mat, 1); 2822 2823 PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2824 PetscCall(VecLockReadPush(v1)); 2825 PetscCall((*op)(mat, v1, v2, v3)); 2826 PetscCall(VecLockReadPop(v1)); 2827 PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2828 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2829 PetscFunctionReturn(PETSC_SUCCESS); 2830 } 2831 2832 /*@ 2833 MatMultHermitianTransposeAdd - Computes v3 = v2 + A^H * v1. 2834 2835 Neighbor-wise Collective 2836 2837 Input Parameters: 2838 + mat - the matrix 2839 . v1 - the vector to be multiplied by the Hermitian transpose 2840 - v2 - the vector to be added to the result 2841 2842 Output Parameter: 2843 . v3 - the result 2844 2845 Level: beginner 2846 2847 Note: 2848 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2849 call `MatMultHermitianTransposeAdd`(A,v1,v2,v1). 2850 2851 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2852 @*/ 2853 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2854 { 2855 PetscFunctionBegin; 2856 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2857 PetscValidType(mat, 1); 2858 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2859 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2860 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2861 2862 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2863 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2864 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2865 PetscCheck(mat->rmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, v1->map->N); 2866 PetscCheck(mat->cmap->N == v2->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v2->map->N); 2867 PetscCheck(mat->cmap->N == v3->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v3->map->N); 2868 MatCheckPreallocated(mat, 1); 2869 2870 PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2871 PetscCall(VecLockReadPush(v1)); 2872 if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3); 2873 else { 2874 Vec w, z; 2875 PetscCall(VecDuplicate(v1, &w)); 2876 PetscCall(VecCopy(v1, w)); 2877 PetscCall(VecConjugate(w)); 2878 PetscCall(VecDuplicate(v3, &z)); 2879 PetscCall(MatMultTranspose(mat, w, z)); 2880 PetscCall(VecDestroy(&w)); 2881 PetscCall(VecConjugate(z)); 2882 if (v2 != v3) { 2883 PetscCall(VecWAXPY(v3, 1.0, v2, z)); 2884 } else { 2885 PetscCall(VecAXPY(v3, 1.0, z)); 2886 } 2887 PetscCall(VecDestroy(&z)); 2888 } 2889 PetscCall(VecLockReadPop(v1)); 2890 PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2891 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2892 PetscFunctionReturn(PETSC_SUCCESS); 2893 } 2894 2895 /*@C 2896 MatGetFactorType - gets the type of factorization it is 2897 2898 Not Collective 2899 2900 Input Parameter: 2901 . mat - the matrix 2902 2903 Output Parameter: 2904 . t - the type, one of `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2905 2906 Level: intermediate 2907 2908 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2909 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2910 @*/ 2911 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t) 2912 { 2913 PetscFunctionBegin; 2914 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2915 PetscValidType(mat, 1); 2916 PetscValidPointer(t, 2); 2917 *t = mat->factortype; 2918 PetscFunctionReturn(PETSC_SUCCESS); 2919 } 2920 2921 /*@C 2922 MatSetFactorType - sets the type of factorization it is 2923 2924 Logically Collective 2925 2926 Input Parameters: 2927 + mat - the matrix 2928 - t - the type, one of `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2929 2930 Level: intermediate 2931 2932 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2933 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2934 @*/ 2935 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t) 2936 { 2937 PetscFunctionBegin; 2938 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2939 PetscValidType(mat, 1); 2940 mat->factortype = t; 2941 PetscFunctionReturn(PETSC_SUCCESS); 2942 } 2943 2944 /*@C 2945 MatGetInfo - Returns information about matrix storage (number of 2946 nonzeros, memory, etc.). 2947 2948 Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag 2949 2950 Input Parameters: 2951 + mat - the matrix 2952 - flag - flag indicating the type of parameters to be returned (`MAT_LOCAL` - local matrix, `MAT_GLOBAL_MAX` - maximum over all processors, `MAT_GLOBAL_SUM` - sum over all processors) 2953 2954 Output Parameter: 2955 . info - matrix information context 2956 2957 Options Database Key: 2958 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT` 2959 2960 Notes: 2961 The `MatInfo` context contains a variety of matrix data, including 2962 number of nonzeros allocated and used, number of mallocs during 2963 matrix assembly, etc. Additional information for factored matrices 2964 is provided (such as the fill ratio, number of mallocs during 2965 factorization, etc.). 2966 2967 Example: 2968 See the file ${PETSC_DIR}/include/petscmat.h for a complete list of 2969 data within the MatInfo context. For example, 2970 .vb 2971 MatInfo info; 2972 Mat A; 2973 double mal, nz_a, nz_u; 2974 2975 MatGetInfo(A, MAT_LOCAL, &info); 2976 mal = info.mallocs; 2977 nz_a = info.nz_allocated; 2978 .ve 2979 2980 Fortran users should declare info as a double precision 2981 array of dimension `MAT_INFO_SIZE`, and then extract the parameters 2982 of interest. See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h 2983 a complete list of parameter names. 2984 .vb 2985 double precision info(MAT_INFO_SIZE) 2986 double precision mal, nz_a 2987 Mat A 2988 integer ierr 2989 2990 call MatGetInfo(A, MAT_LOCAL, info, ierr) 2991 mal = info(MAT_INFO_MALLOCS) 2992 nz_a = info(MAT_INFO_NZ_ALLOCATED) 2993 .ve 2994 2995 Level: intermediate 2996 2997 Developer Notes: 2998 The Fortran interface is not autogenerated as the 2999 interface definition cannot be generated correctly [due to `MatInfo` argument] 3000 3001 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()` 3002 @*/ 3003 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info) 3004 { 3005 PetscFunctionBegin; 3006 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3007 PetscValidType(mat, 1); 3008 PetscValidPointer(info, 3); 3009 MatCheckPreallocated(mat, 1); 3010 PetscUseTypeMethod(mat, getinfo, flag, info); 3011 PetscFunctionReturn(PETSC_SUCCESS); 3012 } 3013 3014 /* 3015 This is used by external packages where it is not easy to get the info from the actual 3016 matrix factorization. 3017 */ 3018 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info) 3019 { 3020 PetscFunctionBegin; 3021 PetscCall(PetscMemzero(info, sizeof(MatInfo))); 3022 PetscFunctionReturn(PETSC_SUCCESS); 3023 } 3024 3025 /*@C 3026 MatLUFactor - Performs in-place LU factorization of matrix. 3027 3028 Collective 3029 3030 Input Parameters: 3031 + mat - the matrix 3032 . row - row permutation 3033 . col - column permutation 3034 - info - options for factorization, includes 3035 .vb 3036 fill - expected fill as ratio of original fill. 3037 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3038 Run with the option -info to determine an optimal value to use 3039 .ve 3040 3041 Level: developer 3042 3043 Notes: 3044 Most users should employ the `KSP` interface for linear solvers 3045 instead of working directly with matrix algebra routines such as this. 3046 See, e.g., `KSPCreate()`. 3047 3048 This changes the state of the matrix to a factored matrix; it cannot be used 3049 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3050 3051 This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()` 3052 when not using `KSP`. 3053 3054 Developer Notes: 3055 The Fortran interface is not autogenerated as the 3056 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3057 3058 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, 3059 `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3060 @*/ 3061 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3062 { 3063 MatFactorInfo tinfo; 3064 3065 PetscFunctionBegin; 3066 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3067 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3068 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3069 if (info) PetscValidPointer(info, 4); 3070 PetscValidType(mat, 1); 3071 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3072 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3073 MatCheckPreallocated(mat, 1); 3074 if (!info) { 3075 PetscCall(MatFactorInfoInitialize(&tinfo)); 3076 info = &tinfo; 3077 } 3078 3079 PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0)); 3080 PetscUseTypeMethod(mat, lufactor, row, col, info); 3081 PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0)); 3082 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3083 PetscFunctionReturn(PETSC_SUCCESS); 3084 } 3085 3086 /*@C 3087 MatILUFactor - Performs in-place ILU factorization of matrix. 3088 3089 Collective 3090 3091 Input Parameters: 3092 + mat - the matrix 3093 . row - row permutation 3094 . col - column permutation 3095 - info - structure containing 3096 .vb 3097 levels - number of levels of fill. 3098 expected fill - as ratio of original fill. 3099 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 3100 missing diagonal entries) 3101 .ve 3102 3103 Level: developer 3104 3105 Notes: 3106 Most users should employ the `KSP` interface for linear solvers 3107 instead of working directly with matrix algebra routines such as this. 3108 See, e.g., `KSPCreate()`. 3109 3110 Probably really in-place only when level of fill is zero, otherwise allocates 3111 new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()` 3112 when not using `KSP`. 3113 3114 Developer Notes: 3115 The Fortran interface is not autogenerated as the 3116 interface definition cannot be generated correctly [due to MatFactorInfo] 3117 3118 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 3119 @*/ 3120 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3121 { 3122 PetscFunctionBegin; 3123 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3124 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3125 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3126 PetscValidPointer(info, 4); 3127 PetscValidType(mat, 1); 3128 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 3129 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3130 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3131 MatCheckPreallocated(mat, 1); 3132 3133 PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0)); 3134 PetscUseTypeMethod(mat, ilufactor, row, col, info); 3135 PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0)); 3136 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3137 PetscFunctionReturn(PETSC_SUCCESS); 3138 } 3139 3140 /*@C 3141 MatLUFactorSymbolic - Performs symbolic LU factorization of matrix. 3142 Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`. 3143 3144 Collective 3145 3146 Input Parameters: 3147 + fact - the factor matrix obtained with `MatGetFactor()` 3148 . mat - the matrix 3149 . row - the row permutation 3150 . col - the column permutation 3151 - info - options for factorization, includes 3152 .vb 3153 fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use 3154 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3155 .ve 3156 3157 Level: developer 3158 3159 Notes: 3160 See [Matrix Factorization](sec_matfactor) for additional information about factorizations 3161 3162 Most users should employ the simplified `KSP` interface for linear solvers 3163 instead of working directly with matrix algebra routines such as this. 3164 See, e.g., `KSPCreate()`. 3165 3166 Developer Notes: 3167 The Fortran interface is not autogenerated as the 3168 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3169 3170 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3171 @*/ 3172 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 3173 { 3174 MatFactorInfo tinfo; 3175 3176 PetscFunctionBegin; 3177 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3178 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3179 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 3180 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 3181 if (info) PetscValidPointer(info, 5); 3182 PetscValidType(fact, 1); 3183 PetscValidType(mat, 2); 3184 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3185 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3186 MatCheckPreallocated(mat, 2); 3187 if (!info) { 3188 PetscCall(MatFactorInfoInitialize(&tinfo)); 3189 info = &tinfo; 3190 } 3191 3192 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0)); 3193 PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info); 3194 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0)); 3195 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3196 PetscFunctionReturn(PETSC_SUCCESS); 3197 } 3198 3199 /*@C 3200 MatLUFactorNumeric - Performs numeric LU factorization of a matrix. 3201 Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`. 3202 3203 Collective 3204 3205 Input Parameters: 3206 + fact - the factor matrix obtained with `MatGetFactor()` 3207 . mat - the matrix 3208 - info - options for factorization 3209 3210 Level: developer 3211 3212 Notes: 3213 See `MatLUFactor()` for in-place factorization. See 3214 `MatCholeskyFactorNumeric()` for the symmetric, positive definite case. 3215 3216 Most users should employ the `KSP` interface for linear solvers 3217 instead of working directly with matrix algebra routines such as this. 3218 See, e.g., `KSPCreate()`. 3219 3220 Developer Notes: 3221 The Fortran interface is not autogenerated as the 3222 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3223 3224 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()` 3225 @*/ 3226 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3227 { 3228 MatFactorInfo tinfo; 3229 3230 PetscFunctionBegin; 3231 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3232 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3233 PetscValidType(fact, 1); 3234 PetscValidType(mat, 2); 3235 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3236 PetscCheck(mat->rmap->N == (fact)->rmap->N && mat->cmap->N == (fact)->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Mat fact: global dimensions are different %" PetscInt_FMT " should = %" PetscInt_FMT " %" PetscInt_FMT " should = %" PetscInt_FMT, 3237 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3238 3239 MatCheckPreallocated(mat, 2); 3240 if (!info) { 3241 PetscCall(MatFactorInfoInitialize(&tinfo)); 3242 info = &tinfo; 3243 } 3244 3245 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3246 else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0)); 3247 PetscUseTypeMethod(fact, lufactornumeric, mat, info); 3248 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3249 else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0)); 3250 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3251 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3252 PetscFunctionReturn(PETSC_SUCCESS); 3253 } 3254 3255 /*@C 3256 MatCholeskyFactor - Performs in-place Cholesky factorization of a 3257 symmetric matrix. 3258 3259 Collective 3260 3261 Input Parameters: 3262 + mat - the matrix 3263 . perm - row and column permutations 3264 - info - expected fill as ratio of original fill 3265 3266 Level: developer 3267 3268 Notes: 3269 See `MatLUFactor()` for the nonsymmetric case. See also `MatGetFactor()`, 3270 `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`. 3271 3272 Most users should employ the `KSP` interface for linear solvers 3273 instead of working directly with matrix algebra routines such as this. 3274 See, e.g., `KSPCreate()`. 3275 3276 Developer Notes: 3277 The Fortran interface is not autogenerated as the 3278 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3279 3280 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()` 3281 `MatGetOrdering()` 3282 @*/ 3283 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info) 3284 { 3285 MatFactorInfo tinfo; 3286 3287 PetscFunctionBegin; 3288 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3289 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2); 3290 if (info) PetscValidPointer(info, 3); 3291 PetscValidType(mat, 1); 3292 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3293 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3294 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3295 MatCheckPreallocated(mat, 1); 3296 if (!info) { 3297 PetscCall(MatFactorInfoInitialize(&tinfo)); 3298 info = &tinfo; 3299 } 3300 3301 PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0)); 3302 PetscUseTypeMethod(mat, choleskyfactor, perm, info); 3303 PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0)); 3304 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3305 PetscFunctionReturn(PETSC_SUCCESS); 3306 } 3307 3308 /*@C 3309 MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization 3310 of a symmetric matrix. 3311 3312 Collective 3313 3314 Input Parameters: 3315 + fact - the factor matrix obtained with `MatGetFactor()` 3316 . mat - the matrix 3317 . perm - row and column permutations 3318 - info - options for factorization, includes 3319 .vb 3320 fill - expected fill as ratio of original fill. 3321 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3322 Run with the option -info to determine an optimal value to use 3323 .ve 3324 3325 Level: developer 3326 3327 Notes: 3328 See `MatLUFactorSymbolic()` for the nonsymmetric case. See also 3329 `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`. 3330 3331 Most users should employ the `KSP` interface for linear solvers 3332 instead of working directly with matrix algebra routines such as this. 3333 See, e.g., `KSPCreate()`. 3334 3335 Developer Notes: 3336 The Fortran interface is not autogenerated as the 3337 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3338 3339 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()` 3340 `MatGetOrdering()` 3341 @*/ 3342 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 3343 { 3344 MatFactorInfo tinfo; 3345 3346 PetscFunctionBegin; 3347 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3348 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3349 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 3350 if (info) PetscValidPointer(info, 4); 3351 PetscValidType(fact, 1); 3352 PetscValidType(mat, 2); 3353 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3354 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3355 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3356 MatCheckPreallocated(mat, 2); 3357 if (!info) { 3358 PetscCall(MatFactorInfoInitialize(&tinfo)); 3359 info = &tinfo; 3360 } 3361 3362 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3363 PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info); 3364 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3365 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3366 PetscFunctionReturn(PETSC_SUCCESS); 3367 } 3368 3369 /*@C 3370 MatCholeskyFactorNumeric - Performs numeric Cholesky factorization 3371 of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and 3372 `MatCholeskyFactorSymbolic()`. 3373 3374 Collective 3375 3376 Input Parameters: 3377 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored 3378 . mat - the initial matrix that is to be factored 3379 - info - options for factorization 3380 3381 Level: developer 3382 3383 Note: 3384 Most users should employ the `KSP` interface for linear solvers 3385 instead of working directly with matrix algebra routines such as this. 3386 See, e.g., `KSPCreate()`. 3387 3388 Developer Notes: 3389 The Fortran interface is not autogenerated as the 3390 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3391 3392 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()` 3393 @*/ 3394 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3395 { 3396 MatFactorInfo tinfo; 3397 3398 PetscFunctionBegin; 3399 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3400 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3401 PetscValidType(fact, 1); 3402 PetscValidType(mat, 2); 3403 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3404 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, 3405 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3406 MatCheckPreallocated(mat, 2); 3407 if (!info) { 3408 PetscCall(MatFactorInfoInitialize(&tinfo)); 3409 info = &tinfo; 3410 } 3411 3412 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3413 else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0)); 3414 PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info); 3415 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3416 else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0)); 3417 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3418 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3419 PetscFunctionReturn(PETSC_SUCCESS); 3420 } 3421 3422 /*@ 3423 MatQRFactor - Performs in-place QR factorization of matrix. 3424 3425 Collective 3426 3427 Input Parameters: 3428 + mat - the matrix 3429 . col - column permutation 3430 - info - options for factorization, includes 3431 .vb 3432 fill - expected fill as ratio of original fill. 3433 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3434 Run with the option -info to determine an optimal value to use 3435 .ve 3436 3437 Level: developer 3438 3439 Notes: 3440 Most users should employ the `KSP` interface for linear solvers 3441 instead of working directly with matrix algebra routines such as this. 3442 See, e.g., `KSPCreate()`. 3443 3444 This changes the state of the matrix to a factored matrix; it cannot be used 3445 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3446 3447 Developer Notes: 3448 The Fortran interface is not autogenerated as the 3449 interface definition cannot be generated correctly [due to MatFactorInfo] 3450 3451 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`, 3452 `MatSetUnfactored()` 3453 @*/ 3454 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info) 3455 { 3456 PetscFunctionBegin; 3457 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3458 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2); 3459 if (info) PetscValidPointer(info, 3); 3460 PetscValidType(mat, 1); 3461 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3462 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3463 MatCheckPreallocated(mat, 1); 3464 PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0)); 3465 PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info)); 3466 PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0)); 3467 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3468 PetscFunctionReturn(PETSC_SUCCESS); 3469 } 3470 3471 /*@ 3472 MatQRFactorSymbolic - Performs symbolic QR factorization of matrix. 3473 Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`. 3474 3475 Collective 3476 3477 Input Parameters: 3478 + fact - the factor matrix obtained with `MatGetFactor()` 3479 . mat - the matrix 3480 . col - column permutation 3481 - info - options for factorization, includes 3482 .vb 3483 fill - expected fill as ratio of original fill. 3484 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3485 Run with the option -info to determine an optimal value to use 3486 .ve 3487 3488 Level: developer 3489 3490 Note: 3491 Most users should employ the `KSP` interface for linear solvers 3492 instead of working directly with matrix algebra routines such as this. 3493 See, e.g., `KSPCreate()`. 3494 3495 Developer Notes: 3496 The Fortran interface is not autogenerated as the 3497 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3498 3499 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfoInitialize()` 3500 @*/ 3501 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info) 3502 { 3503 MatFactorInfo tinfo; 3504 3505 PetscFunctionBegin; 3506 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3507 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3508 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3509 if (info) PetscValidPointer(info, 4); 3510 PetscValidType(fact, 1); 3511 PetscValidType(mat, 2); 3512 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3513 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3514 MatCheckPreallocated(mat, 2); 3515 if (!info) { 3516 PetscCall(MatFactorInfoInitialize(&tinfo)); 3517 info = &tinfo; 3518 } 3519 3520 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3521 PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info)); 3522 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3523 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3524 PetscFunctionReturn(PETSC_SUCCESS); 3525 } 3526 3527 /*@ 3528 MatQRFactorNumeric - Performs numeric QR factorization of a matrix. 3529 Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`. 3530 3531 Collective 3532 3533 Input Parameters: 3534 + fact - the factor matrix obtained with `MatGetFactor()` 3535 . mat - the matrix 3536 - info - options for factorization 3537 3538 Level: developer 3539 3540 Notes: 3541 See `MatQRFactor()` for in-place factorization. 3542 3543 Most users should employ the `KSP` interface for linear solvers 3544 instead of working directly with matrix algebra routines such as this. 3545 See, e.g., `KSPCreate()`. 3546 3547 Developer Notes: 3548 The Fortran interface is not autogenerated as the 3549 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3550 3551 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()` 3552 @*/ 3553 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3554 { 3555 MatFactorInfo tinfo; 3556 3557 PetscFunctionBegin; 3558 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3559 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3560 PetscValidType(fact, 1); 3561 PetscValidType(mat, 2); 3562 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3563 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, 3564 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3565 3566 MatCheckPreallocated(mat, 2); 3567 if (!info) { 3568 PetscCall(MatFactorInfoInitialize(&tinfo)); 3569 info = &tinfo; 3570 } 3571 3572 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3573 else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0)); 3574 PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info)); 3575 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3576 else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0)); 3577 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3578 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3579 PetscFunctionReturn(PETSC_SUCCESS); 3580 } 3581 3582 /*@ 3583 MatSolve - Solves A x = b, given a factored matrix. 3584 3585 Neighbor-wise Collective 3586 3587 Input Parameters: 3588 + mat - the factored matrix 3589 - b - the right-hand-side vector 3590 3591 Output Parameter: 3592 . x - the result vector 3593 3594 Level: developer 3595 3596 Notes: 3597 The vectors `b` and `x` cannot be the same. I.e., one cannot 3598 call `MatSolve`(A,x,x). 3599 3600 Most users should employ the `KSP` interface for linear solvers 3601 instead of working directly with matrix algebra routines such as this. 3602 See, e.g., `KSPCreate()`. 3603 3604 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3605 @*/ 3606 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x) 3607 { 3608 PetscFunctionBegin; 3609 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3610 PetscValidType(mat, 1); 3611 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3612 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3613 PetscCheckSameComm(mat, 1, b, 2); 3614 PetscCheckSameComm(mat, 1, x, 3); 3615 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3616 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); 3617 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); 3618 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); 3619 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3620 MatCheckPreallocated(mat, 1); 3621 3622 PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0)); 3623 if (mat->factorerrortype) { 3624 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3625 PetscCall(VecSetInf(x)); 3626 } else PetscUseTypeMethod(mat, solve, b, x); 3627 PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0)); 3628 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3629 PetscFunctionReturn(PETSC_SUCCESS); 3630 } 3631 3632 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans) 3633 { 3634 Vec b, x; 3635 PetscInt N, i; 3636 PetscErrorCode (*f)(Mat, Vec, Vec); 3637 PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE; 3638 3639 PetscFunctionBegin; 3640 if (A->factorerrortype) { 3641 PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype)); 3642 PetscCall(MatSetInf(X)); 3643 PetscFunctionReturn(PETSC_SUCCESS); 3644 } 3645 f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose; 3646 PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 3647 PetscCall(MatBoundToCPU(A, &Abound)); 3648 if (!Abound) { 3649 PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3650 PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3651 } 3652 #if PetscDefined(HAVE_CUDA) 3653 if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B)); 3654 if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X)); 3655 #elif PetscDefined(HAVE_HIP) 3656 if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B)); 3657 if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X)); 3658 #endif 3659 PetscCall(MatGetSize(B, NULL, &N)); 3660 for (i = 0; i < N; i++) { 3661 PetscCall(MatDenseGetColumnVecRead(B, i, &b)); 3662 PetscCall(MatDenseGetColumnVecWrite(X, i, &x)); 3663 PetscCall((*f)(A, b, x)); 3664 PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x)); 3665 PetscCall(MatDenseRestoreColumnVecRead(B, i, &b)); 3666 } 3667 if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B)); 3668 if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X)); 3669 PetscFunctionReturn(PETSC_SUCCESS); 3670 } 3671 3672 /*@ 3673 MatMatSolve - Solves A X = B, given a factored matrix. 3674 3675 Neighbor-wise Collective 3676 3677 Input Parameters: 3678 + A - the factored matrix 3679 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS) 3680 3681 Output Parameter: 3682 . X - the result matrix (dense matrix) 3683 3684 Level: developer 3685 3686 Note: 3687 If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`; 3688 otherwise, `B` and `X` cannot be the same. 3689 3690 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3691 @*/ 3692 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X) 3693 { 3694 PetscFunctionBegin; 3695 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3696 PetscValidType(A, 1); 3697 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3698 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3699 PetscCheckSameComm(A, 1, B, 2); 3700 PetscCheckSameComm(A, 1, X, 3); 3701 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); 3702 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); 3703 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"); 3704 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3705 MatCheckPreallocated(A, 1); 3706 3707 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3708 if (!A->ops->matsolve) { 3709 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name)); 3710 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE)); 3711 } else PetscUseTypeMethod(A, matsolve, B, X); 3712 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3713 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3714 PetscFunctionReturn(PETSC_SUCCESS); 3715 } 3716 3717 /*@ 3718 MatMatSolveTranspose - Solves A^T X = B, given a factored matrix. 3719 3720 Neighbor-wise Collective 3721 3722 Input Parameters: 3723 + A - the factored matrix 3724 - B - the right-hand-side matrix (`MATDENSE` matrix) 3725 3726 Output Parameter: 3727 . X - the result matrix (dense matrix) 3728 3729 Level: developer 3730 3731 Note: 3732 The matrices `B` and `X` cannot be the same. I.e., one cannot 3733 call `MatMatSolveTranspose`(A,X,X). 3734 3735 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()` 3736 @*/ 3737 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X) 3738 { 3739 PetscFunctionBegin; 3740 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3741 PetscValidType(A, 1); 3742 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3743 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3744 PetscCheckSameComm(A, 1, B, 2); 3745 PetscCheckSameComm(A, 1, X, 3); 3746 PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3747 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); 3748 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); 3749 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); 3750 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"); 3751 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3752 MatCheckPreallocated(A, 1); 3753 3754 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3755 if (!A->ops->matsolvetranspose) { 3756 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name)); 3757 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE)); 3758 } else PetscUseTypeMethod(A, matsolvetranspose, B, X); 3759 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3760 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3761 PetscFunctionReturn(PETSC_SUCCESS); 3762 } 3763 3764 /*@ 3765 MatMatTransposeSolve - Solves A X = B^T, given a factored matrix. 3766 3767 Neighbor-wise Collective 3768 3769 Input Parameters: 3770 + A - the factored matrix 3771 - Bt - the transpose of right-hand-side matrix as a `MATDENSE` 3772 3773 Output Parameter: 3774 . X - the result matrix (dense matrix) 3775 3776 Level: developer 3777 3778 Note: 3779 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 3780 format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`. 3781 3782 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3783 @*/ 3784 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X) 3785 { 3786 PetscFunctionBegin; 3787 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3788 PetscValidType(A, 1); 3789 PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2); 3790 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3791 PetscCheckSameComm(A, 1, Bt, 2); 3792 PetscCheckSameComm(A, 1, X, 3); 3793 3794 PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3795 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); 3796 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); 3797 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"); 3798 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3799 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3800 MatCheckPreallocated(A, 1); 3801 3802 PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0)); 3803 PetscUseTypeMethod(A, mattransposesolve, Bt, X); 3804 PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0)); 3805 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3806 PetscFunctionReturn(PETSC_SUCCESS); 3807 } 3808 3809 /*@ 3810 MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or 3811 U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U, 3812 3813 Neighbor-wise Collective 3814 3815 Input Parameters: 3816 + mat - the factored matrix 3817 - b - the right-hand-side vector 3818 3819 Output Parameter: 3820 . x - the result vector 3821 3822 Level: developer 3823 3824 Notes: 3825 `MatSolve()` should be used for most applications, as it performs 3826 a forward solve followed by a backward solve. 3827 3828 The vectors `b` and `x` cannot be the same, i.e., one cannot 3829 call `MatForwardSolve`(A,x,x). 3830 3831 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3832 the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet. 3833 `MatForwardSolve()` solves U^T*D y = b, and 3834 `MatBackwardSolve()` solves U x = y. 3835 Thus they do not provide a symmetric preconditioner. 3836 3837 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()` 3838 @*/ 3839 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x) 3840 { 3841 PetscFunctionBegin; 3842 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3843 PetscValidType(mat, 1); 3844 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3845 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3846 PetscCheckSameComm(mat, 1, b, 2); 3847 PetscCheckSameComm(mat, 1, x, 3); 3848 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3849 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); 3850 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); 3851 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); 3852 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3853 MatCheckPreallocated(mat, 1); 3854 3855 PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0)); 3856 PetscUseTypeMethod(mat, forwardsolve, b, x); 3857 PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0)); 3858 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3859 PetscFunctionReturn(PETSC_SUCCESS); 3860 } 3861 3862 /*@ 3863 MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU. 3864 D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U, 3865 3866 Neighbor-wise Collective 3867 3868 Input Parameters: 3869 + mat - the factored matrix 3870 - b - the right-hand-side vector 3871 3872 Output Parameter: 3873 . x - the result vector 3874 3875 Level: developer 3876 3877 Notes: 3878 `MatSolve()` should be used for most applications, as it performs 3879 a forward solve followed by a backward solve. 3880 3881 The vectors `b` and `x` cannot be the same. I.e., one cannot 3882 call `MatBackwardSolve`(A,x,x). 3883 3884 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3885 the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet. 3886 `MatForwardSolve()` solves U^T*D y = b, and 3887 `MatBackwardSolve()` solves U x = y. 3888 Thus they do not provide a symmetric preconditioner. 3889 3890 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()` 3891 @*/ 3892 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x) 3893 { 3894 PetscFunctionBegin; 3895 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3896 PetscValidType(mat, 1); 3897 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3898 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3899 PetscCheckSameComm(mat, 1, b, 2); 3900 PetscCheckSameComm(mat, 1, x, 3); 3901 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3902 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); 3903 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); 3904 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); 3905 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3906 MatCheckPreallocated(mat, 1); 3907 3908 PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0)); 3909 PetscUseTypeMethod(mat, backwardsolve, b, x); 3910 PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0)); 3911 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3912 PetscFunctionReturn(PETSC_SUCCESS); 3913 } 3914 3915 /*@ 3916 MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix. 3917 3918 Neighbor-wise Collective 3919 3920 Input Parameters: 3921 + mat - the factored matrix 3922 . b - the right-hand-side vector 3923 - y - the vector to be added to 3924 3925 Output Parameter: 3926 . x - the result vector 3927 3928 Level: developer 3929 3930 Note: 3931 The vectors `b` and `x` cannot be the same. I.e., one cannot 3932 call `MatSolveAdd`(A,x,y,x). 3933 3934 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3935 @*/ 3936 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x) 3937 { 3938 PetscScalar one = 1.0; 3939 Vec tmp; 3940 3941 PetscFunctionBegin; 3942 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3943 PetscValidType(mat, 1); 3944 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 3945 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3946 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 3947 PetscCheckSameComm(mat, 1, b, 2); 3948 PetscCheckSameComm(mat, 1, y, 3); 3949 PetscCheckSameComm(mat, 1, x, 4); 3950 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3951 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); 3952 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); 3953 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); 3954 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); 3955 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); 3956 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3957 MatCheckPreallocated(mat, 1); 3958 3959 PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y)); 3960 if (mat->factorerrortype) { 3961 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3962 PetscCall(VecSetInf(x)); 3963 } else if (mat->ops->solveadd) { 3964 PetscUseTypeMethod(mat, solveadd, b, y, x); 3965 } else { 3966 /* do the solve then the add manually */ 3967 if (x != y) { 3968 PetscCall(MatSolve(mat, b, x)); 3969 PetscCall(VecAXPY(x, one, y)); 3970 } else { 3971 PetscCall(VecDuplicate(x, &tmp)); 3972 PetscCall(VecCopy(x, tmp)); 3973 PetscCall(MatSolve(mat, b, x)); 3974 PetscCall(VecAXPY(x, one, tmp)); 3975 PetscCall(VecDestroy(&tmp)); 3976 } 3977 } 3978 PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y)); 3979 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3980 PetscFunctionReturn(PETSC_SUCCESS); 3981 } 3982 3983 /*@ 3984 MatSolveTranspose - Solves A' x = b, given a factored matrix. 3985 3986 Neighbor-wise Collective 3987 3988 Input Parameters: 3989 + mat - the factored matrix 3990 - b - the right-hand-side vector 3991 3992 Output Parameter: 3993 . x - the result vector 3994 3995 Level: developer 3996 3997 Notes: 3998 The vectors `b` and `x` cannot be the same. I.e., one cannot 3999 call `MatSolveTranspose`(A,x,x). 4000 4001 Most users should employ the `KSP` interface for linear solvers 4002 instead of working directly with matrix algebra routines such as this. 4003 See, e.g., `KSPCreate()`. 4004 4005 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()` 4006 @*/ 4007 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x) 4008 { 4009 PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose; 4010 4011 PetscFunctionBegin; 4012 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4013 PetscValidType(mat, 1); 4014 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4015 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 4016 PetscCheckSameComm(mat, 1, b, 2); 4017 PetscCheckSameComm(mat, 1, x, 3); 4018 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4019 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); 4020 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); 4021 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4022 MatCheckPreallocated(mat, 1); 4023 PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0)); 4024 if (mat->factorerrortype) { 4025 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4026 PetscCall(VecSetInf(x)); 4027 } else { 4028 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name); 4029 PetscCall((*f)(mat, b, x)); 4030 } 4031 PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0)); 4032 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4033 PetscFunctionReturn(PETSC_SUCCESS); 4034 } 4035 4036 /*@ 4037 MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a 4038 factored matrix. 4039 4040 Neighbor-wise Collective 4041 4042 Input Parameters: 4043 + mat - the factored matrix 4044 . b - the right-hand-side vector 4045 - y - the vector to be added to 4046 4047 Output Parameter: 4048 . x - the result vector 4049 4050 Level: developer 4051 4052 Note: 4053 The vectors `b` and `x` cannot be the same. I.e., one cannot 4054 call `MatSolveTransposeAdd`(A,x,y,x). 4055 4056 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()` 4057 @*/ 4058 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x) 4059 { 4060 PetscScalar one = 1.0; 4061 Vec tmp; 4062 PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd; 4063 4064 PetscFunctionBegin; 4065 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4066 PetscValidType(mat, 1); 4067 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4068 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4069 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4070 PetscCheckSameComm(mat, 1, b, 2); 4071 PetscCheckSameComm(mat, 1, y, 3); 4072 PetscCheckSameComm(mat, 1, x, 4); 4073 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4074 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); 4075 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); 4076 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); 4077 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); 4078 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4079 MatCheckPreallocated(mat, 1); 4080 4081 PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y)); 4082 if (mat->factorerrortype) { 4083 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4084 PetscCall(VecSetInf(x)); 4085 } else if (f) { 4086 PetscCall((*f)(mat, b, y, x)); 4087 } else { 4088 /* do the solve then the add manually */ 4089 if (x != y) { 4090 PetscCall(MatSolveTranspose(mat, b, x)); 4091 PetscCall(VecAXPY(x, one, y)); 4092 } else { 4093 PetscCall(VecDuplicate(x, &tmp)); 4094 PetscCall(VecCopy(x, tmp)); 4095 PetscCall(MatSolveTranspose(mat, b, x)); 4096 PetscCall(VecAXPY(x, one, tmp)); 4097 PetscCall(VecDestroy(&tmp)); 4098 } 4099 } 4100 PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y)); 4101 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4102 PetscFunctionReturn(PETSC_SUCCESS); 4103 } 4104 4105 /*@ 4106 MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps. 4107 4108 Neighbor-wise Collective 4109 4110 Input Parameters: 4111 + mat - the matrix 4112 . b - the right hand side 4113 . omega - the relaxation factor 4114 . flag - flag indicating the type of SOR (see below) 4115 . shift - diagonal shift 4116 . its - the number of iterations 4117 - lits - the number of local iterations 4118 4119 Output Parameter: 4120 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess) 4121 4122 SOR Flags: 4123 + `SOR_FORWARD_SWEEP` - forward SOR 4124 . `SOR_BACKWARD_SWEEP` - backward SOR 4125 . `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR) 4126 . `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR 4127 . `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR 4128 . `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR 4129 . `SOR_EISENSTAT` - SOR with Eisenstat trick 4130 . `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies 4131 upper/lower triangular part of matrix to 4132 vector (with omega) 4133 - `SOR_ZERO_INITIAL_GUESS` - zero initial guess 4134 4135 Level: developer 4136 4137 Notes: 4138 `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and 4139 `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings 4140 on each processor. 4141 4142 Application programmers will not generally use `MatSOR()` directly, 4143 but instead will employ the `KSP`/`PC` interface. 4144 4145 For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing 4146 4147 Most users should employ the `KSP` interface for linear solvers 4148 instead of working directly with matrix algebra routines such as this. 4149 See, e.g., `KSPCreate()`. 4150 4151 Vectors `x` and `b` CANNOT be the same 4152 4153 The flags are implemented as bitwise inclusive or operations. 4154 For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`) 4155 to specify a zero initial guess for SSOR. 4156 4157 Developer Notes: 4158 We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes 4159 4160 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()` 4161 @*/ 4162 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x) 4163 { 4164 PetscFunctionBegin; 4165 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4166 PetscValidType(mat, 1); 4167 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4168 PetscValidHeaderSpecific(x, VEC_CLASSID, 8); 4169 PetscCheckSameComm(mat, 1, b, 2); 4170 PetscCheckSameComm(mat, 1, x, 8); 4171 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4172 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4173 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); 4174 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); 4175 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); 4176 PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its); 4177 PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits); 4178 PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same"); 4179 4180 MatCheckPreallocated(mat, 1); 4181 PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0)); 4182 PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x); 4183 PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0)); 4184 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4185 PetscFunctionReturn(PETSC_SUCCESS); 4186 } 4187 4188 /* 4189 Default matrix copy routine. 4190 */ 4191 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str) 4192 { 4193 PetscInt i, rstart = 0, rend = 0, nz; 4194 const PetscInt *cwork; 4195 const PetscScalar *vwork; 4196 4197 PetscFunctionBegin; 4198 if (B->assembled) PetscCall(MatZeroEntries(B)); 4199 if (str == SAME_NONZERO_PATTERN) { 4200 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 4201 for (i = rstart; i < rend; i++) { 4202 PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork)); 4203 PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES)); 4204 PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork)); 4205 } 4206 } else { 4207 PetscCall(MatAYPX(B, 0.0, A, str)); 4208 } 4209 PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 4210 PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 4211 PetscFunctionReturn(PETSC_SUCCESS); 4212 } 4213 4214 /*@ 4215 MatCopy - Copies a matrix to another matrix. 4216 4217 Collective 4218 4219 Input Parameters: 4220 + A - the matrix 4221 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN` 4222 4223 Output Parameter: 4224 . B - where the copy is put 4225 4226 Level: intermediate 4227 4228 Notes: 4229 If you use `SAME_NONZERO_PATTERN` then the two matrices must have the same nonzero pattern or the routine will crash. 4230 4231 `MatCopy()` copies the matrix entries of a matrix to another existing 4232 matrix (after first zeroing the second matrix). A related routine is 4233 `MatConvert()`, which first creates a new matrix and then copies the data. 4234 4235 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()` 4236 @*/ 4237 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str) 4238 { 4239 PetscInt i; 4240 4241 PetscFunctionBegin; 4242 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 4243 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 4244 PetscValidType(A, 1); 4245 PetscValidType(B, 2); 4246 PetscCheckSameComm(A, 1, B, 2); 4247 MatCheckPreallocated(B, 2); 4248 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4249 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4250 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, 4251 A->cmap->N, B->cmap->N); 4252 MatCheckPreallocated(A, 1); 4253 if (A == B) PetscFunctionReturn(PETSC_SUCCESS); 4254 4255 PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0)); 4256 if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str); 4257 else PetscCall(MatCopy_Basic(A, B, str)); 4258 4259 B->stencil.dim = A->stencil.dim; 4260 B->stencil.noc = A->stencil.noc; 4261 for (i = 0; i <= A->stencil.dim; i++) { 4262 B->stencil.dims[i] = A->stencil.dims[i]; 4263 B->stencil.starts[i] = A->stencil.starts[i]; 4264 } 4265 4266 PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0)); 4267 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4268 PetscFunctionReturn(PETSC_SUCCESS); 4269 } 4270 4271 /*@C 4272 MatConvert - Converts a matrix to another matrix, either of the same 4273 or different type. 4274 4275 Collective 4276 4277 Input Parameters: 4278 + mat - the matrix 4279 . newtype - new matrix type. Use `MATSAME` to create a new matrix of the 4280 same type as the original matrix. 4281 - reuse - denotes if the destination matrix is to be created or reused. 4282 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 4283 `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). 4284 4285 Output Parameter: 4286 . M - pointer to place new matrix 4287 4288 Level: intermediate 4289 4290 Notes: 4291 `MatConvert()` first creates a new matrix and then copies the data from 4292 the first matrix. A related routine is `MatCopy()`, which copies the matrix 4293 entries of one matrix to another already existing matrix context. 4294 4295 Cannot be used to convert a sequential matrix to parallel or parallel to sequential, 4296 the MPI communicator of the generated matrix is always the same as the communicator 4297 of the input matrix. 4298 4299 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 4300 @*/ 4301 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M) 4302 { 4303 PetscBool sametype, issame, flg; 4304 PetscBool3 issymmetric, ishermitian; 4305 char convname[256], mtype[256]; 4306 Mat B; 4307 4308 PetscFunctionBegin; 4309 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4310 PetscValidType(mat, 1); 4311 PetscValidPointer(M, 4); 4312 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4313 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4314 MatCheckPreallocated(mat, 1); 4315 4316 PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg)); 4317 if (flg) newtype = mtype; 4318 4319 PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype)); 4320 PetscCall(PetscStrcmp(newtype, "same", &issame)); 4321 PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix"); 4322 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"); 4323 4324 if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) { 4325 PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4326 PetscFunctionReturn(PETSC_SUCCESS); 4327 } 4328 4329 /* Cache Mat options because some converters use MatHeaderReplace */ 4330 issymmetric = mat->symmetric; 4331 ishermitian = mat->hermitian; 4332 4333 if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) { 4334 PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4335 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4336 } else { 4337 PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL; 4338 const char *prefix[3] = {"seq", "mpi", ""}; 4339 PetscInt i; 4340 /* 4341 Order of precedence: 4342 0) See if newtype is a superclass of the current matrix. 4343 1) See if a specialized converter is known to the current matrix. 4344 2) See if a specialized converter is known to the desired matrix class. 4345 3) See if a good general converter is registered for the desired class 4346 (as of 6/27/03 only MATMPIADJ falls into this category). 4347 4) See if a good general converter is known for the current matrix. 4348 5) Use a really basic converter. 4349 */ 4350 4351 /* 0) See if newtype is a superclass of the current matrix. 4352 i.e mat is mpiaij and newtype is aij */ 4353 for (i = 0; i < 2; i++) { 4354 PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname))); 4355 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4356 PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg)); 4357 PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg)); 4358 if (flg) { 4359 if (reuse == MAT_INPLACE_MATRIX) { 4360 PetscCall(PetscInfo(mat, "Early return\n")); 4361 PetscFunctionReturn(PETSC_SUCCESS); 4362 } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) { 4363 PetscCall(PetscInfo(mat, "Calling MatDuplicate\n")); 4364 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4365 PetscFunctionReturn(PETSC_SUCCESS); 4366 } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) { 4367 PetscCall(PetscInfo(mat, "Calling MatCopy\n")); 4368 PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN)); 4369 PetscFunctionReturn(PETSC_SUCCESS); 4370 } 4371 } 4372 } 4373 /* 1) See if a specialized converter is known to the current matrix and the desired class */ 4374 for (i = 0; i < 3; i++) { 4375 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4376 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4377 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4378 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4379 PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname))); 4380 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4381 PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv)); 4382 PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv)); 4383 if (conv) goto foundconv; 4384 } 4385 4386 /* 2) See if a specialized converter is known to the desired matrix class. */ 4387 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B)); 4388 PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 4389 PetscCall(MatSetType(B, newtype)); 4390 for (i = 0; i < 3; i++) { 4391 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4392 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4393 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4394 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4395 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4396 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4397 PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv)); 4398 PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv)); 4399 if (conv) { 4400 PetscCall(MatDestroy(&B)); 4401 goto foundconv; 4402 } 4403 } 4404 4405 /* 3) See if a good general converter is registered for the desired class */ 4406 conv = B->ops->convertfrom; 4407 PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv)); 4408 PetscCall(MatDestroy(&B)); 4409 if (conv) goto foundconv; 4410 4411 /* 4) See if a good general converter is known for the current matrix */ 4412 if (mat->ops->convert) conv = mat->ops->convert; 4413 PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv)); 4414 if (conv) goto foundconv; 4415 4416 /* 5) Use a really basic converter. */ 4417 PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n")); 4418 conv = MatConvert_Basic; 4419 4420 foundconv: 4421 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4422 PetscCall((*conv)(mat, newtype, reuse, M)); 4423 if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) { 4424 /* the block sizes must be same if the mappings are copied over */ 4425 (*M)->rmap->bs = mat->rmap->bs; 4426 (*M)->cmap->bs = mat->cmap->bs; 4427 PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping)); 4428 PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping)); 4429 (*M)->rmap->mapping = mat->rmap->mapping; 4430 (*M)->cmap->mapping = mat->cmap->mapping; 4431 } 4432 (*M)->stencil.dim = mat->stencil.dim; 4433 (*M)->stencil.noc = mat->stencil.noc; 4434 for (i = 0; i <= mat->stencil.dim; i++) { 4435 (*M)->stencil.dims[i] = mat->stencil.dims[i]; 4436 (*M)->stencil.starts[i] = mat->stencil.starts[i]; 4437 } 4438 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4439 } 4440 PetscCall(PetscObjectStateIncrease((PetscObject)*M)); 4441 4442 /* Copy Mat options */ 4443 if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE)); 4444 else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE)); 4445 if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE)); 4446 else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE)); 4447 PetscFunctionReturn(PETSC_SUCCESS); 4448 } 4449 4450 /*@C 4451 MatFactorGetSolverType - Returns name of the package providing the factorization routines 4452 4453 Not Collective 4454 4455 Input Parameter: 4456 . mat - the matrix, must be a factored matrix 4457 4458 Output Parameter: 4459 . type - the string name of the package (do not free this string) 4460 4461 Level: intermediate 4462 4463 Fortran Notes: 4464 Pass in an empty string and the package name will be copied into it. Make sure the string is long enough. 4465 4466 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()` 4467 @*/ 4468 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type) 4469 { 4470 PetscErrorCode (*conv)(Mat, MatSolverType *); 4471 4472 PetscFunctionBegin; 4473 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4474 PetscValidType(mat, 1); 4475 PetscValidPointer(type, 2); 4476 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 4477 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv)); 4478 if (conv) PetscCall((*conv)(mat, type)); 4479 else *type = MATSOLVERPETSC; 4480 PetscFunctionReturn(PETSC_SUCCESS); 4481 } 4482 4483 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType; 4484 struct _MatSolverTypeForSpecifcType { 4485 MatType mtype; 4486 /* no entry for MAT_FACTOR_NONE */ 4487 PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *); 4488 MatSolverTypeForSpecifcType next; 4489 }; 4490 4491 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder; 4492 struct _MatSolverTypeHolder { 4493 char *name; 4494 MatSolverTypeForSpecifcType handlers; 4495 MatSolverTypeHolder next; 4496 }; 4497 4498 static MatSolverTypeHolder MatSolverTypeHolders = NULL; 4499 4500 /*@C 4501 MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type 4502 4503 Input Parameters: 4504 + package - name of the package, for example petsc or superlu 4505 . mtype - the matrix type that works with this package 4506 . ftype - the type of factorization supported by the package 4507 - createfactor - routine that will create the factored matrix ready to be used 4508 4509 Level: developer 4510 4511 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()` 4512 @*/ 4513 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *)) 4514 { 4515 MatSolverTypeHolder next = MatSolverTypeHolders, prev = NULL; 4516 PetscBool flg; 4517 MatSolverTypeForSpecifcType inext, iprev = NULL; 4518 4519 PetscFunctionBegin; 4520 PetscCall(MatInitializePackage()); 4521 if (!next) { 4522 PetscCall(PetscNew(&MatSolverTypeHolders)); 4523 PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name)); 4524 PetscCall(PetscNew(&MatSolverTypeHolders->handlers)); 4525 PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype)); 4526 MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor; 4527 PetscFunctionReturn(PETSC_SUCCESS); 4528 } 4529 while (next) { 4530 PetscCall(PetscStrcasecmp(package, next->name, &flg)); 4531 if (flg) { 4532 PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers"); 4533 inext = next->handlers; 4534 while (inext) { 4535 PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg)); 4536 if (flg) { 4537 inext->createfactor[(int)ftype - 1] = createfactor; 4538 PetscFunctionReturn(PETSC_SUCCESS); 4539 } 4540 iprev = inext; 4541 inext = inext->next; 4542 } 4543 PetscCall(PetscNew(&iprev->next)); 4544 PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype)); 4545 iprev->next->createfactor[(int)ftype - 1] = createfactor; 4546 PetscFunctionReturn(PETSC_SUCCESS); 4547 } 4548 prev = next; 4549 next = next->next; 4550 } 4551 PetscCall(PetscNew(&prev->next)); 4552 PetscCall(PetscStrallocpy(package, &prev->next->name)); 4553 PetscCall(PetscNew(&prev->next->handlers)); 4554 PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype)); 4555 prev->next->handlers->createfactor[(int)ftype - 1] = createfactor; 4556 PetscFunctionReturn(PETSC_SUCCESS); 4557 } 4558 4559 /*@C 4560 MatSolverTypeGet - Gets the function that creates the factor matrix if it exist 4561 4562 Input Parameters: 4563 + type - name of the package, for example petsc or superlu 4564 . ftype - the type of factorization supported by the type 4565 - mtype - the matrix type that works with this type 4566 4567 Output Parameters: 4568 + foundtype - `PETSC_TRUE` if the type was registered 4569 . foundmtype - `PETSC_TRUE` if the type supports the requested mtype 4570 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found 4571 4572 Level: developer 4573 4574 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()` 4575 @*/ 4576 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *)) 4577 { 4578 MatSolverTypeHolder next = MatSolverTypeHolders; 4579 PetscBool flg; 4580 MatSolverTypeForSpecifcType inext; 4581 4582 PetscFunctionBegin; 4583 if (foundtype) *foundtype = PETSC_FALSE; 4584 if (foundmtype) *foundmtype = PETSC_FALSE; 4585 if (createfactor) *createfactor = NULL; 4586 4587 if (type) { 4588 while (next) { 4589 PetscCall(PetscStrcasecmp(type, next->name, &flg)); 4590 if (flg) { 4591 if (foundtype) *foundtype = PETSC_TRUE; 4592 inext = next->handlers; 4593 while (inext) { 4594 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4595 if (flg) { 4596 if (foundmtype) *foundmtype = PETSC_TRUE; 4597 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4598 PetscFunctionReturn(PETSC_SUCCESS); 4599 } 4600 inext = inext->next; 4601 } 4602 } 4603 next = next->next; 4604 } 4605 } else { 4606 while (next) { 4607 inext = next->handlers; 4608 while (inext) { 4609 PetscCall(PetscStrcmp(mtype, inext->mtype, &flg)); 4610 if (flg && inext->createfactor[(int)ftype - 1]) { 4611 if (foundtype) *foundtype = PETSC_TRUE; 4612 if (foundmtype) *foundmtype = PETSC_TRUE; 4613 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4614 PetscFunctionReturn(PETSC_SUCCESS); 4615 } 4616 inext = inext->next; 4617 } 4618 next = next->next; 4619 } 4620 /* try with base classes inext->mtype */ 4621 next = MatSolverTypeHolders; 4622 while (next) { 4623 inext = next->handlers; 4624 while (inext) { 4625 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4626 if (flg && inext->createfactor[(int)ftype - 1]) { 4627 if (foundtype) *foundtype = PETSC_TRUE; 4628 if (foundmtype) *foundmtype = PETSC_TRUE; 4629 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4630 PetscFunctionReturn(PETSC_SUCCESS); 4631 } 4632 inext = inext->next; 4633 } 4634 next = next->next; 4635 } 4636 } 4637 PetscFunctionReturn(PETSC_SUCCESS); 4638 } 4639 4640 PetscErrorCode MatSolverTypeDestroy(void) 4641 { 4642 MatSolverTypeHolder next = MatSolverTypeHolders, prev; 4643 MatSolverTypeForSpecifcType inext, iprev; 4644 4645 PetscFunctionBegin; 4646 while (next) { 4647 PetscCall(PetscFree(next->name)); 4648 inext = next->handlers; 4649 while (inext) { 4650 PetscCall(PetscFree(inext->mtype)); 4651 iprev = inext; 4652 inext = inext->next; 4653 PetscCall(PetscFree(iprev)); 4654 } 4655 prev = next; 4656 next = next->next; 4657 PetscCall(PetscFree(prev)); 4658 } 4659 MatSolverTypeHolders = NULL; 4660 PetscFunctionReturn(PETSC_SUCCESS); 4661 } 4662 4663 /*@C 4664 MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4665 4666 Logically Collective 4667 4668 Input Parameter: 4669 . mat - the matrix 4670 4671 Output Parameter: 4672 . flg - `PETSC_TRUE` if uses the ordering 4673 4674 Level: developer 4675 4676 Note: 4677 Most internal PETSc factorizations use the ordering passed to the factorization routine but external 4678 packages do not, thus we want to skip generating the ordering when it is not needed or used. 4679 4680 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4681 @*/ 4682 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg) 4683 { 4684 PetscFunctionBegin; 4685 *flg = mat->canuseordering; 4686 PetscFunctionReturn(PETSC_SUCCESS); 4687 } 4688 4689 /*@C 4690 MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object 4691 4692 Logically Collective 4693 4694 Input Parameters: 4695 + mat - the matrix obtained with `MatGetFactor()` 4696 - ftype - the factorization type to be used 4697 4698 Output Parameter: 4699 . otype - the preferred ordering type 4700 4701 Level: developer 4702 4703 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4704 @*/ 4705 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype) 4706 { 4707 PetscFunctionBegin; 4708 *otype = mat->preferredordering[ftype]; 4709 PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering"); 4710 PetscFunctionReturn(PETSC_SUCCESS); 4711 } 4712 4713 /*@C 4714 MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic() 4715 4716 Collective 4717 4718 Input Parameters: 4719 + mat - the matrix 4720 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4721 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4722 4723 Output Parameter: 4724 . f - the factor matrix used with MatXXFactorSymbolic() calls. Can be `NULL` in some cases, see notes below. 4725 4726 Options Database Key: 4727 . -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory. 4728 One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices. 4729 4730 Level: intermediate 4731 4732 Notes: 4733 The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization 4734 types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime. 4735 4736 Users usually access the factorization solvers via `KSP` 4737 4738 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4739 such as pastix, superlu, mumps etc. 4740 4741 PETSc must have been ./configure to use the external solver, using the option --download-package 4742 4743 Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption 4744 where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set 4745 call `MatSetOptionsPrefixFactor()` on the originating matrix or `MatSetOptionsPrefix()` on the resulting factor matrix. 4746 4747 Developer Notes: 4748 This should actually be called `MatCreateFactor()` since it creates a new factor object 4749 4750 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, 4751 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4752 @*/ 4753 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f) 4754 { 4755 PetscBool foundtype, foundmtype; 4756 PetscErrorCode (*conv)(Mat, MatFactorType, Mat *); 4757 4758 PetscFunctionBegin; 4759 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4760 PetscValidType(mat, 1); 4761 4762 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4763 MatCheckPreallocated(mat, 1); 4764 4765 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv)); 4766 if (!foundtype) { 4767 if (type) { 4768 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], 4769 ((PetscObject)mat)->type_name, type); 4770 } else { 4771 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); 4772 } 4773 } 4774 PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name); 4775 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); 4776 4777 PetscCall((*conv)(mat, ftype, f)); 4778 if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix)); 4779 PetscFunctionReturn(PETSC_SUCCESS); 4780 } 4781 4782 /*@C 4783 MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type 4784 4785 Not Collective 4786 4787 Input Parameters: 4788 + mat - the matrix 4789 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4790 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4791 4792 Output Parameter: 4793 . flg - PETSC_TRUE if the factorization is available 4794 4795 Level: intermediate 4796 4797 Notes: 4798 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4799 such as pastix, superlu, mumps etc. 4800 4801 PETSc must have been ./configure to use the external solver, using the option --download-package 4802 4803 Developer Notes: 4804 This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object 4805 4806 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatSolverTypeRegister()`, 4807 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4808 @*/ 4809 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg) 4810 { 4811 PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *); 4812 4813 PetscFunctionBegin; 4814 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4815 PetscValidType(mat, 1); 4816 PetscValidBoolPointer(flg, 4); 4817 4818 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4819 MatCheckPreallocated(mat, 1); 4820 4821 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv)); 4822 *flg = gconv ? PETSC_TRUE : PETSC_FALSE; 4823 PetscFunctionReturn(PETSC_SUCCESS); 4824 } 4825 4826 /*@ 4827 MatDuplicate - Duplicates a matrix including the non-zero structure. 4828 4829 Collective 4830 4831 Input Parameters: 4832 + mat - the matrix 4833 - op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`. 4834 See the manual page for `MatDuplicateOption()` for an explanation of these options. 4835 4836 Output Parameter: 4837 . M - pointer to place new matrix 4838 4839 Level: intermediate 4840 4841 Notes: 4842 You cannot change the nonzero pattern for the parent or child matrix if you use `MAT_SHARE_NONZERO_PATTERN`. 4843 4844 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. 4845 4846 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 4847 is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated. 4848 User should not use `MatDuplicate()` to create new matrix M if M is intended to be reused as the product of matrix operation. 4849 4850 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption` 4851 @*/ 4852 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M) 4853 { 4854 Mat B; 4855 VecType vtype; 4856 PetscInt i; 4857 PetscObject dm, container_h, container_d; 4858 void (*viewf)(void); 4859 4860 PetscFunctionBegin; 4861 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4862 PetscValidType(mat, 1); 4863 PetscValidPointer(M, 3); 4864 PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix"); 4865 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4866 MatCheckPreallocated(mat, 1); 4867 4868 *M = NULL; 4869 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4870 PetscUseTypeMethod(mat, duplicate, op, M); 4871 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4872 B = *M; 4873 4874 PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf)); 4875 if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf)); 4876 PetscCall(MatGetVecType(mat, &vtype)); 4877 PetscCall(MatSetVecType(B, vtype)); 4878 4879 B->stencil.dim = mat->stencil.dim; 4880 B->stencil.noc = mat->stencil.noc; 4881 for (i = 0; i <= mat->stencil.dim; i++) { 4882 B->stencil.dims[i] = mat->stencil.dims[i]; 4883 B->stencil.starts[i] = mat->stencil.starts[i]; 4884 } 4885 4886 B->nooffproczerorows = mat->nooffproczerorows; 4887 B->nooffprocentries = mat->nooffprocentries; 4888 4889 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm)); 4890 if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm)); 4891 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h)); 4892 if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h)); 4893 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d)); 4894 if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d)); 4895 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4896 PetscFunctionReturn(PETSC_SUCCESS); 4897 } 4898 4899 /*@ 4900 MatGetDiagonal - Gets the diagonal of a matrix as a `Vec` 4901 4902 Logically Collective 4903 4904 Input Parameter: 4905 . mat - the matrix 4906 4907 Output Parameter: 4908 . v - the diagonal of the matrix 4909 4910 Level: intermediate 4911 4912 Note: 4913 If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries 4914 of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v` 4915 is larger than `ndiag`, the values of the remaining entries are unspecified. 4916 4917 Currently only correct in parallel for square matrices. 4918 4919 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()` 4920 @*/ 4921 PetscErrorCode MatGetDiagonal(Mat mat, Vec v) 4922 { 4923 PetscFunctionBegin; 4924 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4925 PetscValidType(mat, 1); 4926 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4927 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4928 MatCheckPreallocated(mat, 1); 4929 if (PetscDefined(USE_DEBUG)) { 4930 PetscInt nv, row, col, ndiag; 4931 4932 PetscCall(VecGetLocalSize(v, &nv)); 4933 PetscCall(MatGetLocalSize(mat, &row, &col)); 4934 ndiag = PetscMin(row, col); 4935 PetscCheck(nv >= ndiag, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming Mat and Vec. Vec local size %" PetscInt_FMT " < Mat local diagonal length %" PetscInt_FMT, nv, ndiag); 4936 } 4937 4938 PetscUseTypeMethod(mat, getdiagonal, v); 4939 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4940 PetscFunctionReturn(PETSC_SUCCESS); 4941 } 4942 4943 /*@C 4944 MatGetRowMin - Gets the minimum value (of the real part) of each 4945 row of the matrix 4946 4947 Logically Collective 4948 4949 Input Parameter: 4950 . mat - the matrix 4951 4952 Output Parameters: 4953 + v - the vector for storing the maximums 4954 - idx - the indices of the column found for each row (optional) 4955 4956 Level: intermediate 4957 4958 Note: 4959 The result of this call are the same as if one converted the matrix to dense format 4960 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 4961 4962 This code is only implemented for a couple of matrix formats. 4963 4964 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, 4965 `MatGetRowMax()` 4966 @*/ 4967 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[]) 4968 { 4969 PetscFunctionBegin; 4970 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4971 PetscValidType(mat, 1); 4972 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4973 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4974 4975 if (!mat->cmap->N) { 4976 PetscCall(VecSet(v, PETSC_MAX_REAL)); 4977 if (idx) { 4978 PetscInt i, m = mat->rmap->n; 4979 for (i = 0; i < m; i++) idx[i] = -1; 4980 } 4981 } else { 4982 MatCheckPreallocated(mat, 1); 4983 } 4984 PetscUseTypeMethod(mat, getrowmin, v, idx); 4985 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4986 PetscFunctionReturn(PETSC_SUCCESS); 4987 } 4988 4989 /*@C 4990 MatGetRowMinAbs - Gets the minimum value (in absolute value) of each 4991 row of the matrix 4992 4993 Logically Collective 4994 4995 Input Parameter: 4996 . mat - the matrix 4997 4998 Output Parameters: 4999 + v - the vector for storing the minimums 5000 - idx - the indices of the column found for each row (or `NULL` if not needed) 5001 5002 Level: intermediate 5003 5004 Notes: 5005 if a row is completely empty or has only 0.0 values then the idx[] value for that 5006 row is 0 (the first column). 5007 5008 This code is only implemented for a couple of matrix formats. 5009 5010 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()` 5011 @*/ 5012 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[]) 5013 { 5014 PetscFunctionBegin; 5015 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5016 PetscValidType(mat, 1); 5017 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5018 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5019 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5020 5021 if (!mat->cmap->N) { 5022 PetscCall(VecSet(v, 0.0)); 5023 if (idx) { 5024 PetscInt i, m = mat->rmap->n; 5025 for (i = 0; i < m; i++) idx[i] = -1; 5026 } 5027 } else { 5028 MatCheckPreallocated(mat, 1); 5029 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5030 PetscUseTypeMethod(mat, getrowminabs, v, idx); 5031 } 5032 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5033 PetscFunctionReturn(PETSC_SUCCESS); 5034 } 5035 5036 /*@C 5037 MatGetRowMax - Gets the maximum value (of the real part) of each 5038 row of the matrix 5039 5040 Logically Collective 5041 5042 Input Parameter: 5043 . mat - the matrix 5044 5045 Output Parameters: 5046 + v - the vector for storing the maximums 5047 - idx - the indices of the column found for each row (optional) 5048 5049 Level: intermediate 5050 5051 Notes: 5052 The result of this call are the same as if one converted the matrix to dense format 5053 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5054 5055 This code is only implemented for a couple of matrix formats. 5056 5057 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5058 @*/ 5059 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[]) 5060 { 5061 PetscFunctionBegin; 5062 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5063 PetscValidType(mat, 1); 5064 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5065 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5066 5067 if (!mat->cmap->N) { 5068 PetscCall(VecSet(v, PETSC_MIN_REAL)); 5069 if (idx) { 5070 PetscInt i, m = mat->rmap->n; 5071 for (i = 0; i < m; i++) idx[i] = -1; 5072 } 5073 } else { 5074 MatCheckPreallocated(mat, 1); 5075 PetscUseTypeMethod(mat, getrowmax, v, idx); 5076 } 5077 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5078 PetscFunctionReturn(PETSC_SUCCESS); 5079 } 5080 5081 /*@C 5082 MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each 5083 row of the matrix 5084 5085 Logically Collective 5086 5087 Input Parameter: 5088 . mat - the matrix 5089 5090 Output Parameters: 5091 + v - the vector for storing the maximums 5092 - idx - the indices of the column found for each row (or `NULL` if not needed) 5093 5094 Level: intermediate 5095 5096 Notes: 5097 if a row is completely empty or has only 0.0 values then the idx[] value for that 5098 row is 0 (the first column). 5099 5100 This code is only implemented for a couple of matrix formats. 5101 5102 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5103 @*/ 5104 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[]) 5105 { 5106 PetscFunctionBegin; 5107 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5108 PetscValidType(mat, 1); 5109 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5110 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5111 5112 if (!mat->cmap->N) { 5113 PetscCall(VecSet(v, 0.0)); 5114 if (idx) { 5115 PetscInt i, m = mat->rmap->n; 5116 for (i = 0; i < m; i++) idx[i] = -1; 5117 } 5118 } else { 5119 MatCheckPreallocated(mat, 1); 5120 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5121 PetscUseTypeMethod(mat, getrowmaxabs, v, idx); 5122 } 5123 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5124 PetscFunctionReturn(PETSC_SUCCESS); 5125 } 5126 5127 /*@ 5128 MatGetRowSum - Gets the sum of each row of the matrix 5129 5130 Logically or Neighborhood Collective 5131 5132 Input Parameter: 5133 . mat - the matrix 5134 5135 Output Parameter: 5136 . v - the vector for storing the sum of rows 5137 5138 Level: intermediate 5139 5140 Notes: 5141 This code is slow since it is not currently specialized for different formats 5142 5143 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()` 5144 @*/ 5145 PetscErrorCode MatGetRowSum(Mat mat, Vec v) 5146 { 5147 Vec ones; 5148 5149 PetscFunctionBegin; 5150 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5151 PetscValidType(mat, 1); 5152 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5153 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5154 MatCheckPreallocated(mat, 1); 5155 PetscCall(MatCreateVecs(mat, &ones, NULL)); 5156 PetscCall(VecSet(ones, 1.)); 5157 PetscCall(MatMult(mat, ones, v)); 5158 PetscCall(VecDestroy(&ones)); 5159 PetscFunctionReturn(PETSC_SUCCESS); 5160 } 5161 5162 /*@ 5163 MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) 5164 when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B) 5165 5166 Collective 5167 5168 Input Parameter: 5169 . mat - the matrix to provide the transpose 5170 5171 Output Parameter: 5172 . 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 5173 5174 Level: advanced 5175 5176 Note: 5177 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 5178 routine allows bypassing that call. 5179 5180 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5181 @*/ 5182 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B) 5183 { 5184 PetscContainer rB = NULL; 5185 MatParentState *rb = NULL; 5186 5187 PetscFunctionBegin; 5188 PetscCall(PetscNew(&rb)); 5189 rb->id = ((PetscObject)mat)->id; 5190 rb->state = 0; 5191 PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate)); 5192 PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB)); 5193 PetscCall(PetscContainerSetPointer(rB, rb)); 5194 PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault)); 5195 PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB)); 5196 PetscCall(PetscObjectDereference((PetscObject)rB)); 5197 PetscFunctionReturn(PETSC_SUCCESS); 5198 } 5199 5200 /*@ 5201 MatTranspose - Computes an in-place or out-of-place transpose of a matrix. 5202 5203 Collective 5204 5205 Input Parameters: 5206 + mat - the matrix to transpose 5207 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5208 5209 Output Parameter: 5210 . B - the transpose 5211 5212 Level: intermediate 5213 5214 Notes: 5215 If you use `MAT_INPLACE_MATRIX` then you must pass in &mat for B 5216 5217 `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 5218 transpose, call `MatTransposeSetPrecursor`(mat,B) before calling this routine. 5219 5220 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. 5221 5222 Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed. 5223 5224 If mat is unchanged from the last call this function returns immediately without recomputing the result 5225 5226 If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()` 5227 5228 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`, 5229 `MatTransposeSymbolic()`, `MatCreateTranspose()` 5230 @*/ 5231 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B) 5232 { 5233 PetscContainer rB = NULL; 5234 MatParentState *rb = NULL; 5235 5236 PetscFunctionBegin; 5237 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5238 PetscValidType(mat, 1); 5239 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5240 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5241 PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first"); 5242 PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX"); 5243 MatCheckPreallocated(mat, 1); 5244 if (reuse == MAT_REUSE_MATRIX) { 5245 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5246 PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor()."); 5247 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5248 PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5249 if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS); 5250 } 5251 5252 PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0)); 5253 if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) { 5254 PetscUseTypeMethod(mat, transpose, reuse, B); 5255 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5256 } 5257 PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0)); 5258 5259 if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B)); 5260 if (reuse != MAT_INPLACE_MATRIX) { 5261 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5262 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5263 rb->state = ((PetscObject)mat)->state; 5264 rb->nonzerostate = mat->nonzerostate; 5265 } 5266 PetscFunctionReturn(PETSC_SUCCESS); 5267 } 5268 5269 /*@ 5270 MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix. 5271 5272 Collective 5273 5274 Input Parameter: 5275 . A - the matrix to transpose 5276 5277 Output Parameter: 5278 . 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 5279 numerical portion. 5280 5281 Level: intermediate 5282 5283 Note: 5284 This is not supported for many matrix types, use `MatTranspose()` in those cases 5285 5286 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5287 @*/ 5288 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B) 5289 { 5290 PetscFunctionBegin; 5291 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5292 PetscValidType(A, 1); 5293 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5294 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5295 PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0)); 5296 PetscUseTypeMethod(A, transposesymbolic, B); 5297 PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0)); 5298 5299 PetscCall(MatTransposeSetPrecursor(A, *B)); 5300 PetscFunctionReturn(PETSC_SUCCESS); 5301 } 5302 5303 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B) 5304 { 5305 PetscContainer rB; 5306 MatParentState *rb; 5307 5308 PetscFunctionBegin; 5309 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5310 PetscValidType(A, 1); 5311 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5312 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5313 PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB)); 5314 PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()"); 5315 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5316 PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5317 PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure"); 5318 PetscFunctionReturn(PETSC_SUCCESS); 5319 } 5320 5321 /*@ 5322 MatIsTranspose - Test whether a matrix is another one's transpose, 5323 or its own, in which case it tests symmetry. 5324 5325 Collective 5326 5327 Input Parameters: 5328 + A - the matrix to test 5329 . B - the matrix to test against, this can equal the first parameter 5330 - tol - tolerance, differences between entries smaller than this are counted as zero 5331 5332 Output Parameter: 5333 . flg - the result 5334 5335 Level: intermediate 5336 5337 Notes: 5338 Only available for `MATAIJ` matrices. 5339 5340 The sequential algorithm has a running time of the order of the number of nonzeros; the parallel 5341 test involves parallel copies of the block-offdiagonal parts of the matrix. 5342 5343 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()` 5344 @*/ 5345 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5346 { 5347 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5348 5349 PetscFunctionBegin; 5350 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5351 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5352 PetscValidBoolPointer(flg, 4); 5353 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f)); 5354 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g)); 5355 *flg = PETSC_FALSE; 5356 if (f && g) { 5357 PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test"); 5358 PetscCall((*f)(A, B, tol, flg)); 5359 } else { 5360 MatType mattype; 5361 5362 PetscCall(MatGetType(f ? B : A, &mattype)); 5363 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype); 5364 } 5365 PetscFunctionReturn(PETSC_SUCCESS); 5366 } 5367 5368 /*@ 5369 MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate. 5370 5371 Collective 5372 5373 Input Parameters: 5374 + mat - the matrix to transpose and complex conjugate 5375 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5376 5377 Output Parameter: 5378 . B - the Hermitian transpose 5379 5380 Level: intermediate 5381 5382 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse` 5383 @*/ 5384 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B) 5385 { 5386 PetscFunctionBegin; 5387 PetscCall(MatTranspose(mat, reuse, B)); 5388 #if defined(PETSC_USE_COMPLEX) 5389 PetscCall(MatConjugate(*B)); 5390 #endif 5391 PetscFunctionReturn(PETSC_SUCCESS); 5392 } 5393 5394 /*@ 5395 MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose, 5396 5397 Collective 5398 5399 Input Parameters: 5400 + A - the matrix to test 5401 . B - the matrix to test against, this can equal the first parameter 5402 - tol - tolerance, differences between entries smaller than this are counted as zero 5403 5404 Output Parameter: 5405 . flg - the result 5406 5407 Level: intermediate 5408 5409 Notes: 5410 Only available for `MATAIJ` matrices. 5411 5412 The sequential algorithm 5413 has a running time of the order of the number of nonzeros; the parallel 5414 test involves parallel copies of the block-offdiagonal parts of the matrix. 5415 5416 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()` 5417 @*/ 5418 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5419 { 5420 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5421 5422 PetscFunctionBegin; 5423 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5424 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5425 PetscValidBoolPointer(flg, 4); 5426 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f)); 5427 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g)); 5428 if (f && g) { 5429 PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test"); 5430 PetscCall((*f)(A, B, tol, flg)); 5431 } 5432 PetscFunctionReturn(PETSC_SUCCESS); 5433 } 5434 5435 /*@ 5436 MatPermute - Creates a new matrix with rows and columns permuted from the 5437 original. 5438 5439 Collective 5440 5441 Input Parameters: 5442 + mat - the matrix to permute 5443 . row - row permutation, each processor supplies only the permutation for its rows 5444 - col - column permutation, each processor supplies only the permutation for its columns 5445 5446 Output Parameter: 5447 . B - the permuted matrix 5448 5449 Level: advanced 5450 5451 Note: 5452 The index sets map from row/col of permuted matrix to row/col of original matrix. 5453 The index sets should be on the same communicator as mat and have the same local sizes. 5454 5455 Developer Notes: 5456 If you want to implement `MatPermute()` for a matrix type, and your approach doesn't 5457 exploit the fact that row and col are permutations, consider implementing the 5458 more general `MatCreateSubMatrix()` instead. 5459 5460 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()` 5461 @*/ 5462 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B) 5463 { 5464 PetscFunctionBegin; 5465 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5466 PetscValidType(mat, 1); 5467 PetscValidHeaderSpecific(row, IS_CLASSID, 2); 5468 PetscValidHeaderSpecific(col, IS_CLASSID, 3); 5469 PetscValidPointer(B, 4); 5470 PetscCheckSameComm(mat, 1, row, 2); 5471 if (row != col) PetscCheckSameComm(row, 2, col, 3); 5472 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5473 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5474 PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name); 5475 MatCheckPreallocated(mat, 1); 5476 5477 if (mat->ops->permute) { 5478 PetscUseTypeMethod(mat, permute, row, col, B); 5479 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5480 } else { 5481 PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B)); 5482 } 5483 PetscFunctionReturn(PETSC_SUCCESS); 5484 } 5485 5486 /*@ 5487 MatEqual - Compares two matrices. 5488 5489 Collective 5490 5491 Input Parameters: 5492 + A - the first matrix 5493 - B - the second matrix 5494 5495 Output Parameter: 5496 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise. 5497 5498 Level: intermediate 5499 5500 .seealso: [](ch_matrices), `Mat` 5501 @*/ 5502 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg) 5503 { 5504 PetscFunctionBegin; 5505 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5506 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5507 PetscValidType(A, 1); 5508 PetscValidType(B, 2); 5509 PetscValidBoolPointer(flg, 3); 5510 PetscCheckSameComm(A, 1, B, 2); 5511 MatCheckPreallocated(A, 1); 5512 MatCheckPreallocated(B, 2); 5513 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5514 PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5515 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, 5516 B->cmap->N); 5517 if (A->ops->equal && A->ops->equal == B->ops->equal) { 5518 PetscUseTypeMethod(A, equal, B, flg); 5519 } else { 5520 PetscCall(MatMultEqual(A, B, 10, flg)); 5521 } 5522 PetscFunctionReturn(PETSC_SUCCESS); 5523 } 5524 5525 /*@ 5526 MatDiagonalScale - Scales a matrix on the left and right by diagonal 5527 matrices that are stored as vectors. Either of the two scaling 5528 matrices can be `NULL`. 5529 5530 Collective 5531 5532 Input Parameters: 5533 + mat - the matrix to be scaled 5534 . l - the left scaling vector (or `NULL`) 5535 - r - the right scaling vector (or `NULL`) 5536 5537 Level: intermediate 5538 5539 Note: 5540 `MatDiagonalScale()` computes A = LAR, where 5541 L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector) 5542 The L scales the rows of the matrix, the R scales the columns of the matrix. 5543 5544 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()` 5545 @*/ 5546 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r) 5547 { 5548 PetscFunctionBegin; 5549 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5550 PetscValidType(mat, 1); 5551 if (l) { 5552 PetscValidHeaderSpecific(l, VEC_CLASSID, 2); 5553 PetscCheckSameComm(mat, 1, l, 2); 5554 } 5555 if (r) { 5556 PetscValidHeaderSpecific(r, VEC_CLASSID, 3); 5557 PetscCheckSameComm(mat, 1, r, 3); 5558 } 5559 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5560 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5561 MatCheckPreallocated(mat, 1); 5562 if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS); 5563 5564 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5565 PetscUseTypeMethod(mat, diagonalscale, l, r); 5566 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5567 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5568 if (l != r) mat->symmetric = PETSC_BOOL3_FALSE; 5569 PetscFunctionReturn(PETSC_SUCCESS); 5570 } 5571 5572 /*@ 5573 MatScale - Scales all elements of a matrix by a given number. 5574 5575 Logically Collective 5576 5577 Input Parameters: 5578 + mat - the matrix to be scaled 5579 - a - the scaling value 5580 5581 Level: intermediate 5582 5583 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 5584 @*/ 5585 PetscErrorCode MatScale(Mat mat, PetscScalar a) 5586 { 5587 PetscFunctionBegin; 5588 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5589 PetscValidType(mat, 1); 5590 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5591 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5592 PetscValidLogicalCollectiveScalar(mat, a, 2); 5593 MatCheckPreallocated(mat, 1); 5594 5595 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5596 if (a != (PetscScalar)1.0) { 5597 PetscUseTypeMethod(mat, scale, a); 5598 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5599 } 5600 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5601 PetscFunctionReturn(PETSC_SUCCESS); 5602 } 5603 5604 /*@ 5605 MatNorm - Calculates various norms of a matrix. 5606 5607 Collective 5608 5609 Input Parameters: 5610 + mat - the matrix 5611 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY` 5612 5613 Output Parameter: 5614 . nrm - the resulting norm 5615 5616 Level: intermediate 5617 5618 .seealso: [](ch_matrices), `Mat` 5619 @*/ 5620 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm) 5621 { 5622 PetscFunctionBegin; 5623 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5624 PetscValidType(mat, 1); 5625 PetscValidRealPointer(nrm, 3); 5626 5627 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5628 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5629 MatCheckPreallocated(mat, 1); 5630 5631 PetscUseTypeMethod(mat, norm, type, nrm); 5632 PetscFunctionReturn(PETSC_SUCCESS); 5633 } 5634 5635 /* 5636 This variable is used to prevent counting of MatAssemblyBegin() that 5637 are called from within a MatAssemblyEnd(). 5638 */ 5639 static PetscInt MatAssemblyEnd_InUse = 0; 5640 /*@ 5641 MatAssemblyBegin - Begins assembling the matrix. This routine should 5642 be called after completing all calls to `MatSetValues()`. 5643 5644 Collective 5645 5646 Input Parameters: 5647 + mat - the matrix 5648 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5649 5650 Level: beginner 5651 5652 Notes: 5653 `MatSetValues()` generally caches the values that belong to other MPI processes. The matrix is ready to 5654 use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called. 5655 5656 Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES` 5657 in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before 5658 using the matrix. 5659 5660 ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the 5661 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 5662 a global collective operation requiring all processes that share the matrix. 5663 5664 Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed 5665 out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros 5666 before `MAT_FINAL_ASSEMBLY` so the space is not compressed out. 5667 5668 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()` 5669 @*/ 5670 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type) 5671 { 5672 PetscFunctionBegin; 5673 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5674 PetscValidType(mat, 1); 5675 MatCheckPreallocated(mat, 1); 5676 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?"); 5677 if (mat->assembled) { 5678 mat->was_assembled = PETSC_TRUE; 5679 mat->assembled = PETSC_FALSE; 5680 } 5681 5682 if (!MatAssemblyEnd_InUse) { 5683 PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0)); 5684 PetscTryTypeMethod(mat, assemblybegin, type); 5685 PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0)); 5686 } else PetscTryTypeMethod(mat, assemblybegin, type); 5687 PetscFunctionReturn(PETSC_SUCCESS); 5688 } 5689 5690 /*@ 5691 MatAssembled - Indicates if a matrix has been assembled and is ready for 5692 use; for example, in matrix-vector product. 5693 5694 Not Collective 5695 5696 Input Parameter: 5697 . mat - the matrix 5698 5699 Output Parameter: 5700 . assembled - `PETSC_TRUE` or `PETSC_FALSE` 5701 5702 Level: advanced 5703 5704 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()` 5705 @*/ 5706 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled) 5707 { 5708 PetscFunctionBegin; 5709 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5710 PetscValidBoolPointer(assembled, 2); 5711 *assembled = mat->assembled; 5712 PetscFunctionReturn(PETSC_SUCCESS); 5713 } 5714 5715 /*@ 5716 MatAssemblyEnd - Completes assembling the matrix. This routine should 5717 be called after `MatAssemblyBegin()`. 5718 5719 Collective 5720 5721 Input Parameters: 5722 + mat - the matrix 5723 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5724 5725 Options Database Keys: 5726 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 5727 . -mat_view ::ascii_info_detail - Prints more detailed info 5728 . -mat_view - Prints matrix in ASCII format 5729 . -mat_view ::ascii_matlab - Prints matrix in Matlab format 5730 . -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 5731 . -display <name> - Sets display name (default is host) 5732 . -draw_pause <sec> - Sets number of seconds to pause after display 5733 . -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See [Using MATLAB with PETSc](ch_matlab)) 5734 . -viewer_socket_machine <machine> - Machine to use for socket 5735 . -viewer_socket_port <port> - Port number to use for socket 5736 - -mat_view binary:filename[:append] - Save matrix to file in binary format 5737 5738 Level: beginner 5739 5740 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()` 5741 @*/ 5742 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type) 5743 { 5744 static PetscInt inassm = 0; 5745 PetscBool flg = PETSC_FALSE; 5746 5747 PetscFunctionBegin; 5748 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5749 PetscValidType(mat, 1); 5750 5751 inassm++; 5752 MatAssemblyEnd_InUse++; 5753 if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */ 5754 PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0)); 5755 PetscTryTypeMethod(mat, assemblyend, type); 5756 PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0)); 5757 } else PetscTryTypeMethod(mat, assemblyend, type); 5758 5759 /* Flush assembly is not a true assembly */ 5760 if (type != MAT_FLUSH_ASSEMBLY) { 5761 if (mat->num_ass) { 5762 if (!mat->symmetry_eternal) { 5763 mat->symmetric = PETSC_BOOL3_UNKNOWN; 5764 mat->hermitian = PETSC_BOOL3_UNKNOWN; 5765 } 5766 if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN; 5767 if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN; 5768 } 5769 mat->num_ass++; 5770 mat->assembled = PETSC_TRUE; 5771 mat->ass_nonzerostate = mat->nonzerostate; 5772 } 5773 5774 mat->insertmode = NOT_SET_VALUES; 5775 MatAssemblyEnd_InUse--; 5776 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5777 if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) { 5778 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 5779 5780 if (mat->checksymmetryonassembly) { 5781 PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg)); 5782 if (flg) { 5783 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5784 } else { 5785 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5786 } 5787 } 5788 if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL)); 5789 } 5790 inassm--; 5791 PetscFunctionReturn(PETSC_SUCCESS); 5792 } 5793 5794 /*@ 5795 MatSetOption - Sets a parameter option for a matrix. Some options 5796 may be specific to certain storage formats. Some options 5797 determine how values will be inserted (or added). Sorted, 5798 row-oriented input will generally assemble the fastest. The default 5799 is row-oriented. 5800 5801 Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption` 5802 5803 Input Parameters: 5804 + mat - the matrix 5805 . op - the option, one of those listed below (and possibly others), 5806 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5807 5808 Options Describing Matrix Structure: 5809 + `MAT_SPD` - symmetric positive definite 5810 . `MAT_SYMMETRIC` - symmetric in terms of both structure and value 5811 . `MAT_HERMITIAN` - transpose is the complex conjugation 5812 . `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure 5813 . `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix 5814 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix 5815 . `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix 5816 5817 These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they 5818 do not need to be computed (usually at a high cost) 5819 5820 Options For Use with `MatSetValues()`: 5821 Insert a logically dense subblock, which can be 5822 . `MAT_ROW_ORIENTED` - row-oriented (default) 5823 5824 These options reflect the data you pass in with `MatSetValues()`; it has 5825 nothing to do with how the data is stored internally in the matrix 5826 data structure. 5827 5828 When (re)assembling a matrix, we can restrict the input for 5829 efficiency/debugging purposes. These options include 5830 . `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow) 5831 . `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated 5832 . `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries 5833 . `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry 5834 . `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly 5835 . `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if 5836 any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves 5837 performance for very large process counts. 5838 - `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset 5839 of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly 5840 functions, instead sending only neighbor messages. 5841 5842 Level: intermediate 5843 5844 Notes: 5845 Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg! 5846 5847 Some options are relevant only for particular matrix types and 5848 are thus ignored by others. Other options are not supported by 5849 certain matrix types and will generate an error message if set. 5850 5851 If using Fortran to compute a matrix, one may need to 5852 use the column-oriented option (or convert to the row-oriented 5853 format). 5854 5855 `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion 5856 that would generate a new entry in the nonzero structure is instead 5857 ignored. Thus, if memory has not already been allocated for this particular 5858 data, then the insertion is ignored. For dense matrices, in which 5859 the entire array is allocated, no entries are ever ignored. 5860 Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction 5861 5862 `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion 5863 that would generate a new entry in the nonzero structure instead produces 5864 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 5865 5866 `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion 5867 that would generate a new entry that has not been preallocated will 5868 instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats 5869 only.) This is a useful flag when debugging matrix memory preallocation. 5870 If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 5871 5872 `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for 5873 other processors should be dropped, rather than stashed. 5874 This is useful if you know that the "owning" processor is also 5875 always generating the correct matrix entries, so that PETSc need 5876 not transfer duplicate entries generated on another processor. 5877 5878 `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the 5879 searches during matrix assembly. When this flag is set, the hash table 5880 is created during the first matrix assembly. This hash table is 5881 used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()` 5882 to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag 5883 should be used with `MAT_USE_HASH_TABLE` flag. This option is currently 5884 supported by `MATMPIBAIJ` format only. 5885 5886 `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries 5887 are kept in the nonzero structure 5888 5889 `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating 5890 a zero location in the matrix 5891 5892 `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types 5893 5894 `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the 5895 zero row routines and thus improves performance for very large process counts. 5896 5897 `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular 5898 part of the matrix (since they should match the upper triangular part). 5899 5900 `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a 5901 single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common 5902 with finite difference schemes with non-periodic boundary conditions. 5903 5904 Developer Notes: 5905 `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other 5906 places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRIC` or `MAT_SPD` would need to be changed back 5907 to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had 5908 not changed. 5909 5910 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()` 5911 @*/ 5912 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg) 5913 { 5914 PetscFunctionBegin; 5915 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5916 if (op > 0) { 5917 PetscValidLogicalCollectiveEnum(mat, op, 2); 5918 PetscValidLogicalCollectiveBool(mat, flg, 3); 5919 } 5920 5921 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); 5922 5923 switch (op) { 5924 case MAT_FORCE_DIAGONAL_ENTRIES: 5925 mat->force_diagonals = flg; 5926 PetscFunctionReturn(PETSC_SUCCESS); 5927 case MAT_NO_OFF_PROC_ENTRIES: 5928 mat->nooffprocentries = flg; 5929 PetscFunctionReturn(PETSC_SUCCESS); 5930 case MAT_SUBSET_OFF_PROC_ENTRIES: 5931 mat->assembly_subset = flg; 5932 if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */ 5933 #if !defined(PETSC_HAVE_MPIUNI) 5934 PetscCall(MatStashScatterDestroy_BTS(&mat->stash)); 5935 #endif 5936 mat->stash.first_assembly_done = PETSC_FALSE; 5937 } 5938 PetscFunctionReturn(PETSC_SUCCESS); 5939 case MAT_NO_OFF_PROC_ZERO_ROWS: 5940 mat->nooffproczerorows = flg; 5941 PetscFunctionReturn(PETSC_SUCCESS); 5942 case MAT_SPD: 5943 if (flg) { 5944 mat->spd = PETSC_BOOL3_TRUE; 5945 mat->symmetric = PETSC_BOOL3_TRUE; 5946 mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5947 } else { 5948 mat->spd = PETSC_BOOL3_FALSE; 5949 } 5950 break; 5951 case MAT_SYMMETRIC: 5952 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5953 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5954 #if !defined(PETSC_USE_COMPLEX) 5955 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5956 #endif 5957 break; 5958 case MAT_HERMITIAN: 5959 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5960 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5961 #if !defined(PETSC_USE_COMPLEX) 5962 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5963 #endif 5964 break; 5965 case MAT_STRUCTURALLY_SYMMETRIC: 5966 mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5967 break; 5968 case MAT_SYMMETRY_ETERNAL: 5969 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"); 5970 mat->symmetry_eternal = flg; 5971 if (flg) mat->structural_symmetry_eternal = PETSC_TRUE; 5972 break; 5973 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 5974 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"); 5975 mat->structural_symmetry_eternal = flg; 5976 break; 5977 case MAT_SPD_ETERNAL: 5978 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"); 5979 mat->spd_eternal = flg; 5980 if (flg) { 5981 mat->structural_symmetry_eternal = PETSC_TRUE; 5982 mat->symmetry_eternal = PETSC_TRUE; 5983 } 5984 break; 5985 case MAT_STRUCTURE_ONLY: 5986 mat->structure_only = flg; 5987 break; 5988 case MAT_SORTED_FULL: 5989 mat->sortedfull = flg; 5990 break; 5991 default: 5992 break; 5993 } 5994 PetscTryTypeMethod(mat, setoption, op, flg); 5995 PetscFunctionReturn(PETSC_SUCCESS); 5996 } 5997 5998 /*@ 5999 MatGetOption - Gets a parameter option that has been set for a matrix. 6000 6001 Logically Collective 6002 6003 Input Parameters: 6004 + mat - the matrix 6005 - op - the option, this only responds to certain options, check the code for which ones 6006 6007 Output Parameter: 6008 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 6009 6010 Level: intermediate 6011 6012 Notes: 6013 Can only be called after `MatSetSizes()` and `MatSetType()` have been set. 6014 6015 Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or 6016 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6017 6018 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, 6019 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6020 @*/ 6021 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg) 6022 { 6023 PetscFunctionBegin; 6024 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6025 PetscValidType(mat, 1); 6026 6027 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); 6028 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()"); 6029 6030 switch (op) { 6031 case MAT_NO_OFF_PROC_ENTRIES: 6032 *flg = mat->nooffprocentries; 6033 break; 6034 case MAT_NO_OFF_PROC_ZERO_ROWS: 6035 *flg = mat->nooffproczerorows; 6036 break; 6037 case MAT_SYMMETRIC: 6038 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()"); 6039 break; 6040 case MAT_HERMITIAN: 6041 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()"); 6042 break; 6043 case MAT_STRUCTURALLY_SYMMETRIC: 6044 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()"); 6045 break; 6046 case MAT_SPD: 6047 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()"); 6048 break; 6049 case MAT_SYMMETRY_ETERNAL: 6050 *flg = mat->symmetry_eternal; 6051 break; 6052 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6053 *flg = mat->symmetry_eternal; 6054 break; 6055 default: 6056 break; 6057 } 6058 PetscFunctionReturn(PETSC_SUCCESS); 6059 } 6060 6061 /*@ 6062 MatZeroEntries - Zeros all entries of a matrix. For sparse matrices 6063 this routine retains the old nonzero structure. 6064 6065 Logically Collective 6066 6067 Input Parameter: 6068 . mat - the matrix 6069 6070 Level: intermediate 6071 6072 Note: 6073 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. 6074 See the Performance chapter of the users manual for information on preallocating matrices. 6075 6076 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()` 6077 @*/ 6078 PetscErrorCode MatZeroEntries(Mat mat) 6079 { 6080 PetscFunctionBegin; 6081 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6082 PetscValidType(mat, 1); 6083 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6084 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"); 6085 MatCheckPreallocated(mat, 1); 6086 6087 PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0)); 6088 PetscUseTypeMethod(mat, zeroentries); 6089 PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0)); 6090 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6091 PetscFunctionReturn(PETSC_SUCCESS); 6092 } 6093 6094 /*@ 6095 MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal) 6096 of a set of rows and columns of a matrix. 6097 6098 Collective 6099 6100 Input Parameters: 6101 + mat - the matrix 6102 . numRows - the number of rows/columns to zero 6103 . rows - the global row indices 6104 . diag - value put in the diagonal of the eliminated rows 6105 . x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call 6106 - b - optional vector of the right hand side, that will be adjusted by provided solution entries 6107 6108 Level: intermediate 6109 6110 Notes: 6111 This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6112 6113 For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`. 6114 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 6115 6116 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6117 Krylov method to take advantage of the known solution on the zeroed rows. 6118 6119 For the parallel case, all processes that share the matrix (i.e., 6120 those in the communicator used for matrix creation) MUST call this 6121 routine, regardless of whether any rows being zeroed are owned by 6122 them. 6123 6124 Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix. 6125 6126 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6127 list only rows local to itself). 6128 6129 The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine. 6130 6131 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6132 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6133 @*/ 6134 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6135 { 6136 PetscFunctionBegin; 6137 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6138 PetscValidType(mat, 1); 6139 if (numRows) PetscValidIntPointer(rows, 3); 6140 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6141 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6142 MatCheckPreallocated(mat, 1); 6143 6144 PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b); 6145 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6146 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6147 PetscFunctionReturn(PETSC_SUCCESS); 6148 } 6149 6150 /*@ 6151 MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal) 6152 of a set of rows and columns of a matrix. 6153 6154 Collective 6155 6156 Input Parameters: 6157 + mat - the matrix 6158 . is - the rows to zero 6159 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6160 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6161 - b - optional vector of right hand side, that will be adjusted by provided solution 6162 6163 Level: intermediate 6164 6165 Note: 6166 See `MatZeroRowsColumns()` for details on how this routine operates. 6167 6168 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6169 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()` 6170 @*/ 6171 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6172 { 6173 PetscInt numRows; 6174 const PetscInt *rows; 6175 6176 PetscFunctionBegin; 6177 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6178 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6179 PetscValidType(mat, 1); 6180 PetscValidType(is, 2); 6181 PetscCall(ISGetLocalSize(is, &numRows)); 6182 PetscCall(ISGetIndices(is, &rows)); 6183 PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b)); 6184 PetscCall(ISRestoreIndices(is, &rows)); 6185 PetscFunctionReturn(PETSC_SUCCESS); 6186 } 6187 6188 /*@ 6189 MatZeroRows - Zeros all entries (except possibly the main diagonal) 6190 of a set of rows of a matrix. 6191 6192 Collective 6193 6194 Input Parameters: 6195 + mat - the matrix 6196 . numRows - the number of rows to zero 6197 . rows - the global row indices 6198 . diag - value put in the diagonal of the zeroed rows 6199 . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call 6200 - b - optional vector of right hand side, that will be adjusted by provided solution entries 6201 6202 Level: intermediate 6203 6204 Notes: 6205 This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6206 6207 For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`. 6208 6209 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6210 Krylov method to take advantage of the known solution on the zeroed rows. 6211 6212 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) 6213 from the matrix. 6214 6215 Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix 6216 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 6217 formats this does not alter the nonzero structure. 6218 6219 If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure 6220 of the matrix is not changed the values are 6221 merely zeroed. 6222 6223 The user can set a value in the diagonal entry (or for the `MATAIJ` format 6224 formats can optionally remove the main diagonal entry from the 6225 nonzero structure as well, by passing 0.0 as the final argument). 6226 6227 For the parallel case, all processes that share the matrix (i.e., 6228 those in the communicator used for matrix creation) MUST call this 6229 routine, regardless of whether any rows being zeroed are owned by 6230 them. 6231 6232 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6233 list only rows local to itself). 6234 6235 You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it 6236 owns that are to be zeroed. This saves a global synchronization in the implementation. 6237 6238 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6239 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE` 6240 @*/ 6241 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6242 { 6243 PetscFunctionBegin; 6244 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6245 PetscValidType(mat, 1); 6246 if (numRows) PetscValidIntPointer(rows, 3); 6247 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6248 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6249 MatCheckPreallocated(mat, 1); 6250 6251 PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b); 6252 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6253 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6254 PetscFunctionReturn(PETSC_SUCCESS); 6255 } 6256 6257 /*@ 6258 MatZeroRowsIS - Zeros all entries (except possibly the main diagonal) 6259 of a set of rows of a matrix. 6260 6261 Collective 6262 6263 Input Parameters: 6264 + mat - the matrix 6265 . is - index set of rows to remove (if `NULL` then no row is removed) 6266 . diag - value put in all diagonals of eliminated rows 6267 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6268 - b - optional vector of right hand side, that will be adjusted by provided solution 6269 6270 Level: intermediate 6271 6272 Note: 6273 See `MatZeroRows()` for details on how this routine operates. 6274 6275 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6276 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6277 @*/ 6278 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6279 { 6280 PetscInt numRows = 0; 6281 const PetscInt *rows = NULL; 6282 6283 PetscFunctionBegin; 6284 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6285 PetscValidType(mat, 1); 6286 if (is) { 6287 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6288 PetscCall(ISGetLocalSize(is, &numRows)); 6289 PetscCall(ISGetIndices(is, &rows)); 6290 } 6291 PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b)); 6292 if (is) PetscCall(ISRestoreIndices(is, &rows)); 6293 PetscFunctionReturn(PETSC_SUCCESS); 6294 } 6295 6296 /*@ 6297 MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal) 6298 of a set of rows of a matrix. These rows must be local to the process. 6299 6300 Collective 6301 6302 Input Parameters: 6303 + mat - the matrix 6304 . numRows - the number of rows to remove 6305 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6306 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6307 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6308 - b - optional vector of right hand side, that will be adjusted by provided solution 6309 6310 Level: intermediate 6311 6312 Notes: 6313 See `MatZeroRows()` for details on how this routine operates. 6314 6315 The grid coordinates are across the entire grid, not just the local portion 6316 6317 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6318 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6319 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6320 `DM_BOUNDARY_PERIODIC` boundary type. 6321 6322 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 6323 a single value per point) you can skip filling those indices. 6324 6325 Fortran Notes: 6326 `idxm` and `idxn` should be declared as 6327 $ MatStencil idxm(4, m) 6328 and the values inserted using 6329 .vb 6330 idxm(MatStencil_i, 1) = i 6331 idxm(MatStencil_j, 1) = j 6332 idxm(MatStencil_k, 1) = k 6333 idxm(MatStencil_c, 1) = c 6334 etc 6335 .ve 6336 6337 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6338 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6339 @*/ 6340 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6341 { 6342 PetscInt dim = mat->stencil.dim; 6343 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6344 PetscInt *dims = mat->stencil.dims + 1; 6345 PetscInt *starts = mat->stencil.starts; 6346 PetscInt *dxm = (PetscInt *)rows; 6347 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6348 6349 PetscFunctionBegin; 6350 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6351 PetscValidType(mat, 1); 6352 if (numRows) PetscValidPointer(rows, 3); 6353 6354 PetscCall(PetscMalloc1(numRows, &jdxm)); 6355 for (i = 0; i < numRows; ++i) { 6356 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6357 for (j = 0; j < 3 - sdim; ++j) dxm++; 6358 /* Local index in X dir */ 6359 tmp = *dxm++ - starts[0]; 6360 /* Loop over remaining dimensions */ 6361 for (j = 0; j < dim - 1; ++j) { 6362 /* If nonlocal, set index to be negative */ 6363 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6364 /* Update local index */ 6365 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6366 } 6367 /* Skip component slot if necessary */ 6368 if (mat->stencil.noc) dxm++; 6369 /* Local row number */ 6370 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6371 } 6372 PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b)); 6373 PetscCall(PetscFree(jdxm)); 6374 PetscFunctionReturn(PETSC_SUCCESS); 6375 } 6376 6377 /*@ 6378 MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal) 6379 of a set of rows and columns of a matrix. 6380 6381 Collective 6382 6383 Input Parameters: 6384 + mat - the matrix 6385 . numRows - the number of rows/columns to remove 6386 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6387 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6388 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6389 - b - optional vector of right hand side, that will be adjusted by provided solution 6390 6391 Level: intermediate 6392 6393 Notes: 6394 See `MatZeroRowsColumns()` for details on how this routine operates. 6395 6396 The grid coordinates are across the entire grid, not just the local portion 6397 6398 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6399 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6400 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6401 `DM_BOUNDARY_PERIODIC` boundary type. 6402 6403 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 6404 a single value per point) you can skip filling those indices. 6405 6406 Fortran Notes: 6407 `idxm` and `idxn` should be declared as 6408 $ MatStencil idxm(4, m) 6409 and the values inserted using 6410 .vb 6411 idxm(MatStencil_i, 1) = i 6412 idxm(MatStencil_j, 1) = j 6413 idxm(MatStencil_k, 1) = k 6414 idxm(MatStencil_c, 1) = c 6415 etc 6416 .ve 6417 6418 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6419 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()` 6420 @*/ 6421 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6422 { 6423 PetscInt dim = mat->stencil.dim; 6424 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6425 PetscInt *dims = mat->stencil.dims + 1; 6426 PetscInt *starts = mat->stencil.starts; 6427 PetscInt *dxm = (PetscInt *)rows; 6428 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6429 6430 PetscFunctionBegin; 6431 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6432 PetscValidType(mat, 1); 6433 if (numRows) PetscValidPointer(rows, 3); 6434 6435 PetscCall(PetscMalloc1(numRows, &jdxm)); 6436 for (i = 0; i < numRows; ++i) { 6437 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6438 for (j = 0; j < 3 - sdim; ++j) dxm++; 6439 /* Local index in X dir */ 6440 tmp = *dxm++ - starts[0]; 6441 /* Loop over remaining dimensions */ 6442 for (j = 0; j < dim - 1; ++j) { 6443 /* If nonlocal, set index to be negative */ 6444 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6445 /* Update local index */ 6446 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6447 } 6448 /* Skip component slot if necessary */ 6449 if (mat->stencil.noc) dxm++; 6450 /* Local row number */ 6451 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6452 } 6453 PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b)); 6454 PetscCall(PetscFree(jdxm)); 6455 PetscFunctionReturn(PETSC_SUCCESS); 6456 } 6457 6458 /*@C 6459 MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal) 6460 of a set of rows of a matrix; using local numbering of rows. 6461 6462 Collective 6463 6464 Input Parameters: 6465 + mat - the matrix 6466 . numRows - the number of rows to remove 6467 . rows - the local row indices 6468 . diag - value put in all diagonals of eliminated rows 6469 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6470 - b - optional vector of right hand side, that will be adjusted by provided solution 6471 6472 Level: intermediate 6473 6474 Notes: 6475 Before calling `MatZeroRowsLocal()`, the user must first set the 6476 local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`. 6477 6478 See `MatZeroRows()` for details on how this routine operates. 6479 6480 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`, 6481 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6482 @*/ 6483 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6484 { 6485 PetscFunctionBegin; 6486 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6487 PetscValidType(mat, 1); 6488 if (numRows) PetscValidIntPointer(rows, 3); 6489 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6490 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6491 MatCheckPreallocated(mat, 1); 6492 6493 if (mat->ops->zerorowslocal) { 6494 PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b); 6495 } else { 6496 IS is, newis; 6497 const PetscInt *newRows; 6498 6499 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6500 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6501 PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis)); 6502 PetscCall(ISGetIndices(newis, &newRows)); 6503 PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b); 6504 PetscCall(ISRestoreIndices(newis, &newRows)); 6505 PetscCall(ISDestroy(&newis)); 6506 PetscCall(ISDestroy(&is)); 6507 } 6508 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6509 PetscFunctionReturn(PETSC_SUCCESS); 6510 } 6511 6512 /*@ 6513 MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal) 6514 of a set of rows of a matrix; using local numbering of rows. 6515 6516 Collective 6517 6518 Input Parameters: 6519 + mat - the matrix 6520 . is - index set of rows to remove 6521 . diag - value put in all diagonals of eliminated rows 6522 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6523 - b - optional vector of right hand side, that will be adjusted by provided solution 6524 6525 Level: intermediate 6526 6527 Notes: 6528 Before calling `MatZeroRowsLocalIS()`, the user must first set the 6529 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6530 6531 See `MatZeroRows()` for details on how this routine operates. 6532 6533 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6534 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6535 @*/ 6536 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6537 { 6538 PetscInt numRows; 6539 const PetscInt *rows; 6540 6541 PetscFunctionBegin; 6542 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6543 PetscValidType(mat, 1); 6544 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6545 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6546 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6547 MatCheckPreallocated(mat, 1); 6548 6549 PetscCall(ISGetLocalSize(is, &numRows)); 6550 PetscCall(ISGetIndices(is, &rows)); 6551 PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b)); 6552 PetscCall(ISRestoreIndices(is, &rows)); 6553 PetscFunctionReturn(PETSC_SUCCESS); 6554 } 6555 6556 /*@ 6557 MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal) 6558 of a set of rows and columns of a matrix; using local numbering of rows. 6559 6560 Collective 6561 6562 Input Parameters: 6563 + mat - the matrix 6564 . numRows - the number of rows to remove 6565 . rows - the global row indices 6566 . diag - value put in all diagonals of eliminated rows 6567 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6568 - b - optional vector of right hand side, that will be adjusted by provided solution 6569 6570 Level: intermediate 6571 6572 Notes: 6573 Before calling `MatZeroRowsColumnsLocal()`, the user must first set the 6574 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6575 6576 See `MatZeroRowsColumns()` for details on how this routine operates. 6577 6578 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6579 `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6580 @*/ 6581 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6582 { 6583 IS is, newis; 6584 const PetscInt *newRows; 6585 6586 PetscFunctionBegin; 6587 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6588 PetscValidType(mat, 1); 6589 if (numRows) PetscValidIntPointer(rows, 3); 6590 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6591 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6592 MatCheckPreallocated(mat, 1); 6593 6594 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6595 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6596 PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis)); 6597 PetscCall(ISGetIndices(newis, &newRows)); 6598 PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b); 6599 PetscCall(ISRestoreIndices(newis, &newRows)); 6600 PetscCall(ISDestroy(&newis)); 6601 PetscCall(ISDestroy(&is)); 6602 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6603 PetscFunctionReturn(PETSC_SUCCESS); 6604 } 6605 6606 /*@ 6607 MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal) 6608 of a set of rows and columns of a matrix; using local numbering of rows. 6609 6610 Collective 6611 6612 Input Parameters: 6613 + mat - the matrix 6614 . is - index set of rows to remove 6615 . diag - value put in all diagonals of eliminated rows 6616 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6617 - b - optional vector of right hand side, that will be adjusted by provided solution 6618 6619 Level: intermediate 6620 6621 Notes: 6622 Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the 6623 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6624 6625 See `MatZeroRowsColumns()` for details on how this routine operates. 6626 6627 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6628 `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6629 @*/ 6630 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6631 { 6632 PetscInt numRows; 6633 const PetscInt *rows; 6634 6635 PetscFunctionBegin; 6636 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6637 PetscValidType(mat, 1); 6638 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6639 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6640 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6641 MatCheckPreallocated(mat, 1); 6642 6643 PetscCall(ISGetLocalSize(is, &numRows)); 6644 PetscCall(ISGetIndices(is, &rows)); 6645 PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b)); 6646 PetscCall(ISRestoreIndices(is, &rows)); 6647 PetscFunctionReturn(PETSC_SUCCESS); 6648 } 6649 6650 /*@C 6651 MatGetSize - Returns the numbers of rows and columns in a matrix. 6652 6653 Not Collective 6654 6655 Input Parameter: 6656 . mat - the matrix 6657 6658 Output Parameters: 6659 + m - the number of global rows 6660 - n - the number of global columns 6661 6662 Level: beginner 6663 6664 Note: 6665 Both output parameters can be `NULL` on input. 6666 6667 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()` 6668 @*/ 6669 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n) 6670 { 6671 PetscFunctionBegin; 6672 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6673 if (m) *m = mat->rmap->N; 6674 if (n) *n = mat->cmap->N; 6675 PetscFunctionReturn(PETSC_SUCCESS); 6676 } 6677 6678 /*@C 6679 MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns 6680 of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`. 6681 6682 Not Collective 6683 6684 Input Parameter: 6685 . mat - the matrix 6686 6687 Output Parameters: 6688 + m - the number of local rows, use `NULL` to not obtain this value 6689 - n - the number of local columns, use `NULL` to not obtain this value 6690 6691 Level: beginner 6692 6693 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()` 6694 @*/ 6695 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n) 6696 { 6697 PetscFunctionBegin; 6698 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6699 if (m) PetscValidIntPointer(m, 2); 6700 if (n) PetscValidIntPointer(n, 3); 6701 if (m) *m = mat->rmap->n; 6702 if (n) *n = mat->cmap->n; 6703 PetscFunctionReturn(PETSC_SUCCESS); 6704 } 6705 6706 /*@C 6707 MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by 6708 this processor. (The columns of the "diagonal block" for most sparse matrix formats). See [Matrix Layouts](sec_matlayout) for details on matrix layouts. 6709 6710 Not Collective, unless matrix has not been allocated, then collective 6711 6712 Input Parameter: 6713 . mat - the matrix 6714 6715 Output Parameters: 6716 + m - the global index of the first local column, use `NULL` to not obtain this value 6717 - n - one more than the global index of the last local column, use `NULL` to not obtain this value 6718 6719 Level: developer 6720 6721 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout` 6722 @*/ 6723 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n) 6724 { 6725 PetscFunctionBegin; 6726 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6727 PetscValidType(mat, 1); 6728 if (m) PetscValidIntPointer(m, 2); 6729 if (n) PetscValidIntPointer(n, 3); 6730 MatCheckPreallocated(mat, 1); 6731 if (m) *m = mat->cmap->rstart; 6732 if (n) *n = mat->cmap->rend; 6733 PetscFunctionReturn(PETSC_SUCCESS); 6734 } 6735 6736 /*@C 6737 MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6738 this MPI process. For all matrices it returns the range of matrix rows associated with rows of a vector that would contain the result of a matrix 6739 vector product with this matrix. See [Matrix Layouts](sec_matlayout) for details on matrix layouts 6740 6741 Not Collective 6742 6743 Input Parameter: 6744 . mat - the matrix 6745 6746 Output Parameters: 6747 + m - the global index of the first local row, use `NULL` to not obtain this value 6748 - n - one more than the global index of the last local row, use `NULL` to not obtain this value 6749 6750 Level: beginner 6751 6752 Note: 6753 This function requires that the matrix be preallocated. If you have not preallocated, consider using 6754 `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N) 6755 and then `MPI_Scan()` to calculate prefix sums of the local sizes. 6756 6757 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, 6758 `PetscLayout` 6759 @*/ 6760 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n) 6761 { 6762 PetscFunctionBegin; 6763 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6764 PetscValidType(mat, 1); 6765 if (m) PetscValidIntPointer(m, 2); 6766 if (n) PetscValidIntPointer(n, 3); 6767 MatCheckPreallocated(mat, 1); 6768 if (m) *m = mat->rmap->rstart; 6769 if (n) *n = mat->rmap->rend; 6770 PetscFunctionReturn(PETSC_SUCCESS); 6771 } 6772 6773 /*@C 6774 MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6775 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 6776 vector product with this matrix. See [Matrix Layouts](sec_matlayout) for details on matrix layouts 6777 6778 Not Collective, unless matrix has not been allocated 6779 6780 Input Parameter: 6781 . mat - the matrix 6782 6783 Output Parameter: 6784 . ranges - start of each processors portion plus one more than the total length at the end 6785 6786 Level: beginner 6787 6788 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout` 6789 @*/ 6790 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges) 6791 { 6792 PetscFunctionBegin; 6793 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6794 PetscValidType(mat, 1); 6795 MatCheckPreallocated(mat, 1); 6796 PetscCall(PetscLayoutGetRanges(mat->rmap, ranges)); 6797 PetscFunctionReturn(PETSC_SUCCESS); 6798 } 6799 6800 /*@C 6801 MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by 6802 each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See [Matrix Layouts](sec_matlayout) for details on matrix layouts. 6803 6804 Not Collective, unless matrix has not been allocated 6805 6806 Input Parameter: 6807 . mat - the matrix 6808 6809 Output Parameter: 6810 . ranges - start of each processors portion plus one more then the total length at the end 6811 6812 Level: beginner 6813 6814 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()` 6815 @*/ 6816 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges) 6817 { 6818 PetscFunctionBegin; 6819 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6820 PetscValidType(mat, 1); 6821 MatCheckPreallocated(mat, 1); 6822 PetscCall(PetscLayoutGetRanges(mat->cmap, ranges)); 6823 PetscFunctionReturn(PETSC_SUCCESS); 6824 } 6825 6826 /*@C 6827 MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this 6828 corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership 6829 is more complicated. See [Matrix Layouts](sec_matlayout) for details on matrix layouts. 6830 6831 Not Collective 6832 6833 Input Parameter: 6834 . A - matrix 6835 6836 Output Parameters: 6837 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value 6838 - cols - columns in which this process owns elements, use `NULL` to not obtain this value 6839 6840 Level: intermediate 6841 6842 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK`` 6843 @*/ 6844 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols) 6845 { 6846 PetscErrorCode (*f)(Mat, IS *, IS *); 6847 6848 PetscFunctionBegin; 6849 MatCheckPreallocated(A, 1); 6850 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f)); 6851 if (f) { 6852 PetscCall((*f)(A, rows, cols)); 6853 } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */ 6854 if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows)); 6855 if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols)); 6856 } 6857 PetscFunctionReturn(PETSC_SUCCESS); 6858 } 6859 6860 /*@C 6861 MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()` 6862 Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()` 6863 to complete the factorization. 6864 6865 Collective 6866 6867 Input Parameters: 6868 + fact - the factorized matrix obtained with `MatGetFactor()` 6869 . mat - the matrix 6870 . row - row permutation 6871 . col - column permutation 6872 - info - structure containing 6873 .vb 6874 levels - number of levels of fill. 6875 expected fill - as ratio of original fill. 6876 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 6877 missing diagonal entries) 6878 .ve 6879 6880 Level: developer 6881 6882 Notes: 6883 See [Matrix Factorization](sec_matfactor) for additional information. 6884 6885 Most users should employ the `KSP` interface for linear solvers 6886 instead of working directly with matrix algebra routines such as this. 6887 See, e.g., `KSPCreate()`. 6888 6889 Uses the definition of level of fill as in Y. Saad, 2003 6890 6891 Developer Notes: 6892 The Fortran interface is not autogenerated as the 6893 interface definition cannot be generated correctly [due to `MatFactorInfo`] 6894 6895 References: 6896 . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003 6897 6898 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 6899 `MatGetOrdering()`, `MatFactorInfo` 6900 @*/ 6901 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 6902 { 6903 PetscFunctionBegin; 6904 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 6905 PetscValidType(mat, 2); 6906 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 6907 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 6908 PetscValidPointer(info, 5); 6909 PetscValidPointer(fact, 1); 6910 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels); 6911 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 6912 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6913 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6914 MatCheckPreallocated(mat, 2); 6915 6916 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0)); 6917 PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info); 6918 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0)); 6919 PetscFunctionReturn(PETSC_SUCCESS); 6920 } 6921 6922 /*@C 6923 MatICCFactorSymbolic - Performs symbolic incomplete 6924 Cholesky factorization for a symmetric matrix. Use 6925 `MatCholeskyFactorNumeric()` to complete the factorization. 6926 6927 Collective 6928 6929 Input Parameters: 6930 + fact - the factorized matrix obtained with `MatGetFactor()` 6931 . mat - the matrix to be factored 6932 . perm - row and column permutation 6933 - info - structure containing 6934 .vb 6935 levels - number of levels of fill. 6936 expected fill - as ratio of original fill. 6937 .ve 6938 6939 Level: developer 6940 6941 Notes: 6942 Most users should employ the `KSP` interface for linear solvers 6943 instead of working directly with matrix algebra routines such as this. 6944 See, e.g., `KSPCreate()`. 6945 6946 This uses the definition of level of fill as in Y. Saad, 2003 6947 6948 Developer Notes: 6949 The Fortran interface is not autogenerated as the 6950 interface definition cannot be generated correctly [due to `MatFactorInfo`] 6951 6952 References: 6953 . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003 6954 6955 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 6956 @*/ 6957 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 6958 { 6959 PetscFunctionBegin; 6960 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 6961 PetscValidType(mat, 2); 6962 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 6963 PetscValidPointer(info, 4); 6964 PetscValidPointer(fact, 1); 6965 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6966 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels); 6967 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 6968 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6969 MatCheckPreallocated(mat, 2); 6970 6971 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 6972 PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info); 6973 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 6974 PetscFunctionReturn(PETSC_SUCCESS); 6975 } 6976 6977 /*@C 6978 MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat 6979 points to an array of valid matrices, they may be reused to store the new 6980 submatrices. 6981 6982 Collective 6983 6984 Input Parameters: 6985 + mat - the matrix 6986 . n - the number of submatrixes to be extracted (on this processor, may be zero) 6987 . irow - index set of rows to extract 6988 . icol - index set of columns to extract 6989 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 6990 6991 Output Parameter: 6992 . submat - the array of submatrices 6993 6994 Level: advanced 6995 6996 Notes: 6997 `MatCreateSubMatrices()` can extract ONLY sequential submatrices 6998 (from both sequential and parallel matrices). Use `MatCreateSubMatrix()` 6999 to extract a parallel submatrix. 7000 7001 Some matrix types place restrictions on the row and column 7002 indices, such as that they be sorted or that they be equal to each other. 7003 7004 The index sets may not have duplicate entries. 7005 7006 When extracting submatrices from a parallel matrix, each processor can 7007 form a different submatrix by setting the rows and columns of its 7008 individual index sets according to the local submatrix desired. 7009 7010 When finished using the submatrices, the user should destroy 7011 them with `MatDestroySubMatrices()`. 7012 7013 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 7014 original matrix has not changed from that last call to `MatCreateSubMatrices()`. 7015 7016 This routine creates the matrices in submat; you should NOT create them before 7017 calling it. It also allocates the array of matrix pointers submat. 7018 7019 For `MATBAIJ` matrices the index sets must respect the block structure, that is if they 7020 request one row/column in a block, they must request all rows/columns that are in 7021 that block. For example, if the block size is 2 you cannot request just row 0 and 7022 column 0. 7023 7024 Fortran Notes: 7025 The Fortran interface is slightly different from that given below; it 7026 requires one to pass in as `submat` a `Mat` (integer) array of size at least n+1. 7027 7028 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7029 @*/ 7030 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7031 { 7032 PetscInt i; 7033 PetscBool eq; 7034 7035 PetscFunctionBegin; 7036 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7037 PetscValidType(mat, 1); 7038 if (n) { 7039 PetscValidPointer(irow, 3); 7040 for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3); 7041 PetscValidPointer(icol, 4); 7042 for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4); 7043 } 7044 PetscValidPointer(submat, 6); 7045 if (n && scall == MAT_REUSE_MATRIX) { 7046 PetscValidPointer(*submat, 6); 7047 for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6); 7048 } 7049 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7050 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7051 MatCheckPreallocated(mat, 1); 7052 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7053 PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat); 7054 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7055 for (i = 0; i < n; i++) { 7056 (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */ 7057 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7058 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7059 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 7060 if (mat->boundtocpu && mat->bindingpropagates) { 7061 PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE)); 7062 PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE)); 7063 } 7064 #endif 7065 } 7066 PetscFunctionReturn(PETSC_SUCCESS); 7067 } 7068 7069 /*@C 7070 MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms). 7071 7072 Collective 7073 7074 Input Parameters: 7075 + mat - the matrix 7076 . n - the number of submatrixes to be extracted 7077 . irow - index set of rows to extract 7078 . icol - index set of columns to extract 7079 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7080 7081 Output Parameter: 7082 . submat - the array of submatrices 7083 7084 Level: advanced 7085 7086 Note: 7087 This is used by `PCGASM` 7088 7089 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7090 @*/ 7091 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7092 { 7093 PetscInt i; 7094 PetscBool eq; 7095 7096 PetscFunctionBegin; 7097 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7098 PetscValidType(mat, 1); 7099 if (n) { 7100 PetscValidPointer(irow, 3); 7101 PetscValidHeaderSpecific(*irow, IS_CLASSID, 3); 7102 PetscValidPointer(icol, 4); 7103 PetscValidHeaderSpecific(*icol, IS_CLASSID, 4); 7104 } 7105 PetscValidPointer(submat, 6); 7106 if (n && scall == MAT_REUSE_MATRIX) { 7107 PetscValidPointer(*submat, 6); 7108 PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6); 7109 } 7110 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7111 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7112 MatCheckPreallocated(mat, 1); 7113 7114 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7115 PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat); 7116 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7117 for (i = 0; i < n; i++) { 7118 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7119 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7120 } 7121 PetscFunctionReturn(PETSC_SUCCESS); 7122 } 7123 7124 /*@C 7125 MatDestroyMatrices - Destroys an array of matrices. 7126 7127 Collective 7128 7129 Input Parameters: 7130 + n - the number of local matrices 7131 - mat - the matrices (this is a pointer to the array of matrices) 7132 7133 Level: advanced 7134 7135 Note: 7136 Frees not only the matrices, but also the array that contains the matrices 7137 7138 Fortran Notes: 7139 This does not free the array. 7140 7141 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()` 7142 @*/ 7143 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[]) 7144 { 7145 PetscInt i; 7146 7147 PetscFunctionBegin; 7148 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7149 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7150 PetscValidPointer(mat, 2); 7151 7152 for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i])); 7153 7154 /* memory is allocated even if n = 0 */ 7155 PetscCall(PetscFree(*mat)); 7156 PetscFunctionReturn(PETSC_SUCCESS); 7157 } 7158 7159 /*@C 7160 MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`. 7161 7162 Collective 7163 7164 Input Parameters: 7165 + n - the number of local matrices 7166 - mat - the matrices (this is a pointer to the array of matrices, just to match the calling 7167 sequence of `MatCreateSubMatrices()`) 7168 7169 Level: advanced 7170 7171 Note: 7172 Frees not only the matrices, but also the array that contains the matrices 7173 7174 Fortran Notes: 7175 This does not free the array. 7176 7177 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7178 @*/ 7179 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[]) 7180 { 7181 Mat mat0; 7182 7183 PetscFunctionBegin; 7184 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7185 /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */ 7186 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7187 PetscValidPointer(mat, 2); 7188 7189 mat0 = (*mat)[0]; 7190 if (mat0 && mat0->ops->destroysubmatrices) { 7191 PetscCall((*mat0->ops->destroysubmatrices)(n, mat)); 7192 } else { 7193 PetscCall(MatDestroyMatrices(n, mat)); 7194 } 7195 PetscFunctionReturn(PETSC_SUCCESS); 7196 } 7197 7198 /*@C 7199 MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process 7200 7201 Collective 7202 7203 Input Parameter: 7204 . mat - the matrix 7205 7206 Output Parameter: 7207 . matstruct - the sequential matrix with the nonzero structure of mat 7208 7209 Level: developer 7210 7211 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7212 @*/ 7213 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct) 7214 { 7215 PetscFunctionBegin; 7216 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7217 PetscValidPointer(matstruct, 2); 7218 7219 PetscValidType(mat, 1); 7220 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7221 MatCheckPreallocated(mat, 1); 7222 7223 PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7224 PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct); 7225 PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7226 PetscFunctionReturn(PETSC_SUCCESS); 7227 } 7228 7229 /*@C 7230 MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`. 7231 7232 Collective 7233 7234 Input Parameter: 7235 . mat - the matrix (this is a pointer to the array of matrices, just to match the calling 7236 sequence of `MatGetSeqNonzeroStructure()`) 7237 7238 Level: advanced 7239 7240 Note: 7241 Frees not only the matrices, but also the array that contains the matrices 7242 7243 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()` 7244 @*/ 7245 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat) 7246 { 7247 PetscFunctionBegin; 7248 PetscValidPointer(mat, 1); 7249 PetscCall(MatDestroy(mat)); 7250 PetscFunctionReturn(PETSC_SUCCESS); 7251 } 7252 7253 /*@ 7254 MatIncreaseOverlap - Given a set of submatrices indicated by index sets, 7255 replaces the index sets by larger ones that represent submatrices with 7256 additional overlap. 7257 7258 Collective 7259 7260 Input Parameters: 7261 + mat - the matrix 7262 . n - the number of index sets 7263 . is - the array of index sets (these index sets will changed during the call) 7264 - ov - the additional overlap requested 7265 7266 Options Database Key: 7267 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7268 7269 Level: developer 7270 7271 Note: 7272 The computed overlap preserves the matrix block sizes when the blocks are square. 7273 That is: if a matrix nonzero for a given block would increase the overlap all columns associated with 7274 that block are included in the overlap regardless of whether each specific column would increase the overlap. 7275 7276 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()` 7277 @*/ 7278 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov) 7279 { 7280 PetscInt i, bs, cbs; 7281 7282 PetscFunctionBegin; 7283 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7284 PetscValidType(mat, 1); 7285 PetscValidLogicalCollectiveInt(mat, n, 2); 7286 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7287 if (n) { 7288 PetscValidPointer(is, 3); 7289 for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3); 7290 } 7291 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7292 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7293 MatCheckPreallocated(mat, 1); 7294 7295 if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS); 7296 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7297 PetscUseTypeMethod(mat, increaseoverlap, n, is, ov); 7298 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7299 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 7300 if (bs == cbs) { 7301 for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs)); 7302 } 7303 PetscFunctionReturn(PETSC_SUCCESS); 7304 } 7305 7306 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt); 7307 7308 /*@ 7309 MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across 7310 a sub communicator, replaces the index sets by larger ones that represent submatrices with 7311 additional overlap. 7312 7313 Collective 7314 7315 Input Parameters: 7316 + mat - the matrix 7317 . n - the number of index sets 7318 . is - the array of index sets (these index sets will changed during the call) 7319 - ov - the additional overlap requested 7320 7321 ` Options Database Key: 7322 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7323 7324 Level: developer 7325 7326 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()` 7327 @*/ 7328 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov) 7329 { 7330 PetscInt i; 7331 7332 PetscFunctionBegin; 7333 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7334 PetscValidType(mat, 1); 7335 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7336 if (n) { 7337 PetscValidPointer(is, 3); 7338 PetscValidHeaderSpecific(*is, IS_CLASSID, 3); 7339 } 7340 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7341 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7342 MatCheckPreallocated(mat, 1); 7343 if (!ov) PetscFunctionReturn(PETSC_SUCCESS); 7344 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7345 for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov)); 7346 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7347 PetscFunctionReturn(PETSC_SUCCESS); 7348 } 7349 7350 /*@ 7351 MatGetBlockSize - Returns the matrix block size. 7352 7353 Not Collective 7354 7355 Input Parameter: 7356 . mat - the matrix 7357 7358 Output Parameter: 7359 . bs - block size 7360 7361 Level: intermediate 7362 7363 Notes: 7364 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7365 7366 If the block size has not been set yet this routine returns 1. 7367 7368 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()` 7369 @*/ 7370 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs) 7371 { 7372 PetscFunctionBegin; 7373 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7374 PetscValidIntPointer(bs, 2); 7375 *bs = PetscAbs(mat->rmap->bs); 7376 PetscFunctionReturn(PETSC_SUCCESS); 7377 } 7378 7379 /*@ 7380 MatGetBlockSizes - Returns the matrix block row and column sizes. 7381 7382 Not Collective 7383 7384 Input Parameter: 7385 . mat - the matrix 7386 7387 Output Parameters: 7388 + rbs - row block size 7389 - cbs - column block size 7390 7391 Level: intermediate 7392 7393 Notes: 7394 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7395 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7396 7397 If a block size has not been set yet this routine returns 1. 7398 7399 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()` 7400 @*/ 7401 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs) 7402 { 7403 PetscFunctionBegin; 7404 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7405 if (rbs) PetscValidIntPointer(rbs, 2); 7406 if (cbs) PetscValidIntPointer(cbs, 3); 7407 if (rbs) *rbs = PetscAbs(mat->rmap->bs); 7408 if (cbs) *cbs = PetscAbs(mat->cmap->bs); 7409 PetscFunctionReturn(PETSC_SUCCESS); 7410 } 7411 7412 /*@ 7413 MatSetBlockSize - Sets the matrix block size. 7414 7415 Logically Collective 7416 7417 Input Parameters: 7418 + mat - the matrix 7419 - bs - block size 7420 7421 Level: intermediate 7422 7423 Notes: 7424 Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix. 7425 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7426 7427 For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size 7428 is compatible with the matrix local sizes. 7429 7430 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()` 7431 @*/ 7432 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs) 7433 { 7434 PetscFunctionBegin; 7435 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7436 PetscValidLogicalCollectiveInt(mat, bs, 2); 7437 PetscCall(MatSetBlockSizes(mat, bs, bs)); 7438 PetscFunctionReturn(PETSC_SUCCESS); 7439 } 7440 7441 typedef struct { 7442 PetscInt n; 7443 IS *is; 7444 Mat *mat; 7445 PetscObjectState nonzerostate; 7446 Mat C; 7447 } EnvelopeData; 7448 7449 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata) 7450 { 7451 for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i])); 7452 PetscCall(PetscFree(edata->is)); 7453 PetscCall(PetscFree(edata)); 7454 return PETSC_SUCCESS; 7455 } 7456 7457 /* 7458 MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores 7459 the sizes of these blocks in the matrix. An individual block may lie over several processes. 7460 7461 Collective 7462 7463 Input Parameter: 7464 . mat - the matrix 7465 7466 Notes: 7467 There can be zeros within the blocks 7468 7469 The blocks can overlap between processes, including laying on more than two processes 7470 7471 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()` 7472 */ 7473 static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat) 7474 { 7475 PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend; 7476 PetscInt *diag, *odiag, sc; 7477 VecScatter scatter; 7478 PetscScalar *seqv; 7479 const PetscScalar *parv; 7480 const PetscInt *ia, *ja; 7481 PetscBool set, flag, done; 7482 Mat AA = mat, A; 7483 MPI_Comm comm; 7484 PetscMPIInt rank, size, tag; 7485 MPI_Status status; 7486 PetscContainer container; 7487 EnvelopeData *edata; 7488 Vec seq, par; 7489 IS isglobal; 7490 7491 PetscFunctionBegin; 7492 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7493 PetscCall(MatIsSymmetricKnown(mat, &set, &flag)); 7494 if (!set || !flag) { 7495 /* TOO: only needs nonzero structure of transpose */ 7496 PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA)); 7497 PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN)); 7498 } 7499 PetscCall(MatAIJGetLocalMat(AA, &A)); 7500 PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7501 PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix"); 7502 7503 PetscCall(MatGetLocalSize(mat, &n, NULL)); 7504 PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag)); 7505 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 7506 PetscCallMPI(MPI_Comm_size(comm, &size)); 7507 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7508 7509 PetscCall(PetscMalloc2(n, &sizes, n, &starts)); 7510 7511 if (rank > 0) { 7512 PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7513 PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7514 } 7515 PetscCall(MatGetOwnershipRange(mat, &rstart, NULL)); 7516 for (i = 0; i < n; i++) { 7517 env = PetscMax(env, ja[ia[i + 1] - 1]); 7518 II = rstart + i; 7519 if (env == II) { 7520 starts[lblocks] = tbs; 7521 sizes[lblocks++] = 1 + II - tbs; 7522 tbs = 1 + II; 7523 } 7524 } 7525 if (rank < size - 1) { 7526 PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm)); 7527 PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm)); 7528 } 7529 7530 PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7531 if (!set || !flag) PetscCall(MatDestroy(&AA)); 7532 PetscCall(MatDestroy(&A)); 7533 7534 PetscCall(PetscNew(&edata)); 7535 PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate)); 7536 edata->n = lblocks; 7537 /* create IS needed for extracting blocks from the original matrix */ 7538 PetscCall(PetscMalloc1(lblocks, &edata->is)); 7539 for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i])); 7540 7541 /* Create the resulting inverse matrix structure with preallocation information */ 7542 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C)); 7543 PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 7544 PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat)); 7545 PetscCall(MatSetType(edata->C, MATAIJ)); 7546 7547 /* Communicate the start and end of each row, from each block to the correct rank */ 7548 /* TODO: Use PetscSF instead of VecScatter */ 7549 for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i]; 7550 PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq)); 7551 PetscCall(VecGetArrayWrite(seq, &seqv)); 7552 for (PetscInt i = 0; i < lblocks; i++) { 7553 for (PetscInt j = 0; j < sizes[i]; j++) { 7554 seqv[cnt] = starts[i]; 7555 seqv[cnt + 1] = starts[i] + sizes[i]; 7556 cnt += 2; 7557 } 7558 } 7559 PetscCall(VecRestoreArrayWrite(seq, &seqv)); 7560 PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 7561 sc -= cnt; 7562 PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par)); 7563 PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal)); 7564 PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter)); 7565 PetscCall(ISDestroy(&isglobal)); 7566 PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7567 PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7568 PetscCall(VecScatterDestroy(&scatter)); 7569 PetscCall(VecDestroy(&seq)); 7570 PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend)); 7571 PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag)); 7572 PetscCall(VecGetArrayRead(par, &parv)); 7573 cnt = 0; 7574 PetscCall(MatGetSize(mat, NULL, &n)); 7575 for (PetscInt i = 0; i < mat->rmap->n; i++) { 7576 PetscInt start, end, d = 0, od = 0; 7577 7578 start = (PetscInt)PetscRealPart(parv[cnt]); 7579 end = (PetscInt)PetscRealPart(parv[cnt + 1]); 7580 cnt += 2; 7581 7582 if (start < cstart) { 7583 od += cstart - start + n - cend; 7584 d += cend - cstart; 7585 } else if (start < cend) { 7586 od += n - cend; 7587 d += cend - start; 7588 } else od += n - start; 7589 if (end <= cstart) { 7590 od -= cstart - end + n - cend; 7591 d -= cend - cstart; 7592 } else if (end < cend) { 7593 od -= n - cend; 7594 d -= cend - end; 7595 } else od -= n - end; 7596 7597 odiag[i] = od; 7598 diag[i] = d; 7599 } 7600 PetscCall(VecRestoreArrayRead(par, &parv)); 7601 PetscCall(VecDestroy(&par)); 7602 PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL)); 7603 PetscCall(PetscFree2(diag, odiag)); 7604 PetscCall(PetscFree2(sizes, starts)); 7605 7606 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container)); 7607 PetscCall(PetscContainerSetPointer(container, edata)); 7608 PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy)); 7609 PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container)); 7610 PetscCall(PetscObjectDereference((PetscObject)container)); 7611 PetscFunctionReturn(PETSC_SUCCESS); 7612 } 7613 7614 /*@ 7615 MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A 7616 7617 Collective 7618 7619 Input Parameters: 7620 + A - the matrix 7621 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine 7622 7623 Output Parameter: 7624 . C - matrix with inverted block diagonal of `A` 7625 7626 Level: advanced 7627 7628 Note: 7629 For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal. 7630 7631 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()` 7632 @*/ 7633 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C) 7634 { 7635 PetscContainer container; 7636 EnvelopeData *edata; 7637 PetscObjectState nonzerostate; 7638 7639 PetscFunctionBegin; 7640 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7641 if (!container) { 7642 PetscCall(MatComputeVariableBlockEnvelope(A)); 7643 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7644 } 7645 PetscCall(PetscContainerGetPointer(container, (void **)&edata)); 7646 PetscCall(MatGetNonzeroState(A, &nonzerostate)); 7647 PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure"); 7648 PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output"); 7649 7650 PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat)); 7651 *C = edata->C; 7652 7653 for (PetscInt i = 0; i < edata->n; i++) { 7654 Mat D; 7655 PetscScalar *dvalues; 7656 7657 PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D)); 7658 PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE)); 7659 PetscCall(MatSeqDenseInvert(D)); 7660 PetscCall(MatDenseGetArray(D, &dvalues)); 7661 PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES)); 7662 PetscCall(MatDestroy(&D)); 7663 } 7664 PetscCall(MatDestroySubMatrices(edata->n, &edata->mat)); 7665 PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY)); 7666 PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY)); 7667 PetscFunctionReturn(PETSC_SUCCESS); 7668 } 7669 7670 /*@ 7671 MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size 7672 7673 Logically Collective 7674 7675 Input Parameters: 7676 + mat - the matrix 7677 . nblocks - the number of blocks on this process, each block can only exist on a single process 7678 - bsizes - the block sizes 7679 7680 Level: intermediate 7681 7682 Notes: 7683 Currently used by `PCVPBJACOBI` for `MATAIJ` matrices 7684 7685 Each variable point-block set of degrees of freedom must live on a single MPI process. That is a point block cannot straddle two MPI processes. 7686 7687 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, 7688 `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI` 7689 @*/ 7690 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes) 7691 { 7692 PetscInt i, ncnt = 0, nlocal; 7693 7694 PetscFunctionBegin; 7695 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7696 PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero"); 7697 PetscCall(MatGetLocalSize(mat, &nlocal, NULL)); 7698 for (i = 0; i < nblocks; i++) ncnt += bsizes[i]; 7699 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); 7700 PetscCall(PetscFree(mat->bsizes)); 7701 mat->nblocks = nblocks; 7702 PetscCall(PetscMalloc1(nblocks, &mat->bsizes)); 7703 PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks)); 7704 PetscFunctionReturn(PETSC_SUCCESS); 7705 } 7706 7707 /*@C 7708 MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size 7709 7710 Logically Collective; No Fortran Support 7711 7712 Input Parameter: 7713 . mat - the matrix 7714 7715 Output Parameters: 7716 + nblocks - the number of blocks on this process 7717 - bsizes - the block sizes 7718 7719 Level: intermediate 7720 7721 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()` 7722 @*/ 7723 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes) 7724 { 7725 PetscFunctionBegin; 7726 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7727 *nblocks = mat->nblocks; 7728 *bsizes = mat->bsizes; 7729 PetscFunctionReturn(PETSC_SUCCESS); 7730 } 7731 7732 /*@ 7733 MatSetBlockSizes - Sets the matrix block row and column sizes. 7734 7735 Logically Collective 7736 7737 Input Parameters: 7738 + mat - the matrix 7739 . rbs - row block size 7740 - cbs - column block size 7741 7742 Level: intermediate 7743 7744 Notes: 7745 Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix. 7746 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7747 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7748 7749 For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes 7750 are compatible with the matrix local sizes. 7751 7752 The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`. 7753 7754 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()` 7755 @*/ 7756 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs) 7757 { 7758 PetscFunctionBegin; 7759 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7760 PetscValidLogicalCollectiveInt(mat, rbs, 2); 7761 PetscValidLogicalCollectiveInt(mat, cbs, 3); 7762 PetscTryTypeMethod(mat, setblocksizes, rbs, cbs); 7763 if (mat->rmap->refcnt) { 7764 ISLocalToGlobalMapping l2g = NULL; 7765 PetscLayout nmap = NULL; 7766 7767 PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap)); 7768 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g)); 7769 PetscCall(PetscLayoutDestroy(&mat->rmap)); 7770 mat->rmap = nmap; 7771 mat->rmap->mapping = l2g; 7772 } 7773 if (mat->cmap->refcnt) { 7774 ISLocalToGlobalMapping l2g = NULL; 7775 PetscLayout nmap = NULL; 7776 7777 PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap)); 7778 if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g)); 7779 PetscCall(PetscLayoutDestroy(&mat->cmap)); 7780 mat->cmap = nmap; 7781 mat->cmap->mapping = l2g; 7782 } 7783 PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs)); 7784 PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs)); 7785 PetscFunctionReturn(PETSC_SUCCESS); 7786 } 7787 7788 /*@ 7789 MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices 7790 7791 Logically Collective 7792 7793 Input Parameters: 7794 + mat - the matrix 7795 . fromRow - matrix from which to copy row block size 7796 - fromCol - matrix from which to copy column block size (can be same as fromRow) 7797 7798 Level: developer 7799 7800 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()` 7801 @*/ 7802 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol) 7803 { 7804 PetscFunctionBegin; 7805 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7806 PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2); 7807 PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3); 7808 if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs)); 7809 if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs)); 7810 PetscFunctionReturn(PETSC_SUCCESS); 7811 } 7812 7813 /*@ 7814 MatResidual - Default routine to calculate the residual r = b - Ax 7815 7816 Collective 7817 7818 Input Parameters: 7819 + mat - the matrix 7820 . b - the right-hand-side 7821 - x - the approximate solution 7822 7823 Output Parameter: 7824 . r - location to store the residual 7825 7826 Level: developer 7827 7828 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()` 7829 @*/ 7830 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r) 7831 { 7832 PetscFunctionBegin; 7833 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7834 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 7835 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 7836 PetscValidHeaderSpecific(r, VEC_CLASSID, 4); 7837 PetscValidType(mat, 1); 7838 MatCheckPreallocated(mat, 1); 7839 PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0)); 7840 if (!mat->ops->residual) { 7841 PetscCall(MatMult(mat, x, r)); 7842 PetscCall(VecAYPX(r, -1.0, b)); 7843 } else { 7844 PetscUseTypeMethod(mat, residual, b, x, r); 7845 } 7846 PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0)); 7847 PetscFunctionReturn(PETSC_SUCCESS); 7848 } 7849 7850 /*MC 7851 MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix 7852 7853 Synopsis: 7854 MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 7855 7856 Not Collective 7857 7858 Input Parameters: 7859 + A - the matrix 7860 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7861 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7862 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7863 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7864 always used. 7865 7866 Output Parameters: 7867 + n - number of local rows in the (possibly compressed) matrix 7868 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 7869 . ja - the column indices 7870 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7871 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7872 7873 Level: developer 7874 7875 Note: 7876 Use `MatRestoreRowIJF90()` when you no longer need access to the data 7877 7878 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()` 7879 M*/ 7880 7881 /*MC 7882 MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()` 7883 7884 Synopsis: 7885 MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 7886 7887 Not Collective 7888 7889 Input Parameters: 7890 + A - the matrix 7891 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7892 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7893 inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7894 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7895 always used. 7896 . n - number of local rows in the (possibly compressed) matrix 7897 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 7898 . ja - the column indices 7899 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7900 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7901 7902 Level: developer 7903 7904 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()` 7905 M*/ 7906 7907 /*@C 7908 MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix 7909 7910 Collective 7911 7912 Input Parameters: 7913 + mat - the matrix 7914 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7915 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7916 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7917 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7918 always used. 7919 7920 Output Parameters: 7921 + n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed 7922 . 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 7923 . ja - the column indices, use `NULL` if not needed 7924 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7925 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7926 7927 Level: developer 7928 7929 Notes: 7930 You CANNOT change any of the ia[] or ja[] values. 7931 7932 Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values. 7933 7934 Fortran Notes: 7935 Use 7936 .vb 7937 PetscInt, pointer :: ia(:),ja(:) 7938 call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr) 7939 ! Access the ith and jth entries via ia(i) and ja(j) 7940 .ve 7941 `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()` 7942 7943 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()` 7944 @*/ 7945 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7946 { 7947 PetscFunctionBegin; 7948 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7949 PetscValidType(mat, 1); 7950 if (n) PetscValidIntPointer(n, 5); 7951 if (ia) PetscValidPointer(ia, 6); 7952 if (ja) PetscValidPointer(ja, 7); 7953 if (done) PetscValidBoolPointer(done, 8); 7954 MatCheckPreallocated(mat, 1); 7955 if (!mat->ops->getrowij && done) *done = PETSC_FALSE; 7956 else { 7957 if (done) *done = PETSC_TRUE; 7958 PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0)); 7959 PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done); 7960 PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0)); 7961 } 7962 PetscFunctionReturn(PETSC_SUCCESS); 7963 } 7964 7965 /*@C 7966 MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices. 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 7974 symmetrized 7975 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7976 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7977 always used. 7978 . n - number of columns in the (possibly compressed) matrix 7979 . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix 7980 - ja - the row indices 7981 7982 Output Parameter: 7983 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned 7984 7985 Level: developer 7986 7987 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 7988 @*/ 7989 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7990 { 7991 PetscFunctionBegin; 7992 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7993 PetscValidType(mat, 1); 7994 PetscValidIntPointer(n, 5); 7995 if (ia) PetscValidPointer(ia, 6); 7996 if (ja) PetscValidPointer(ja, 7); 7997 PetscValidBoolPointer(done, 8); 7998 MatCheckPreallocated(mat, 1); 7999 if (!mat->ops->getcolumnij) *done = PETSC_FALSE; 8000 else { 8001 *done = PETSC_TRUE; 8002 PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8003 } 8004 PetscFunctionReturn(PETSC_SUCCESS); 8005 } 8006 8007 /*@C 8008 MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`. 8009 8010 Collective 8011 8012 Input Parameters: 8013 + mat - the matrix 8014 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8015 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8016 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8017 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8018 always used. 8019 . n - size of (possibly compressed) matrix 8020 . ia - the row pointers 8021 - ja - the column indices 8022 8023 Output Parameter: 8024 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8025 8026 Level: developer 8027 8028 Note: 8029 This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental 8030 us of the array after it has been restored. If you pass `NULL`, it will 8031 not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid. 8032 8033 Fortran Notes: 8034 `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()` 8035 8036 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()` 8037 @*/ 8038 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8039 { 8040 PetscFunctionBegin; 8041 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8042 PetscValidType(mat, 1); 8043 if (ia) PetscValidPointer(ia, 6); 8044 if (ja) PetscValidPointer(ja, 7); 8045 if (done) PetscValidBoolPointer(done, 8); 8046 MatCheckPreallocated(mat, 1); 8047 8048 if (!mat->ops->restorerowij && done) *done = PETSC_FALSE; 8049 else { 8050 if (done) *done = PETSC_TRUE; 8051 PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8052 if (n) *n = 0; 8053 if (ia) *ia = NULL; 8054 if (ja) *ja = NULL; 8055 } 8056 PetscFunctionReturn(PETSC_SUCCESS); 8057 } 8058 8059 /*@C 8060 MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`. 8061 8062 Collective 8063 8064 Input Parameters: 8065 + mat - the matrix 8066 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8067 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8068 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8069 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8070 always used. 8071 8072 Output Parameters: 8073 + n - size of (possibly compressed) matrix 8074 . ia - the column pointers 8075 . ja - the row indices 8076 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8077 8078 Level: developer 8079 8080 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()` 8081 @*/ 8082 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8083 { 8084 PetscFunctionBegin; 8085 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8086 PetscValidType(mat, 1); 8087 if (ia) PetscValidPointer(ia, 6); 8088 if (ja) PetscValidPointer(ja, 7); 8089 PetscValidBoolPointer(done, 8); 8090 MatCheckPreallocated(mat, 1); 8091 8092 if (!mat->ops->restorecolumnij) *done = PETSC_FALSE; 8093 else { 8094 *done = PETSC_TRUE; 8095 PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8096 if (n) *n = 0; 8097 if (ia) *ia = NULL; 8098 if (ja) *ja = NULL; 8099 } 8100 PetscFunctionReturn(PETSC_SUCCESS); 8101 } 8102 8103 /*@C 8104 MatColoringPatch -Used inside matrix coloring routines that use `MatGetRowIJ()` and/or `MatGetColumnIJ()`. 8105 8106 Collective 8107 8108 Input Parameters: 8109 + mat - the matrix 8110 . ncolors - maximum color value 8111 . n - number of entries in colorarray 8112 - colorarray - array indicating color for each column 8113 8114 Output Parameter: 8115 . iscoloring - coloring generated using colorarray information 8116 8117 Level: developer 8118 8119 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()` 8120 @*/ 8121 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring) 8122 { 8123 PetscFunctionBegin; 8124 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8125 PetscValidType(mat, 1); 8126 PetscValidIntPointer(colorarray, 4); 8127 PetscValidPointer(iscoloring, 5); 8128 MatCheckPreallocated(mat, 1); 8129 8130 if (!mat->ops->coloringpatch) { 8131 PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring)); 8132 } else { 8133 PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring); 8134 } 8135 PetscFunctionReturn(PETSC_SUCCESS); 8136 } 8137 8138 /*@ 8139 MatSetUnfactored - Resets a factored matrix to be treated as unfactored. 8140 8141 Logically Collective 8142 8143 Input Parameter: 8144 . mat - the factored matrix to be reset 8145 8146 Level: developer 8147 8148 Notes: 8149 This routine should be used only with factored matrices formed by in-place 8150 factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE` 8151 format). This option can save memory, for example, when solving nonlinear 8152 systems with a matrix-free Newton-Krylov method and a matrix-based, in-place 8153 ILU(0) preconditioner. 8154 8155 One can specify in-place ILU(0) factorization by calling 8156 .vb 8157 PCType(pc,PCILU); 8158 PCFactorSeUseInPlace(pc); 8159 .ve 8160 or by using the options -pc_type ilu -pc_factor_in_place 8161 8162 In-place factorization ILU(0) can also be used as a local 8163 solver for the blocks within the block Jacobi or additive Schwarz 8164 methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc 8165 for details on setting local solver options. 8166 8167 Most users should employ the `KSP` interface for linear solvers 8168 instead of working directly with matrix algebra routines such as this. 8169 See, e.g., `KSPCreate()`. 8170 8171 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()` 8172 @*/ 8173 PetscErrorCode MatSetUnfactored(Mat mat) 8174 { 8175 PetscFunctionBegin; 8176 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8177 PetscValidType(mat, 1); 8178 MatCheckPreallocated(mat, 1); 8179 mat->factortype = MAT_FACTOR_NONE; 8180 if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS); 8181 PetscUseTypeMethod(mat, setunfactored); 8182 PetscFunctionReturn(PETSC_SUCCESS); 8183 } 8184 8185 /*MC 8186 MatDenseGetArrayF90 - Accesses a matrix array from Fortran 8187 8188 Synopsis: 8189 MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8190 8191 Not Collective 8192 8193 Input Parameter: 8194 . x - matrix 8195 8196 Output Parameters: 8197 + xx_v - the Fortran pointer to the array 8198 - ierr - error code 8199 8200 Example of Usage: 8201 .vb 8202 PetscScalar, pointer xx_v(:,:) 8203 .... 8204 call MatDenseGetArrayF90(x,xx_v,ierr) 8205 a = xx_v(3) 8206 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8207 .ve 8208 8209 Level: advanced 8210 8211 .seealso: [](ch_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()` 8212 M*/ 8213 8214 /*MC 8215 MatDenseRestoreArrayF90 - Restores a matrix array that has been 8216 accessed with `MatDenseGetArrayF90()`. 8217 8218 Synopsis: 8219 MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8220 8221 Not Collective 8222 8223 Input Parameters: 8224 + x - matrix 8225 - xx_v - the Fortran90 pointer to the array 8226 8227 Output Parameter: 8228 . ierr - error code 8229 8230 Example of Usage: 8231 .vb 8232 PetscScalar, pointer xx_v(:,:) 8233 .... 8234 call MatDenseGetArrayF90(x,xx_v,ierr) 8235 a = xx_v(3) 8236 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8237 .ve 8238 8239 Level: advanced 8240 8241 .seealso: [](ch_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()` 8242 M*/ 8243 8244 /*MC 8245 MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran. 8246 8247 Synopsis: 8248 MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8249 8250 Not Collective 8251 8252 Input Parameter: 8253 . x - matrix 8254 8255 Output Parameters: 8256 + xx_v - the Fortran pointer to the array 8257 - ierr - error code 8258 8259 Example of Usage: 8260 .vb 8261 PetscScalar, pointer xx_v(:) 8262 .... 8263 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8264 a = xx_v(3) 8265 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8266 .ve 8267 8268 Level: advanced 8269 8270 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()` 8271 M*/ 8272 8273 /*MC 8274 MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been 8275 accessed with `MatSeqAIJGetArrayF90()`. 8276 8277 Synopsis: 8278 MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8279 8280 Not Collective 8281 8282 Input Parameters: 8283 + x - matrix 8284 - xx_v - the Fortran90 pointer to the array 8285 8286 Output Parameter: 8287 . ierr - error code 8288 8289 Example of Usage: 8290 .vb 8291 PetscScalar, pointer xx_v(:) 8292 .... 8293 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8294 a = xx_v(3) 8295 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8296 .ve 8297 8298 Level: advanced 8299 8300 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()` 8301 M*/ 8302 8303 /*@ 8304 MatCreateSubMatrix - Gets a single submatrix on the same number of processors 8305 as the original matrix. 8306 8307 Collective 8308 8309 Input Parameters: 8310 + mat - the original matrix 8311 . isrow - parallel `IS` containing the rows this processor should obtain 8312 . 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. 8313 - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 8314 8315 Output Parameter: 8316 . newmat - the new submatrix, of the same type as the original matrix 8317 8318 Level: advanced 8319 8320 Notes: 8321 The submatrix will be able to be multiplied with vectors using the same layout as `iscol`. 8322 8323 Some matrix types place restrictions on the row and column indices, such 8324 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; 8325 for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row. 8326 8327 The index sets may not have duplicate entries. 8328 8329 The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`, 8330 the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls 8331 to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX` 8332 will reuse the matrix generated the first time. You should call `MatDestroy()` on `newmat` when 8333 you are finished using it. 8334 8335 The communicator of the newly obtained matrix is ALWAYS the same as the communicator of 8336 the input matrix. 8337 8338 If `iscol` is `NULL` then all columns are obtained (not supported in Fortran). 8339 8340 Example usage: 8341 Consider the following 8x8 matrix with 34 non-zero values, that is 8342 assembled across 3 processors. Let's assume that proc0 owns 3 rows, 8343 proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 8344 as follows 8345 .vb 8346 1 2 0 | 0 3 0 | 0 4 8347 Proc0 0 5 6 | 7 0 0 | 8 0 8348 9 0 10 | 11 0 0 | 12 0 8349 ------------------------------------- 8350 13 0 14 | 15 16 17 | 0 0 8351 Proc1 0 18 0 | 19 20 21 | 0 0 8352 0 0 0 | 22 23 0 | 24 0 8353 ------------------------------------- 8354 Proc2 25 26 27 | 0 0 28 | 29 0 8355 30 0 0 | 31 32 33 | 0 34 8356 .ve 8357 8358 Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6]. The resulting submatrix is 8359 8360 .vb 8361 2 0 | 0 3 0 | 0 8362 Proc0 5 6 | 7 0 0 | 8 8363 ------------------------------- 8364 Proc1 18 0 | 19 20 21 | 0 8365 ------------------------------- 8366 Proc2 26 27 | 0 0 28 | 29 8367 0 0 | 31 32 33 | 0 8368 .ve 8369 8370 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()` 8371 @*/ 8372 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat) 8373 { 8374 PetscMPIInt size; 8375 Mat *local; 8376 IS iscoltmp; 8377 PetscBool flg; 8378 8379 PetscFunctionBegin; 8380 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8381 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 8382 if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 8383 PetscValidPointer(newmat, 5); 8384 if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5); 8385 PetscValidType(mat, 1); 8386 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8387 PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX"); 8388 8389 MatCheckPreallocated(mat, 1); 8390 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8391 8392 if (!iscol || isrow == iscol) { 8393 PetscBool stride; 8394 PetscMPIInt grabentirematrix = 0, grab; 8395 PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride)); 8396 if (stride) { 8397 PetscInt first, step, n, rstart, rend; 8398 PetscCall(ISStrideGetInfo(isrow, &first, &step)); 8399 if (step == 1) { 8400 PetscCall(MatGetOwnershipRange(mat, &rstart, &rend)); 8401 if (rstart == first) { 8402 PetscCall(ISGetLocalSize(isrow, &n)); 8403 if (n == rend - rstart) grabentirematrix = 1; 8404 } 8405 } 8406 } 8407 PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat))); 8408 if (grab) { 8409 PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n")); 8410 if (cll == MAT_INITIAL_MATRIX) { 8411 *newmat = mat; 8412 PetscCall(PetscObjectReference((PetscObject)mat)); 8413 } 8414 PetscFunctionReturn(PETSC_SUCCESS); 8415 } 8416 } 8417 8418 if (!iscol) { 8419 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp)); 8420 } else { 8421 iscoltmp = iscol; 8422 } 8423 8424 /* if original matrix is on just one processor then use submatrix generated */ 8425 if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) { 8426 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat)); 8427 goto setproperties; 8428 } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) { 8429 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local)); 8430 *newmat = *local; 8431 PetscCall(PetscFree(local)); 8432 goto setproperties; 8433 } else if (!mat->ops->createsubmatrix) { 8434 /* Create a new matrix type that implements the operation using the full matrix */ 8435 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8436 switch (cll) { 8437 case MAT_INITIAL_MATRIX: 8438 PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat)); 8439 break; 8440 case MAT_REUSE_MATRIX: 8441 PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp)); 8442 break; 8443 default: 8444 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX"); 8445 } 8446 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8447 goto setproperties; 8448 } 8449 8450 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8451 PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat); 8452 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8453 8454 setproperties: 8455 PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg)); 8456 if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat)); 8457 if (!iscol) PetscCall(ISDestroy(&iscoltmp)); 8458 if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat)); 8459 PetscFunctionReturn(PETSC_SUCCESS); 8460 } 8461 8462 /*@ 8463 MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix 8464 8465 Not Collective 8466 8467 Input Parameters: 8468 + A - the matrix we wish to propagate options from 8469 - B - the matrix we wish to propagate options to 8470 8471 Level: beginner 8472 8473 Note: 8474 Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL` 8475 8476 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 8477 @*/ 8478 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B) 8479 { 8480 PetscFunctionBegin; 8481 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8482 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 8483 B->symmetry_eternal = A->symmetry_eternal; 8484 B->structural_symmetry_eternal = A->structural_symmetry_eternal; 8485 B->symmetric = A->symmetric; 8486 B->structurally_symmetric = A->structurally_symmetric; 8487 B->spd = A->spd; 8488 B->hermitian = A->hermitian; 8489 PetscFunctionReturn(PETSC_SUCCESS); 8490 } 8491 8492 /*@ 8493 MatStashSetInitialSize - sets the sizes of the matrix stash, that is 8494 used during the assembly process to store values that belong to 8495 other processors. 8496 8497 Not Collective 8498 8499 Input Parameters: 8500 + mat - the matrix 8501 . size - the initial size of the stash. 8502 - bsize - the initial size of the block-stash(if used). 8503 8504 Options Database Keys: 8505 + -matstash_initial_size <size> or <size0,size1,...sizep-1> - set initial size 8506 - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1> - set initial block size 8507 8508 Level: intermediate 8509 8510 Notes: 8511 The block-stash is used for values set with `MatSetValuesBlocked()` while 8512 the stash is used for values set with `MatSetValues()` 8513 8514 Run with the option -info and look for output of the form 8515 MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs. 8516 to determine the appropriate value, MM, to use for size and 8517 MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs. 8518 to determine the value, BMM to use for bsize 8519 8520 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()` 8521 @*/ 8522 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize) 8523 { 8524 PetscFunctionBegin; 8525 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8526 PetscValidType(mat, 1); 8527 PetscCall(MatStashSetInitialSize_Private(&mat->stash, size)); 8528 PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize)); 8529 PetscFunctionReturn(PETSC_SUCCESS); 8530 } 8531 8532 /*@ 8533 MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of 8534 the matrix 8535 8536 Neighbor-wise Collective 8537 8538 Input Parameters: 8539 + A - the matrix 8540 . x - the vector to be multiplied by the interpolation operator 8541 - y - the vector to be added to the result 8542 8543 Output Parameter: 8544 . w - the resulting vector 8545 8546 Level: intermediate 8547 8548 Notes: 8549 `w` may be the same vector as `y`. 8550 8551 This allows one to use either the restriction or interpolation (its transpose) 8552 matrix to do the interpolation 8553 8554 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8555 @*/ 8556 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w) 8557 { 8558 PetscInt M, N, Ny; 8559 8560 PetscFunctionBegin; 8561 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8562 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8563 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8564 PetscValidHeaderSpecific(w, VEC_CLASSID, 4); 8565 PetscCall(MatGetSize(A, &M, &N)); 8566 PetscCall(VecGetSize(y, &Ny)); 8567 if (M == Ny) { 8568 PetscCall(MatMultAdd(A, x, y, w)); 8569 } else { 8570 PetscCall(MatMultTransposeAdd(A, x, y, w)); 8571 } 8572 PetscFunctionReturn(PETSC_SUCCESS); 8573 } 8574 8575 /*@ 8576 MatInterpolate - y = A*x or A'*x depending on the shape of 8577 the matrix 8578 8579 Neighbor-wise Collective 8580 8581 Input Parameters: 8582 + A - the matrix 8583 - x - the vector to be interpolated 8584 8585 Output Parameter: 8586 . y - the resulting vector 8587 8588 Level: intermediate 8589 8590 Note: 8591 This allows one to use either the restriction or interpolation (its transpose) 8592 matrix to do the interpolation 8593 8594 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8595 @*/ 8596 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y) 8597 { 8598 PetscInt M, N, Ny; 8599 8600 PetscFunctionBegin; 8601 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8602 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8603 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8604 PetscCall(MatGetSize(A, &M, &N)); 8605 PetscCall(VecGetSize(y, &Ny)); 8606 if (M == Ny) { 8607 PetscCall(MatMult(A, x, y)); 8608 } else { 8609 PetscCall(MatMultTranspose(A, x, y)); 8610 } 8611 PetscFunctionReturn(PETSC_SUCCESS); 8612 } 8613 8614 /*@ 8615 MatRestrict - y = A*x or A'*x 8616 8617 Neighbor-wise Collective 8618 8619 Input Parameters: 8620 + A - the matrix 8621 - x - the vector to be restricted 8622 8623 Output Parameter: 8624 . y - the resulting vector 8625 8626 Level: intermediate 8627 8628 Note: 8629 This allows one to use either the restriction or interpolation (its transpose) 8630 matrix to do the restriction 8631 8632 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG` 8633 @*/ 8634 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y) 8635 { 8636 PetscInt M, N, Ny; 8637 8638 PetscFunctionBegin; 8639 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8640 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8641 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8642 PetscCall(MatGetSize(A, &M, &N)); 8643 PetscCall(VecGetSize(y, &Ny)); 8644 if (M == Ny) { 8645 PetscCall(MatMult(A, x, y)); 8646 } else { 8647 PetscCall(MatMultTranspose(A, x, y)); 8648 } 8649 PetscFunctionReturn(PETSC_SUCCESS); 8650 } 8651 8652 /*@ 8653 MatMatInterpolateAdd - Y = W + A*X or W + A'*X 8654 8655 Neighbor-wise Collective 8656 8657 Input Parameters: 8658 + A - the matrix 8659 . x - the input dense matrix to be multiplied 8660 - w - the input dense matrix to be added to the result 8661 8662 Output Parameter: 8663 . y - the output dense matrix 8664 8665 Level: intermediate 8666 8667 Note: 8668 This allows one to use either the restriction or interpolation (its transpose) 8669 matrix to do the interpolation. y matrix can be reused if already created with the proper sizes, 8670 otherwise it will be recreated. y must be initialized to `NULL` if not supplied. 8671 8672 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG` 8673 @*/ 8674 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y) 8675 { 8676 PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0; 8677 PetscBool trans = PETSC_TRUE; 8678 MatReuse reuse = MAT_INITIAL_MATRIX; 8679 8680 PetscFunctionBegin; 8681 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8682 PetscValidHeaderSpecific(x, MAT_CLASSID, 2); 8683 PetscValidType(x, 2); 8684 if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3); 8685 if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4); 8686 PetscCall(MatGetSize(A, &M, &N)); 8687 PetscCall(MatGetSize(x, &Mx, &Nx)); 8688 if (N == Mx) trans = PETSC_FALSE; 8689 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); 8690 Mo = trans ? N : M; 8691 if (*y) { 8692 PetscCall(MatGetSize(*y, &My, &Ny)); 8693 if (Mo == My && Nx == Ny) { 8694 reuse = MAT_REUSE_MATRIX; 8695 } else { 8696 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); 8697 PetscCall(MatDestroy(y)); 8698 } 8699 } 8700 8701 if (w && *y == w) { /* this is to minimize changes in PCMG */ 8702 PetscBool flg; 8703 8704 PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w)); 8705 if (w) { 8706 PetscInt My, Ny, Mw, Nw; 8707 8708 PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg)); 8709 PetscCall(MatGetSize(*y, &My, &Ny)); 8710 PetscCall(MatGetSize(w, &Mw, &Nw)); 8711 if (!flg || My != Mw || Ny != Nw) w = NULL; 8712 } 8713 if (!w) { 8714 PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w)); 8715 PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w)); 8716 PetscCall(PetscObjectDereference((PetscObject)w)); 8717 } else { 8718 PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN)); 8719 } 8720 } 8721 if (!trans) { 8722 PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8723 } else { 8724 PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8725 } 8726 if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN)); 8727 PetscFunctionReturn(PETSC_SUCCESS); 8728 } 8729 8730 /*@ 8731 MatMatInterpolate - Y = A*X or A'*X 8732 8733 Neighbor-wise Collective 8734 8735 Input Parameters: 8736 + A - the matrix 8737 - x - the input dense matrix 8738 8739 Output Parameter: 8740 . y - the output dense matrix 8741 8742 Level: intermediate 8743 8744 Note: 8745 This allows one to use either the restriction or interpolation (its transpose) 8746 matrix to do the interpolation. y matrix can be reused if already created with the proper sizes, 8747 otherwise it will be recreated. y must be initialized to `NULL` if not supplied. 8748 8749 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG` 8750 @*/ 8751 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y) 8752 { 8753 PetscFunctionBegin; 8754 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8755 PetscFunctionReturn(PETSC_SUCCESS); 8756 } 8757 8758 /*@ 8759 MatMatRestrict - Y = A*X or A'*X 8760 8761 Neighbor-wise Collective 8762 8763 Input Parameters: 8764 + A - the matrix 8765 - x - the input dense matrix 8766 8767 Output Parameter: 8768 . y - the output dense matrix 8769 8770 Level: intermediate 8771 8772 Note: 8773 This allows one to use either the restriction or interpolation (its transpose) 8774 matrix to do the restriction. y matrix can be reused if already created with the proper sizes, 8775 otherwise it will be recreated. y must be initialized to `NULL` if not supplied. 8776 8777 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG` 8778 @*/ 8779 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y) 8780 { 8781 PetscFunctionBegin; 8782 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8783 PetscFunctionReturn(PETSC_SUCCESS); 8784 } 8785 8786 /*@ 8787 MatGetNullSpace - retrieves the null space of a matrix. 8788 8789 Logically Collective 8790 8791 Input Parameters: 8792 + mat - the matrix 8793 - nullsp - the null space object 8794 8795 Level: developer 8796 8797 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace` 8798 @*/ 8799 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp) 8800 { 8801 PetscFunctionBegin; 8802 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8803 PetscValidPointer(nullsp, 2); 8804 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp; 8805 PetscFunctionReturn(PETSC_SUCCESS); 8806 } 8807 8808 /*@ 8809 MatSetNullSpace - attaches a null space to a matrix. 8810 8811 Logically Collective 8812 8813 Input Parameters: 8814 + mat - the matrix 8815 - nullsp - the null space object 8816 8817 Level: advanced 8818 8819 Notes: 8820 This null space is used by the `KSP` linear solvers to solve singular systems. 8821 8822 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` 8823 8824 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 8825 to zero but the linear system will still be solved in a least squares sense. 8826 8827 The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that 8828 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). 8829 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 8830 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 8831 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). 8832 This \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix. 8833 8834 If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called 8835 `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this 8836 routine also automatically calls `MatSetTransposeNullSpace()`. 8837 8838 The user should call `MatNullSpaceDestroy()`. 8839 8840 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, 8841 `KSPSetPCSide()` 8842 @*/ 8843 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp) 8844 { 8845 PetscFunctionBegin; 8846 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8847 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8848 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8849 PetscCall(MatNullSpaceDestroy(&mat->nullsp)); 8850 mat->nullsp = nullsp; 8851 if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp)); 8852 PetscFunctionReturn(PETSC_SUCCESS); 8853 } 8854 8855 /*@ 8856 MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix. 8857 8858 Logically Collective 8859 8860 Input Parameters: 8861 + mat - the matrix 8862 - nullsp - the null space object 8863 8864 Level: developer 8865 8866 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()` 8867 @*/ 8868 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp) 8869 { 8870 PetscFunctionBegin; 8871 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8872 PetscValidType(mat, 1); 8873 PetscValidPointer(nullsp, 2); 8874 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp; 8875 PetscFunctionReturn(PETSC_SUCCESS); 8876 } 8877 8878 /*@ 8879 MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix 8880 8881 Logically Collective 8882 8883 Input Parameters: 8884 + mat - the matrix 8885 - nullsp - the null space object 8886 8887 Level: advanced 8888 8889 Notes: 8890 This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning. 8891 8892 See `MatSetNullSpace()` 8893 8894 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()` 8895 @*/ 8896 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp) 8897 { 8898 PetscFunctionBegin; 8899 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8900 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8901 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8902 PetscCall(MatNullSpaceDestroy(&mat->transnullsp)); 8903 mat->transnullsp = nullsp; 8904 PetscFunctionReturn(PETSC_SUCCESS); 8905 } 8906 8907 /*@ 8908 MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions 8909 This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix. 8910 8911 Logically Collective 8912 8913 Input Parameters: 8914 + mat - the matrix 8915 - nullsp - the null space object 8916 8917 Level: advanced 8918 8919 Notes: 8920 Overwrites any previous near null space that may have been attached 8921 8922 You can remove the null space by calling this routine with an nullsp of `NULL` 8923 8924 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()` 8925 @*/ 8926 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp) 8927 { 8928 PetscFunctionBegin; 8929 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8930 PetscValidType(mat, 1); 8931 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8932 MatCheckPreallocated(mat, 1); 8933 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8934 PetscCall(MatNullSpaceDestroy(&mat->nearnullsp)); 8935 mat->nearnullsp = nullsp; 8936 PetscFunctionReturn(PETSC_SUCCESS); 8937 } 8938 8939 /*@ 8940 MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()` 8941 8942 Not Collective 8943 8944 Input Parameter: 8945 . mat - the matrix 8946 8947 Output Parameter: 8948 . nullsp - the null space object, `NULL` if not set 8949 8950 Level: advanced 8951 8952 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()` 8953 @*/ 8954 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp) 8955 { 8956 PetscFunctionBegin; 8957 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8958 PetscValidType(mat, 1); 8959 PetscValidPointer(nullsp, 2); 8960 MatCheckPreallocated(mat, 1); 8961 *nullsp = mat->nearnullsp; 8962 PetscFunctionReturn(PETSC_SUCCESS); 8963 } 8964 8965 /*@C 8966 MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix. 8967 8968 Collective 8969 8970 Input Parameters: 8971 + mat - the matrix 8972 . row - row/column permutation 8973 - info - information on desired factorization process 8974 8975 Level: developer 8976 8977 Notes: 8978 Probably really in-place only when level of fill is zero, otherwise allocates 8979 new space to store factored matrix and deletes previous memory. 8980 8981 Most users should employ the `KSP` interface for linear solvers 8982 instead of working directly with matrix algebra routines such as this. 8983 See, e.g., `KSPCreate()`. 8984 8985 Developer Notes: 8986 The Fortran interface is not autogenerated as the 8987 interface definition cannot be generated correctly [due to `MatFactorInfo`] 8988 8989 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 8990 @*/ 8991 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info) 8992 { 8993 PetscFunctionBegin; 8994 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8995 PetscValidType(mat, 1); 8996 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 8997 PetscValidPointer(info, 3); 8998 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 8999 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 9000 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 9001 MatCheckPreallocated(mat, 1); 9002 PetscUseTypeMethod(mat, iccfactor, row, info); 9003 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9004 PetscFunctionReturn(PETSC_SUCCESS); 9005 } 9006 9007 /*@ 9008 MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the 9009 ghosted ones. 9010 9011 Not Collective 9012 9013 Input Parameters: 9014 + mat - the matrix 9015 - diag - the diagonal values, including ghost ones 9016 9017 Level: developer 9018 9019 Notes: 9020 Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices 9021 9022 This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()` 9023 9024 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 9025 @*/ 9026 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag) 9027 { 9028 PetscMPIInt size; 9029 9030 PetscFunctionBegin; 9031 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9032 PetscValidHeaderSpecific(diag, VEC_CLASSID, 2); 9033 PetscValidType(mat, 1); 9034 9035 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled"); 9036 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 9037 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 9038 if (size == 1) { 9039 PetscInt n, m; 9040 PetscCall(VecGetSize(diag, &n)); 9041 PetscCall(MatGetSize(mat, NULL, &m)); 9042 PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions"); 9043 PetscCall(MatDiagonalScale(mat, NULL, diag)); 9044 } else { 9045 PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag)); 9046 } 9047 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 9048 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9049 PetscFunctionReturn(PETSC_SUCCESS); 9050 } 9051 9052 /*@ 9053 MatGetInertia - Gets the inertia from a factored matrix 9054 9055 Collective 9056 9057 Input Parameter: 9058 . mat - the matrix 9059 9060 Output Parameters: 9061 + nneg - number of negative eigenvalues 9062 . nzero - number of zero eigenvalues 9063 - npos - number of positive eigenvalues 9064 9065 Level: advanced 9066 9067 Note: 9068 Matrix must have been factored by `MatCholeskyFactor()` 9069 9070 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()` 9071 @*/ 9072 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos) 9073 { 9074 PetscFunctionBegin; 9075 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9076 PetscValidType(mat, 1); 9077 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9078 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled"); 9079 PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos); 9080 PetscFunctionReturn(PETSC_SUCCESS); 9081 } 9082 9083 /*@C 9084 MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors 9085 9086 Neighbor-wise Collective 9087 9088 Input Parameters: 9089 + mat - the factored matrix obtained with `MatGetFactor()` 9090 - b - the right-hand-side vectors 9091 9092 Output Parameter: 9093 . x - the result vectors 9094 9095 Level: developer 9096 9097 Note: 9098 The vectors `b` and `x` cannot be the same. I.e., one cannot 9099 call `MatSolves`(A,x,x). 9100 9101 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()` 9102 @*/ 9103 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x) 9104 { 9105 PetscFunctionBegin; 9106 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9107 PetscValidType(mat, 1); 9108 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 9109 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9110 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 9111 9112 MatCheckPreallocated(mat, 1); 9113 PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0)); 9114 PetscUseTypeMethod(mat, solves, b, x); 9115 PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0)); 9116 PetscFunctionReturn(PETSC_SUCCESS); 9117 } 9118 9119 /*@ 9120 MatIsSymmetric - Test whether a matrix is symmetric 9121 9122 Collective 9123 9124 Input Parameters: 9125 + A - the matrix to test 9126 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose) 9127 9128 Output Parameter: 9129 . flg - the result 9130 9131 Level: intermediate 9132 9133 Notes: 9134 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9135 9136 If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()` 9137 9138 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9139 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9140 9141 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`, 9142 `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL` 9143 @*/ 9144 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg) 9145 { 9146 PetscFunctionBegin; 9147 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9148 PetscValidBoolPointer(flg, 3); 9149 9150 if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE; 9151 else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE; 9152 else { 9153 PetscUseTypeMethod(A, issymmetric, tol, flg); 9154 if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg)); 9155 } 9156 PetscFunctionReturn(PETSC_SUCCESS); 9157 } 9158 9159 /*@ 9160 MatIsHermitian - Test whether a matrix is Hermitian 9161 9162 Collective 9163 9164 Input Parameters: 9165 + A - the matrix to test 9166 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian) 9167 9168 Output Parameter: 9169 . flg - the result 9170 9171 Level: intermediate 9172 9173 Notes: 9174 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9175 9176 If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()` 9177 9178 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9179 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`) 9180 9181 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, 9182 `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL` 9183 @*/ 9184 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg) 9185 { 9186 PetscFunctionBegin; 9187 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9188 PetscValidBoolPointer(flg, 3); 9189 9190 if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE; 9191 else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE; 9192 else { 9193 PetscUseTypeMethod(A, ishermitian, tol, flg); 9194 if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg)); 9195 } 9196 PetscFunctionReturn(PETSC_SUCCESS); 9197 } 9198 9199 /*@ 9200 MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state 9201 9202 Not Collective 9203 9204 Input Parameter: 9205 . A - the matrix to check 9206 9207 Output Parameters: 9208 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid) 9209 - flg - the result (only valid if set is `PETSC_TRUE`) 9210 9211 Level: advanced 9212 9213 Notes: 9214 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()` 9215 if you want it explicitly checked 9216 9217 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9218 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9219 9220 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9221 @*/ 9222 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9223 { 9224 PetscFunctionBegin; 9225 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9226 PetscValidBoolPointer(set, 2); 9227 PetscValidBoolPointer(flg, 3); 9228 if (A->symmetric != PETSC_BOOL3_UNKNOWN) { 9229 *set = PETSC_TRUE; 9230 *flg = PetscBool3ToBool(A->symmetric); 9231 } else { 9232 *set = PETSC_FALSE; 9233 } 9234 PetscFunctionReturn(PETSC_SUCCESS); 9235 } 9236 9237 /*@ 9238 MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state 9239 9240 Not Collective 9241 9242 Input Parameter: 9243 . A - the matrix to check 9244 9245 Output Parameters: 9246 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid) 9247 - flg - the result (only valid if set is `PETSC_TRUE`) 9248 9249 Level: advanced 9250 9251 Notes: 9252 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). 9253 9254 One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD 9255 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`) 9256 9257 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9258 @*/ 9259 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg) 9260 { 9261 PetscFunctionBegin; 9262 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9263 PetscValidBoolPointer(set, 2); 9264 PetscValidBoolPointer(flg, 3); 9265 if (A->spd != PETSC_BOOL3_UNKNOWN) { 9266 *set = PETSC_TRUE; 9267 *flg = PetscBool3ToBool(A->spd); 9268 } else { 9269 *set = PETSC_FALSE; 9270 } 9271 PetscFunctionReturn(PETSC_SUCCESS); 9272 } 9273 9274 /*@ 9275 MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state 9276 9277 Not Collective 9278 9279 Input Parameter: 9280 . A - the matrix to check 9281 9282 Output Parameters: 9283 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid) 9284 - flg - the result (only valid if set is `PETSC_TRUE`) 9285 9286 Level: advanced 9287 9288 Notes: 9289 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()` 9290 if you want it explicitly checked 9291 9292 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9293 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9294 9295 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()` 9296 @*/ 9297 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg) 9298 { 9299 PetscFunctionBegin; 9300 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9301 PetscValidBoolPointer(set, 2); 9302 PetscValidBoolPointer(flg, 3); 9303 if (A->hermitian != PETSC_BOOL3_UNKNOWN) { 9304 *set = PETSC_TRUE; 9305 *flg = PetscBool3ToBool(A->hermitian); 9306 } else { 9307 *set = PETSC_FALSE; 9308 } 9309 PetscFunctionReturn(PETSC_SUCCESS); 9310 } 9311 9312 /*@ 9313 MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric 9314 9315 Collective 9316 9317 Input Parameter: 9318 . A - the matrix to test 9319 9320 Output Parameter: 9321 . flg - the result 9322 9323 Level: intermediate 9324 9325 Notes: 9326 If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()` 9327 9328 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 9329 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9330 9331 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()` 9332 @*/ 9333 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg) 9334 { 9335 PetscFunctionBegin; 9336 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9337 PetscValidBoolPointer(flg, 2); 9338 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9339 *flg = PetscBool3ToBool(A->structurally_symmetric); 9340 } else { 9341 PetscUseTypeMethod(A, isstructurallysymmetric, flg); 9342 PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg)); 9343 } 9344 PetscFunctionReturn(PETSC_SUCCESS); 9345 } 9346 9347 /*@ 9348 MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state 9349 9350 Not Collective 9351 9352 Input Parameter: 9353 . A - the matrix to check 9354 9355 Output Parameters: 9356 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid) 9357 - flg - the result (only valid if set is PETSC_TRUE) 9358 9359 Level: advanced 9360 9361 Notes: 9362 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 9363 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9364 9365 Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation) 9366 9367 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9368 @*/ 9369 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9370 { 9371 PetscFunctionBegin; 9372 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9373 PetscValidBoolPointer(set, 2); 9374 PetscValidBoolPointer(flg, 3); 9375 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9376 *set = PETSC_TRUE; 9377 *flg = PetscBool3ToBool(A->structurally_symmetric); 9378 } else { 9379 *set = PETSC_FALSE; 9380 } 9381 PetscFunctionReturn(PETSC_SUCCESS); 9382 } 9383 9384 /*@ 9385 MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need 9386 to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process 9387 9388 Not Collective 9389 9390 Input Parameter: 9391 . mat - the matrix 9392 9393 Output Parameters: 9394 + nstash - the size of the stash 9395 . reallocs - the number of additional mallocs incurred. 9396 . bnstash - the size of the block stash 9397 - breallocs - the number of additional mallocs incurred.in the block stash 9398 9399 Level: advanced 9400 9401 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()` 9402 @*/ 9403 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs) 9404 { 9405 PetscFunctionBegin; 9406 PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs)); 9407 PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs)); 9408 PetscFunctionReturn(PETSC_SUCCESS); 9409 } 9410 9411 /*@C 9412 MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same 9413 parallel layout, `PetscLayout` for rows and columns 9414 9415 Collective 9416 9417 Input Parameter: 9418 . mat - the matrix 9419 9420 Output Parameters: 9421 + right - (optional) vector that the matrix can be multiplied against 9422 - left - (optional) vector that the matrix vector product can be stored in 9423 9424 Level: advanced 9425 9426 Notes: 9427 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()`. 9428 9429 These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed 9430 9431 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()` 9432 @*/ 9433 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left) 9434 { 9435 PetscFunctionBegin; 9436 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9437 PetscValidType(mat, 1); 9438 if (mat->ops->getvecs) { 9439 PetscUseTypeMethod(mat, getvecs, right, left); 9440 } else { 9441 if (right) { 9442 PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup"); 9443 PetscCall(VecCreateWithLayout_Private(mat->cmap, right)); 9444 PetscCall(VecSetType(*right, mat->defaultvectype)); 9445 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9446 if (mat->boundtocpu && mat->bindingpropagates) { 9447 PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE)); 9448 PetscCall(VecBindToCPU(*right, PETSC_TRUE)); 9449 } 9450 #endif 9451 } 9452 if (left) { 9453 PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup"); 9454 PetscCall(VecCreateWithLayout_Private(mat->rmap, left)); 9455 PetscCall(VecSetType(*left, mat->defaultvectype)); 9456 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9457 if (mat->boundtocpu && mat->bindingpropagates) { 9458 PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE)); 9459 PetscCall(VecBindToCPU(*left, PETSC_TRUE)); 9460 } 9461 #endif 9462 } 9463 } 9464 PetscFunctionReturn(PETSC_SUCCESS); 9465 } 9466 9467 /*@C 9468 MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure 9469 with default values. 9470 9471 Not Collective 9472 9473 Input Parameter: 9474 . info - the `MatFactorInfo` data structure 9475 9476 Level: developer 9477 9478 Notes: 9479 The solvers are generally used through the `KSP` and `PC` objects, for example 9480 `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC` 9481 9482 Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed 9483 9484 Developer Notes: 9485 The Fortran interface is not autogenerated as the 9486 interface definition cannot be generated correctly [due to `MatFactorInfo`] 9487 9488 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo` 9489 @*/ 9490 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info) 9491 { 9492 PetscFunctionBegin; 9493 PetscCall(PetscMemzero(info, sizeof(MatFactorInfo))); 9494 PetscFunctionReturn(PETSC_SUCCESS); 9495 } 9496 9497 /*@ 9498 MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed 9499 9500 Collective 9501 9502 Input Parameters: 9503 + mat - the factored matrix 9504 - is - the index set defining the Schur indices (0-based) 9505 9506 Level: advanced 9507 9508 Notes: 9509 Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system. 9510 9511 You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call. 9512 9513 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9514 9515 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`, 9516 `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9517 @*/ 9518 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is) 9519 { 9520 PetscErrorCode (*f)(Mat, IS); 9521 9522 PetscFunctionBegin; 9523 PetscValidType(mat, 1); 9524 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9525 PetscValidType(is, 2); 9526 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 9527 PetscCheckSameComm(mat, 1, is, 2); 9528 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 9529 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f)); 9530 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO"); 9531 PetscCall(MatDestroy(&mat->schur)); 9532 PetscCall((*f)(mat, is)); 9533 PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created"); 9534 PetscFunctionReturn(PETSC_SUCCESS); 9535 } 9536 9537 /*@ 9538 MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step 9539 9540 Logically Collective 9541 9542 Input Parameters: 9543 + F - the factored matrix obtained by calling `MatGetFactor()` 9544 . S - location where to return the Schur complement, can be `NULL` 9545 - status - the status of the Schur complement matrix, can be `NULL` 9546 9547 Level: advanced 9548 9549 Notes: 9550 You must call `MatFactorSetSchurIS()` before calling this routine. 9551 9552 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9553 9554 The routine provides a copy of the Schur matrix stored within the solver data structures. 9555 The caller must destroy the object when it is no longer needed. 9556 If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse. 9557 9558 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) 9559 9560 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9561 9562 Developer Notes: 9563 The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc 9564 matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix. 9565 9566 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9567 @*/ 9568 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9569 { 9570 PetscFunctionBegin; 9571 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9572 if (S) PetscValidPointer(S, 2); 9573 if (status) PetscValidPointer(status, 3); 9574 if (S) { 9575 PetscErrorCode (*f)(Mat, Mat *); 9576 9577 PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f)); 9578 if (f) { 9579 PetscCall((*f)(F, S)); 9580 } else { 9581 PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S)); 9582 } 9583 } 9584 if (status) *status = F->schur_status; 9585 PetscFunctionReturn(PETSC_SUCCESS); 9586 } 9587 9588 /*@ 9589 MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix 9590 9591 Logically Collective 9592 9593 Input Parameters: 9594 + F - the factored matrix obtained by calling `MatGetFactor()` 9595 . S - location where to return the Schur complement, can be `NULL` 9596 - status - the status of the Schur complement matrix, can be `NULL` 9597 9598 Level: advanced 9599 9600 Notes: 9601 You must call `MatFactorSetSchurIS()` before calling this routine. 9602 9603 Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS` 9604 9605 The routine returns a the Schur Complement stored within the data structures of the solver. 9606 9607 If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement. 9608 9609 The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed. 9610 9611 Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix 9612 9613 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9614 9615 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9616 @*/ 9617 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9618 { 9619 PetscFunctionBegin; 9620 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9621 if (S) PetscValidPointer(S, 2); 9622 if (status) PetscValidPointer(status, 3); 9623 if (S) *S = F->schur; 9624 if (status) *status = F->schur_status; 9625 PetscFunctionReturn(PETSC_SUCCESS); 9626 } 9627 9628 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F) 9629 { 9630 Mat S = F->schur; 9631 9632 PetscFunctionBegin; 9633 switch (F->schur_status) { 9634 case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through 9635 case MAT_FACTOR_SCHUR_INVERTED: 9636 if (S) { 9637 S->ops->solve = NULL; 9638 S->ops->matsolve = NULL; 9639 S->ops->solvetranspose = NULL; 9640 S->ops->matsolvetranspose = NULL; 9641 S->ops->solveadd = NULL; 9642 S->ops->solvetransposeadd = NULL; 9643 S->factortype = MAT_FACTOR_NONE; 9644 PetscCall(PetscFree(S->solvertype)); 9645 } 9646 case MAT_FACTOR_SCHUR_FACTORED: // fall-through 9647 break; 9648 default: 9649 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9650 } 9651 PetscFunctionReturn(PETSC_SUCCESS); 9652 } 9653 9654 /*@ 9655 MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()` 9656 9657 Logically Collective 9658 9659 Input Parameters: 9660 + F - the factored matrix obtained by calling `MatGetFactor()` 9661 . S - location where the Schur complement is stored 9662 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`) 9663 9664 Level: advanced 9665 9666 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9667 @*/ 9668 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status) 9669 { 9670 PetscFunctionBegin; 9671 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9672 if (S) { 9673 PetscValidHeaderSpecific(*S, MAT_CLASSID, 2); 9674 *S = NULL; 9675 } 9676 F->schur_status = status; 9677 PetscCall(MatFactorUpdateSchurStatus_Private(F)); 9678 PetscFunctionReturn(PETSC_SUCCESS); 9679 } 9680 9681 /*@ 9682 MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step 9683 9684 Logically Collective 9685 9686 Input Parameters: 9687 + F - the factored matrix obtained by calling `MatGetFactor()` 9688 . rhs - location where the right hand side of the Schur complement system is stored 9689 - sol - location where the solution of the Schur complement system has to be returned 9690 9691 Level: advanced 9692 9693 Notes: 9694 The sizes of the vectors should match the size of the Schur complement 9695 9696 Must be called after `MatFactorSetSchurIS()` 9697 9698 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()` 9699 @*/ 9700 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol) 9701 { 9702 PetscFunctionBegin; 9703 PetscValidType(F, 1); 9704 PetscValidType(rhs, 2); 9705 PetscValidType(sol, 3); 9706 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9707 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9708 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9709 PetscCheckSameComm(F, 1, rhs, 2); 9710 PetscCheckSameComm(F, 1, sol, 3); 9711 PetscCall(MatFactorFactorizeSchurComplement(F)); 9712 switch (F->schur_status) { 9713 case MAT_FACTOR_SCHUR_FACTORED: 9714 PetscCall(MatSolveTranspose(F->schur, rhs, sol)); 9715 break; 9716 case MAT_FACTOR_SCHUR_INVERTED: 9717 PetscCall(MatMultTranspose(F->schur, rhs, sol)); 9718 break; 9719 default: 9720 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9721 } 9722 PetscFunctionReturn(PETSC_SUCCESS); 9723 } 9724 9725 /*@ 9726 MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step 9727 9728 Logically Collective 9729 9730 Input Parameters: 9731 + F - the factored matrix obtained by calling `MatGetFactor()` 9732 . rhs - location where the right hand side of the Schur complement system is stored 9733 - sol - location where the solution of the Schur complement system has to be returned 9734 9735 Level: advanced 9736 9737 Notes: 9738 The sizes of the vectors should match the size of the Schur complement 9739 9740 Must be called after `MatFactorSetSchurIS()` 9741 9742 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()` 9743 @*/ 9744 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol) 9745 { 9746 PetscFunctionBegin; 9747 PetscValidType(F, 1); 9748 PetscValidType(rhs, 2); 9749 PetscValidType(sol, 3); 9750 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9751 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9752 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9753 PetscCheckSameComm(F, 1, rhs, 2); 9754 PetscCheckSameComm(F, 1, sol, 3); 9755 PetscCall(MatFactorFactorizeSchurComplement(F)); 9756 switch (F->schur_status) { 9757 case MAT_FACTOR_SCHUR_FACTORED: 9758 PetscCall(MatSolve(F->schur, rhs, sol)); 9759 break; 9760 case MAT_FACTOR_SCHUR_INVERTED: 9761 PetscCall(MatMult(F->schur, rhs, sol)); 9762 break; 9763 default: 9764 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9765 } 9766 PetscFunctionReturn(PETSC_SUCCESS); 9767 } 9768 9769 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat); 9770 #if PetscDefined(HAVE_CUDA) 9771 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat); 9772 #endif 9773 9774 /* Schur status updated in the interface */ 9775 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F) 9776 { 9777 Mat S = F->schur; 9778 9779 PetscFunctionBegin; 9780 if (S) { 9781 PetscMPIInt size; 9782 PetscBool isdense, isdensecuda; 9783 9784 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size)); 9785 PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented"); 9786 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense)); 9787 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda)); 9788 PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name); 9789 PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0)); 9790 if (isdense) { 9791 PetscCall(MatSeqDenseInvertFactors_Private(S)); 9792 } else if (isdensecuda) { 9793 #if defined(PETSC_HAVE_CUDA) 9794 PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S)); 9795 #endif 9796 } 9797 // HIP?????????????? 9798 PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0)); 9799 } 9800 PetscFunctionReturn(PETSC_SUCCESS); 9801 } 9802 9803 /*@ 9804 MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step 9805 9806 Logically Collective 9807 9808 Input Parameter: 9809 . F - the factored matrix obtained by calling `MatGetFactor()` 9810 9811 Level: advanced 9812 9813 Notes: 9814 Must be called after `MatFactorSetSchurIS()`. 9815 9816 Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it. 9817 9818 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()` 9819 @*/ 9820 PetscErrorCode MatFactorInvertSchurComplement(Mat F) 9821 { 9822 PetscFunctionBegin; 9823 PetscValidType(F, 1); 9824 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9825 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS); 9826 PetscCall(MatFactorFactorizeSchurComplement(F)); 9827 PetscCall(MatFactorInvertSchurComplement_Private(F)); 9828 F->schur_status = MAT_FACTOR_SCHUR_INVERTED; 9829 PetscFunctionReturn(PETSC_SUCCESS); 9830 } 9831 9832 /*@ 9833 MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step 9834 9835 Logically Collective 9836 9837 Input Parameter: 9838 . F - the factored matrix obtained by calling `MatGetFactor()` 9839 9840 Level: advanced 9841 9842 Note: 9843 Must be called after `MatFactorSetSchurIS()` 9844 9845 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()` 9846 @*/ 9847 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F) 9848 { 9849 MatFactorInfo info; 9850 9851 PetscFunctionBegin; 9852 PetscValidType(F, 1); 9853 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9854 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS); 9855 PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0)); 9856 PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo))); 9857 if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */ 9858 PetscCall(MatCholeskyFactor(F->schur, NULL, &info)); 9859 } else { 9860 PetscCall(MatLUFactor(F->schur, NULL, NULL, &info)); 9861 } 9862 PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0)); 9863 F->schur_status = MAT_FACTOR_SCHUR_FACTORED; 9864 PetscFunctionReturn(PETSC_SUCCESS); 9865 } 9866 9867 /*@ 9868 MatPtAP - Creates the matrix product C = P^T * A * P 9869 9870 Neighbor-wise Collective 9871 9872 Input Parameters: 9873 + A - the matrix 9874 . P - the projection matrix 9875 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9876 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate 9877 if the result is a dense matrix this is irrelevant 9878 9879 Output Parameter: 9880 . C - the product matrix 9881 9882 Level: intermediate 9883 9884 Notes: 9885 C will be created and must be destroyed by the user with `MatDestroy()`. 9886 9887 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9888 9889 Developer Notes: 9890 For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`. 9891 9892 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()` 9893 @*/ 9894 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C) 9895 { 9896 PetscFunctionBegin; 9897 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 9898 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9899 9900 if (scall == MAT_INITIAL_MATRIX) { 9901 PetscCall(MatProductCreate(A, P, NULL, C)); 9902 PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP)); 9903 PetscCall(MatProductSetAlgorithm(*C, "default")); 9904 PetscCall(MatProductSetFill(*C, fill)); 9905 9906 (*C)->product->api_user = PETSC_TRUE; 9907 PetscCall(MatProductSetFromOptions(*C)); 9908 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); 9909 PetscCall(MatProductSymbolic(*C)); 9910 } else { /* scall == MAT_REUSE_MATRIX */ 9911 PetscCall(MatProductReplaceMats(A, P, NULL, *C)); 9912 } 9913 9914 PetscCall(MatProductNumeric(*C)); 9915 (*C)->symmetric = A->symmetric; 9916 (*C)->spd = A->spd; 9917 PetscFunctionReturn(PETSC_SUCCESS); 9918 } 9919 9920 /*@ 9921 MatRARt - Creates the matrix product C = R * A * R^T 9922 9923 Neighbor-wise Collective 9924 9925 Input Parameters: 9926 + A - the matrix 9927 . R - the projection matrix 9928 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9929 - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate 9930 if the result is a dense matrix this is irrelevant 9931 9932 Output Parameter: 9933 . C - the product matrix 9934 9935 Level: intermediate 9936 9937 Notes: 9938 C will be created and must be destroyed by the user with `MatDestroy()`. 9939 9940 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9941 9942 This routine is currently only implemented for pairs of `MATAIJ` matrices and classes 9943 which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes, 9944 parallel MatRARt is implemented via explicit transpose of R, which could be very expensive. 9945 We recommend using MatPtAP(). 9946 9947 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()` 9948 @*/ 9949 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C) 9950 { 9951 PetscFunctionBegin; 9952 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 9953 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9954 9955 if (scall == MAT_INITIAL_MATRIX) { 9956 PetscCall(MatProductCreate(A, R, NULL, C)); 9957 PetscCall(MatProductSetType(*C, MATPRODUCT_RARt)); 9958 PetscCall(MatProductSetAlgorithm(*C, "default")); 9959 PetscCall(MatProductSetFill(*C, fill)); 9960 9961 (*C)->product->api_user = PETSC_TRUE; 9962 PetscCall(MatProductSetFromOptions(*C)); 9963 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); 9964 PetscCall(MatProductSymbolic(*C)); 9965 } else { /* scall == MAT_REUSE_MATRIX */ 9966 PetscCall(MatProductReplaceMats(A, R, NULL, *C)); 9967 } 9968 9969 PetscCall(MatProductNumeric(*C)); 9970 if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 9971 PetscFunctionReturn(PETSC_SUCCESS); 9972 } 9973 9974 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C) 9975 { 9976 PetscFunctionBegin; 9977 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9978 9979 if (scall == MAT_INITIAL_MATRIX) { 9980 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype])); 9981 PetscCall(MatProductCreate(A, B, NULL, C)); 9982 PetscCall(MatProductSetType(*C, ptype)); 9983 PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT)); 9984 PetscCall(MatProductSetFill(*C, fill)); 9985 9986 (*C)->product->api_user = PETSC_TRUE; 9987 PetscCall(MatProductSetFromOptions(*C)); 9988 PetscCall(MatProductSymbolic(*C)); 9989 } else { /* scall == MAT_REUSE_MATRIX */ 9990 Mat_Product *product = (*C)->product; 9991 PetscBool isdense; 9992 9993 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, "")); 9994 if (isdense && product && product->type != ptype) { 9995 PetscCall(MatProductClear(*C)); 9996 product = NULL; 9997 } 9998 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype])); 9999 if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */ 10000 PetscCheck(isdense, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first"); 10001 PetscCall(MatProductCreate_Private(A, B, NULL, *C)); 10002 product = (*C)->product; 10003 product->fill = fill; 10004 product->api_user = PETSC_TRUE; 10005 product->clear = PETSC_TRUE; 10006 10007 PetscCall(MatProductSetType(*C, ptype)); 10008 PetscCall(MatProductSetFromOptions(*C)); 10009 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); 10010 PetscCall(MatProductSymbolic(*C)); 10011 } else { /* user may change input matrices A or B when REUSE */ 10012 PetscCall(MatProductReplaceMats(A, B, NULL, *C)); 10013 } 10014 } 10015 PetscCall(MatProductNumeric(*C)); 10016 PetscFunctionReturn(PETSC_SUCCESS); 10017 } 10018 10019 /*@ 10020 MatMatMult - Performs matrix-matrix multiplication C=A*B. 10021 10022 Neighbor-wise Collective 10023 10024 Input Parameters: 10025 + A - the left matrix 10026 . B - the right matrix 10027 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10028 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate 10029 if the result is a dense matrix this is irrelevant 10030 10031 Output Parameter: 10032 . C - the product matrix 10033 10034 Notes: 10035 Unless scall is `MAT_REUSE_MATRIX` C will be created. 10036 10037 `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 10038 call to this function with `MAT_INITIAL_MATRIX`. 10039 10040 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed. 10041 10042 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`, 10043 rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse. 10044 10045 Example of Usage: 10046 .vb 10047 MatProductCreate(A,B,NULL,&C); 10048 MatProductSetType(C,MATPRODUCT_AB); 10049 MatProductSymbolic(C); 10050 MatProductNumeric(C); // compute C=A * B 10051 MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1 10052 MatProductNumeric(C); 10053 MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1 10054 MatProductNumeric(C); 10055 .ve 10056 10057 Level: intermediate 10058 10059 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()` 10060 @*/ 10061 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10062 { 10063 PetscFunctionBegin; 10064 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C)); 10065 PetscFunctionReturn(PETSC_SUCCESS); 10066 } 10067 10068 /*@ 10069 MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T. 10070 10071 Neighbor-wise Collective 10072 10073 Input Parameters: 10074 + A - the left matrix 10075 . B - the right matrix 10076 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10077 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 10078 10079 Output Parameter: 10080 . C - the product matrix 10081 10082 Level: intermediate 10083 10084 Notes: 10085 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10086 10087 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call 10088 10089 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10090 actually needed. 10091 10092 This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class, 10093 and for pairs of `MATMPIDENSE` matrices. 10094 10095 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt` 10096 10097 Options Database Keys: 10098 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the 10099 first redundantly copies the transposed B matrix on each process and requires O(log P) communication complexity; 10100 the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity. 10101 10102 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType` 10103 @*/ 10104 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10105 { 10106 PetscFunctionBegin; 10107 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C)); 10108 if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10109 PetscFunctionReturn(PETSC_SUCCESS); 10110 } 10111 10112 /*@ 10113 MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B. 10114 10115 Neighbor-wise Collective 10116 10117 Input Parameters: 10118 + A - the left matrix 10119 . B - the right matrix 10120 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10121 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 10122 10123 Output Parameter: 10124 . C - the product matrix 10125 10126 Level: intermediate 10127 10128 Notes: 10129 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10130 10131 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call. 10132 10133 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB` 10134 10135 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10136 actually needed. 10137 10138 This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes 10139 which inherit from `MATSEQAIJ`. C will be of the same type as the input matrices. 10140 10141 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()` 10142 @*/ 10143 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10144 { 10145 PetscFunctionBegin; 10146 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C)); 10147 PetscFunctionReturn(PETSC_SUCCESS); 10148 } 10149 10150 /*@ 10151 MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C. 10152 10153 Neighbor-wise Collective 10154 10155 Input Parameters: 10156 + A - the left matrix 10157 . B - the middle matrix 10158 . C - the right matrix 10159 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10160 - 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 10161 if the result is a dense matrix this is irrelevant 10162 10163 Output Parameter: 10164 . D - the product matrix 10165 10166 Level: intermediate 10167 10168 Notes: 10169 Unless scall is `MAT_REUSE_MATRIX` D will be created. 10170 10171 `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call 10172 10173 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC` 10174 10175 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10176 actually needed. 10177 10178 If you have many matrices with the same non-zero structure to multiply, you 10179 should use `MAT_REUSE_MATRIX` in all calls but the first 10180 10181 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()` 10182 @*/ 10183 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D) 10184 { 10185 PetscFunctionBegin; 10186 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6); 10187 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10188 10189 if (scall == MAT_INITIAL_MATRIX) { 10190 PetscCall(MatProductCreate(A, B, C, D)); 10191 PetscCall(MatProductSetType(*D, MATPRODUCT_ABC)); 10192 PetscCall(MatProductSetAlgorithm(*D, "default")); 10193 PetscCall(MatProductSetFill(*D, fill)); 10194 10195 (*D)->product->api_user = PETSC_TRUE; 10196 PetscCall(MatProductSetFromOptions(*D)); 10197 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, 10198 ((PetscObject)C)->type_name); 10199 PetscCall(MatProductSymbolic(*D)); 10200 } else { /* user may change input matrices when REUSE */ 10201 PetscCall(MatProductReplaceMats(A, B, C, *D)); 10202 } 10203 PetscCall(MatProductNumeric(*D)); 10204 PetscFunctionReturn(PETSC_SUCCESS); 10205 } 10206 10207 /*@ 10208 MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators. 10209 10210 Collective 10211 10212 Input Parameters: 10213 + mat - the matrix 10214 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices) 10215 . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used) 10216 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10217 10218 Output Parameter: 10219 . matredundant - redundant matrix 10220 10221 Level: advanced 10222 10223 Notes: 10224 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 10225 original matrix has not changed from that last call to MatCreateRedundantMatrix(). 10226 10227 This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before 10228 calling it. 10229 10230 `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be. 10231 10232 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm` 10233 @*/ 10234 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant) 10235 { 10236 MPI_Comm comm; 10237 PetscMPIInt size; 10238 PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs; 10239 Mat_Redundant *redund = NULL; 10240 PetscSubcomm psubcomm = NULL; 10241 MPI_Comm subcomm_in = subcomm; 10242 Mat *matseq; 10243 IS isrow, iscol; 10244 PetscBool newsubcomm = PETSC_FALSE; 10245 10246 PetscFunctionBegin; 10247 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10248 if (nsubcomm && reuse == MAT_REUSE_MATRIX) { 10249 PetscValidPointer(*matredundant, 5); 10250 PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5); 10251 } 10252 10253 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10254 if (size == 1 || nsubcomm == 1) { 10255 if (reuse == MAT_INITIAL_MATRIX) { 10256 PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant)); 10257 } else { 10258 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"); 10259 PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN)); 10260 } 10261 PetscFunctionReturn(PETSC_SUCCESS); 10262 } 10263 10264 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10265 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10266 MatCheckPreallocated(mat, 1); 10267 10268 PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0)); 10269 if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */ 10270 /* create psubcomm, then get subcomm */ 10271 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10272 PetscCallMPI(MPI_Comm_size(comm, &size)); 10273 PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size); 10274 10275 PetscCall(PetscSubcommCreate(comm, &psubcomm)); 10276 PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm)); 10277 PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS)); 10278 PetscCall(PetscSubcommSetFromOptions(psubcomm)); 10279 PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL)); 10280 newsubcomm = PETSC_TRUE; 10281 PetscCall(PetscSubcommDestroy(&psubcomm)); 10282 } 10283 10284 /* get isrow, iscol and a local sequential matrix matseq[0] */ 10285 if (reuse == MAT_INITIAL_MATRIX) { 10286 mloc_sub = PETSC_DECIDE; 10287 nloc_sub = PETSC_DECIDE; 10288 if (bs < 1) { 10289 PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M)); 10290 PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N)); 10291 } else { 10292 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M)); 10293 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N)); 10294 } 10295 PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm)); 10296 rstart = rend - mloc_sub; 10297 PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow)); 10298 PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol)); 10299 } else { /* reuse == MAT_REUSE_MATRIX */ 10300 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"); 10301 /* retrieve subcomm */ 10302 PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm)); 10303 redund = (*matredundant)->redundant; 10304 isrow = redund->isrow; 10305 iscol = redund->iscol; 10306 matseq = redund->matseq; 10307 } 10308 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq)); 10309 10310 /* get matredundant over subcomm */ 10311 if (reuse == MAT_INITIAL_MATRIX) { 10312 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant)); 10313 10314 /* create a supporting struct and attach it to C for reuse */ 10315 PetscCall(PetscNew(&redund)); 10316 (*matredundant)->redundant = redund; 10317 redund->isrow = isrow; 10318 redund->iscol = iscol; 10319 redund->matseq = matseq; 10320 if (newsubcomm) { 10321 redund->subcomm = subcomm; 10322 } else { 10323 redund->subcomm = MPI_COMM_NULL; 10324 } 10325 } else { 10326 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant)); 10327 } 10328 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 10329 if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) { 10330 PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE)); 10331 PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE)); 10332 } 10333 #endif 10334 PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0)); 10335 PetscFunctionReturn(PETSC_SUCCESS); 10336 } 10337 10338 /*@C 10339 MatGetMultiProcBlock - Create multiple 'parallel submatrices' from 10340 a given `Mat`. Each submatrix can span multiple procs. 10341 10342 Collective 10343 10344 Input Parameters: 10345 + mat - the matrix 10346 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))` 10347 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10348 10349 Output Parameter: 10350 . subMat - parallel sub-matrices each spanning a given `subcomm` 10351 10352 Level: advanced 10353 10354 Notes: 10355 The submatrix partition across processors is dictated by `subComm` a 10356 communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm` 10357 is not restricted to be grouped with consecutive original ranks. 10358 10359 Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices 10360 map directly to the layout of the original matrix [wrt the local 10361 row,col partitioning]. So the original 'DiagonalMat' naturally maps 10362 into the 'DiagonalMat' of the `subMat`, hence it is used directly from 10363 the `subMat`. However the offDiagMat looses some columns - and this is 10364 reconstructed with `MatSetValues()` 10365 10366 This is used by `PCBJACOBI` when a single block spans multiple MPI processes. 10367 10368 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI` 10369 @*/ 10370 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) 10371 { 10372 PetscMPIInt commsize, subCommSize; 10373 10374 PetscFunctionBegin; 10375 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize)); 10376 PetscCallMPI(MPI_Comm_size(subComm, &subCommSize)); 10377 PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize); 10378 10379 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"); 10380 PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10381 PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat); 10382 PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10383 PetscFunctionReturn(PETSC_SUCCESS); 10384 } 10385 10386 /*@ 10387 MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering 10388 10389 Not Collective 10390 10391 Input Parameters: 10392 + mat - matrix to extract local submatrix from 10393 . isrow - local row indices for submatrix 10394 - iscol - local column indices for submatrix 10395 10396 Output Parameter: 10397 . submat - the submatrix 10398 10399 Level: intermediate 10400 10401 Notes: 10402 `submat` should be disposed of with `MatRestoreLocalSubMatrix()`. 10403 10404 Depending on the format of `mat`, the returned submat may not implement `MatMult()`. Its communicator may be 10405 the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of `mat`'s. 10406 10407 `submat` always implements `MatSetValuesLocal()`. If `isrow` and `iscol` have the same block size, then 10408 `MatSetValuesBlockedLocal()` will also be implemented. 10409 10410 `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`. 10411 Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided. 10412 10413 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()` 10414 @*/ 10415 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10416 { 10417 PetscFunctionBegin; 10418 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10419 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10420 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10421 PetscCheckSameComm(isrow, 2, iscol, 3); 10422 PetscValidPointer(submat, 4); 10423 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call"); 10424 10425 if (mat->ops->getlocalsubmatrix) { 10426 PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat); 10427 } else { 10428 PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat)); 10429 } 10430 PetscFunctionReturn(PETSC_SUCCESS); 10431 } 10432 10433 /*@ 10434 MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()` 10435 10436 Not Collective 10437 10438 Input Parameters: 10439 + mat - matrix to extract local submatrix from 10440 . isrow - local row indices for submatrix 10441 . iscol - local column indices for submatrix 10442 - submat - the submatrix 10443 10444 Level: intermediate 10445 10446 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()` 10447 @*/ 10448 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10449 { 10450 PetscFunctionBegin; 10451 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10452 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10453 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10454 PetscCheckSameComm(isrow, 2, iscol, 3); 10455 PetscValidPointer(submat, 4); 10456 if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4); 10457 10458 if (mat->ops->restorelocalsubmatrix) { 10459 PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat); 10460 } else { 10461 PetscCall(MatDestroy(submat)); 10462 } 10463 *submat = NULL; 10464 PetscFunctionReturn(PETSC_SUCCESS); 10465 } 10466 10467 /*@ 10468 MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix 10469 10470 Collective 10471 10472 Input Parameter: 10473 . mat - the matrix 10474 10475 Output Parameter: 10476 . is - if any rows have zero diagonals this contains the list of them 10477 10478 Level: developer 10479 10480 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10481 @*/ 10482 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is) 10483 { 10484 PetscFunctionBegin; 10485 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10486 PetscValidType(mat, 1); 10487 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10488 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10489 10490 if (!mat->ops->findzerodiagonals) { 10491 Vec diag; 10492 const PetscScalar *a; 10493 PetscInt *rows; 10494 PetscInt rStart, rEnd, r, nrow = 0; 10495 10496 PetscCall(MatCreateVecs(mat, &diag, NULL)); 10497 PetscCall(MatGetDiagonal(mat, diag)); 10498 PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd)); 10499 PetscCall(VecGetArrayRead(diag, &a)); 10500 for (r = 0; r < rEnd - rStart; ++r) 10501 if (a[r] == 0.0) ++nrow; 10502 PetscCall(PetscMalloc1(nrow, &rows)); 10503 nrow = 0; 10504 for (r = 0; r < rEnd - rStart; ++r) 10505 if (a[r] == 0.0) rows[nrow++] = r + rStart; 10506 PetscCall(VecRestoreArrayRead(diag, &a)); 10507 PetscCall(VecDestroy(&diag)); 10508 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is)); 10509 } else { 10510 PetscUseTypeMethod(mat, findzerodiagonals, is); 10511 } 10512 PetscFunctionReturn(PETSC_SUCCESS); 10513 } 10514 10515 /*@ 10516 MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size) 10517 10518 Collective 10519 10520 Input Parameter: 10521 . mat - the matrix 10522 10523 Output Parameter: 10524 . is - contains the list of rows with off block diagonal entries 10525 10526 Level: developer 10527 10528 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10529 @*/ 10530 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is) 10531 { 10532 PetscFunctionBegin; 10533 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10534 PetscValidType(mat, 1); 10535 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10536 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10537 10538 PetscUseTypeMethod(mat, findoffblockdiagonalentries, is); 10539 PetscFunctionReturn(PETSC_SUCCESS); 10540 } 10541 10542 /*@C 10543 MatInvertBlockDiagonal - Inverts the block diagonal entries. 10544 10545 Collective; No Fortran Support 10546 10547 Input Parameter: 10548 . mat - the matrix 10549 10550 Output Parameter: 10551 . values - the block inverses in column major order (FORTRAN-like) 10552 10553 Level: advanced 10554 10555 Notes: 10556 The size of the blocks is determined by the block size of the matrix. 10557 10558 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10559 10560 The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size 10561 10562 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()` 10563 @*/ 10564 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values) 10565 { 10566 PetscFunctionBegin; 10567 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10568 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10569 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10570 PetscUseTypeMethod(mat, invertblockdiagonal, values); 10571 PetscFunctionReturn(PETSC_SUCCESS); 10572 } 10573 10574 /*@C 10575 MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries. 10576 10577 Collective; No Fortran Support 10578 10579 Input Parameters: 10580 + mat - the matrix 10581 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()` 10582 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()` 10583 10584 Output Parameter: 10585 . values - the block inverses in column major order (FORTRAN-like) 10586 10587 Level: advanced 10588 10589 Notes: 10590 Use `MatInvertBlockDiagonal()` if all blocks have the same size 10591 10592 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10593 10594 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()` 10595 @*/ 10596 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values) 10597 { 10598 PetscFunctionBegin; 10599 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10600 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10601 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10602 PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values); 10603 PetscFunctionReturn(PETSC_SUCCESS); 10604 } 10605 10606 /*@ 10607 MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A 10608 10609 Collective 10610 10611 Input Parameters: 10612 + A - the matrix 10613 - C - matrix with inverted block diagonal of `A`. This matrix should be created and may have its type set. 10614 10615 Level: advanced 10616 10617 Note: 10618 The blocksize of the matrix is used to determine the blocks on the diagonal of `C` 10619 10620 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()` 10621 @*/ 10622 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C) 10623 { 10624 const PetscScalar *vals; 10625 PetscInt *dnnz; 10626 PetscInt m, rstart, rend, bs, i, j; 10627 10628 PetscFunctionBegin; 10629 PetscCall(MatInvertBlockDiagonal(A, &vals)); 10630 PetscCall(MatGetBlockSize(A, &bs)); 10631 PetscCall(MatGetLocalSize(A, &m, NULL)); 10632 PetscCall(MatSetLayouts(C, A->rmap, A->cmap)); 10633 PetscCall(PetscMalloc1(m / bs, &dnnz)); 10634 for (j = 0; j < m / bs; j++) dnnz[j] = 1; 10635 PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL)); 10636 PetscCall(PetscFree(dnnz)); 10637 PetscCall(MatGetOwnershipRange(C, &rstart, &rend)); 10638 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE)); 10639 for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES)); 10640 PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 10641 PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 10642 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE)); 10643 PetscFunctionReturn(PETSC_SUCCESS); 10644 } 10645 10646 /*@C 10647 MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created 10648 via `MatTransposeColoringCreate()`. 10649 10650 Collective 10651 10652 Input Parameter: 10653 . c - coloring context 10654 10655 Level: intermediate 10656 10657 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()` 10658 @*/ 10659 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c) 10660 { 10661 MatTransposeColoring matcolor = *c; 10662 10663 PetscFunctionBegin; 10664 if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS); 10665 if (--((PetscObject)matcolor)->refct > 0) { 10666 matcolor = NULL; 10667 PetscFunctionReturn(PETSC_SUCCESS); 10668 } 10669 10670 PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow)); 10671 PetscCall(PetscFree(matcolor->rows)); 10672 PetscCall(PetscFree(matcolor->den2sp)); 10673 PetscCall(PetscFree(matcolor->colorforcol)); 10674 PetscCall(PetscFree(matcolor->columns)); 10675 if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart)); 10676 PetscCall(PetscHeaderDestroy(c)); 10677 PetscFunctionReturn(PETSC_SUCCESS); 10678 } 10679 10680 /*@C 10681 MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which 10682 a `MatTransposeColoring` context has been created, computes a dense B^T by applying 10683 `MatTransposeColoring` to sparse B. 10684 10685 Collective 10686 10687 Input Parameters: 10688 + coloring - coloring context created with `MatTransposeColoringCreate()` 10689 - B - sparse matrix 10690 10691 Output Parameter: 10692 . Btdense - dense matrix B^T 10693 10694 Level: developer 10695 10696 Note: 10697 These are used internally for some implementations of `MatRARt()` 10698 10699 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()` 10700 @*/ 10701 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense) 10702 { 10703 PetscFunctionBegin; 10704 PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10705 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 10706 PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3); 10707 10708 PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense)); 10709 PetscFunctionReturn(PETSC_SUCCESS); 10710 } 10711 10712 /*@C 10713 MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which 10714 a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense 10715 in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix 10716 `Csp` from `Cden`. 10717 10718 Collective 10719 10720 Input Parameters: 10721 + matcoloring - coloring context created with `MatTransposeColoringCreate()` 10722 - Cden - matrix product of a sparse matrix and a dense matrix Btdense 10723 10724 Output Parameter: 10725 . Csp - sparse matrix 10726 10727 Level: developer 10728 10729 Note: 10730 These are used internally for some implementations of `MatRARt()` 10731 10732 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()` 10733 @*/ 10734 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp) 10735 { 10736 PetscFunctionBegin; 10737 PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10738 PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2); 10739 PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3); 10740 10741 PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp)); 10742 PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY)); 10743 PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY)); 10744 PetscFunctionReturn(PETSC_SUCCESS); 10745 } 10746 10747 /*@C 10748 MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T. 10749 10750 Collective 10751 10752 Input Parameters: 10753 + mat - the matrix product C 10754 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()` 10755 10756 Output Parameter: 10757 . color - the new coloring context 10758 10759 Level: intermediate 10760 10761 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`, 10762 `MatTransColoringApplyDenToSp()` 10763 @*/ 10764 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color) 10765 { 10766 MatTransposeColoring c; 10767 MPI_Comm comm; 10768 10769 PetscFunctionBegin; 10770 PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10771 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10772 PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL)); 10773 10774 c->ctype = iscoloring->ctype; 10775 PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c); 10776 10777 *color = c; 10778 PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10779 PetscFunctionReturn(PETSC_SUCCESS); 10780 } 10781 10782 /*@ 10783 MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the 10784 matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the 10785 same, otherwise it will be larger 10786 10787 Not Collective 10788 10789 Input Parameter: 10790 . mat - the matrix 10791 10792 Output Parameter: 10793 . state - the current state 10794 10795 Level: intermediate 10796 10797 Notes: 10798 You can only compare states from two different calls to the SAME matrix, you cannot compare calls between 10799 different matrices 10800 10801 Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix 10802 10803 Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers. 10804 10805 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()` 10806 @*/ 10807 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state) 10808 { 10809 PetscFunctionBegin; 10810 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10811 *state = mat->nonzerostate; 10812 PetscFunctionReturn(PETSC_SUCCESS); 10813 } 10814 10815 /*@ 10816 MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential 10817 matrices from each processor 10818 10819 Collective 10820 10821 Input Parameters: 10822 + comm - the communicators the parallel matrix will live on 10823 . seqmat - the input sequential matrices 10824 . n - number of local columns (or `PETSC_DECIDE`) 10825 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10826 10827 Output Parameter: 10828 . mpimat - the parallel matrix generated 10829 10830 Level: developer 10831 10832 Note: 10833 The number of columns of the matrix in EACH processor MUST be the same. 10834 10835 .seealso: [](ch_matrices), `Mat` 10836 @*/ 10837 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat) 10838 { 10839 PetscMPIInt size; 10840 10841 PetscFunctionBegin; 10842 PetscCallMPI(MPI_Comm_size(comm, &size)); 10843 if (size == 1) { 10844 if (reuse == MAT_INITIAL_MATRIX) { 10845 PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat)); 10846 } else { 10847 PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN)); 10848 } 10849 PetscFunctionReturn(PETSC_SUCCESS); 10850 } 10851 10852 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"); 10853 10854 PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0)); 10855 PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat)); 10856 PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0)); 10857 PetscFunctionReturn(PETSC_SUCCESS); 10858 } 10859 10860 /*@ 10861 MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI ranks' ownership ranges. 10862 10863 Collective 10864 10865 Input Parameters: 10866 + A - the matrix to create subdomains from 10867 - N - requested number of subdomains 10868 10869 Output Parameters: 10870 + n - number of subdomains resulting on this MPI process 10871 - iss - `IS` list with indices of subdomains on this MPI process 10872 10873 Level: advanced 10874 10875 Note: 10876 The number of subdomains must be smaller than the communicator size 10877 10878 .seealso: [](ch_matrices), `Mat`, `IS` 10879 @*/ 10880 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[]) 10881 { 10882 MPI_Comm comm, subcomm; 10883 PetscMPIInt size, rank, color; 10884 PetscInt rstart, rend, k; 10885 10886 PetscFunctionBegin; 10887 PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 10888 PetscCallMPI(MPI_Comm_size(comm, &size)); 10889 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 10890 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); 10891 *n = 1; 10892 k = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */ 10893 color = rank / k; 10894 PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm)); 10895 PetscCall(PetscMalloc1(1, iss)); 10896 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 10897 PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0])); 10898 PetscCallMPI(MPI_Comm_free(&subcomm)); 10899 PetscFunctionReturn(PETSC_SUCCESS); 10900 } 10901 10902 /*@ 10903 MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection. 10904 10905 If the interpolation and restriction operators are the same, uses `MatPtAP()`. 10906 If they are not the same, uses `MatMatMatMult()`. 10907 10908 Once the coarse grid problem is constructed, correct for interpolation operators 10909 that are not of full rank, which can legitimately happen in the case of non-nested 10910 geometric multigrid. 10911 10912 Input Parameters: 10913 + restrct - restriction operator 10914 . dA - fine grid matrix 10915 . interpolate - interpolation operator 10916 . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10917 - fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate 10918 10919 Output Parameter: 10920 . A - the Galerkin coarse matrix 10921 10922 Options Database Key: 10923 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used 10924 10925 Level: developer 10926 10927 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()` 10928 @*/ 10929 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A) 10930 { 10931 IS zerorows; 10932 Vec diag; 10933 10934 PetscFunctionBegin; 10935 PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10936 /* Construct the coarse grid matrix */ 10937 if (interpolate == restrct) { 10938 PetscCall(MatPtAP(dA, interpolate, reuse, fill, A)); 10939 } else { 10940 PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A)); 10941 } 10942 10943 /* If the interpolation matrix is not of full rank, A will have zero rows. 10944 This can legitimately happen in the case of non-nested geometric multigrid. 10945 In that event, we set the rows of the matrix to the rows of the identity, 10946 ignoring the equations (as the RHS will also be zero). */ 10947 10948 PetscCall(MatFindZeroRows(*A, &zerorows)); 10949 10950 if (zerorows != NULL) { /* if there are any zero rows */ 10951 PetscCall(MatCreateVecs(*A, &diag, NULL)); 10952 PetscCall(MatGetDiagonal(*A, diag)); 10953 PetscCall(VecISSet(diag, zerorows, 1.0)); 10954 PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES)); 10955 PetscCall(VecDestroy(&diag)); 10956 PetscCall(ISDestroy(&zerorows)); 10957 } 10958 PetscFunctionReturn(PETSC_SUCCESS); 10959 } 10960 10961 /*@C 10962 MatSetOperation - Allows user to set a matrix operation for any matrix type 10963 10964 Logically Collective 10965 10966 Input Parameters: 10967 + mat - the matrix 10968 . op - the name of the operation 10969 - f - the function that provides the operation 10970 10971 Level: developer 10972 10973 Usage: 10974 .vb 10975 extern PetscErrorCode usermult(Mat, Vec, Vec); 10976 10977 PetscCall(MatCreateXXX(comm, ..., &A)); 10978 PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFunction)usermult)); 10979 .ve 10980 10981 Notes: 10982 See the file `include/petscmat.h` for a complete list of matrix 10983 operations, which all have the form MATOP_<OPERATION>, where 10984 <OPERATION> is the name (in all capital letters) of the 10985 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 10986 10987 All user-provided functions (except for `MATOP_DESTROY`) should have the same calling 10988 sequence as the usual matrix interface routines, since they 10989 are intended to be accessed via the usual matrix interface 10990 routines, e.g., 10991 .vb 10992 MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec) 10993 .ve 10994 10995 In particular each function MUST return `PETSC_SUCCESS` on success and 10996 nonzero on failure. 10997 10998 This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type. 10999 11000 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()` 11001 @*/ 11002 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void)) 11003 { 11004 PetscFunctionBegin; 11005 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11006 if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view; 11007 (((void (**)(void))mat->ops)[op]) = f; 11008 PetscFunctionReturn(PETSC_SUCCESS); 11009 } 11010 11011 /*@C 11012 MatGetOperation - Gets a matrix operation for any matrix type. 11013 11014 Not Collective 11015 11016 Input Parameters: 11017 + mat - the matrix 11018 - op - the name of the operation 11019 11020 Output Parameter: 11021 . f - the function that provides the operation 11022 11023 Level: developer 11024 11025 Usage: 11026 .vb 11027 PetscErrorCode (*usermult)(Mat, Vec, Vec); 11028 MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult); 11029 .ve 11030 11031 Notes: 11032 See the file include/petscmat.h for a complete list of matrix 11033 operations, which all have the form MATOP_<OPERATION>, where 11034 <OPERATION> is the name (in all capital letters) of the 11035 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11036 11037 This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type. 11038 11039 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()` 11040 @*/ 11041 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void)) 11042 { 11043 PetscFunctionBegin; 11044 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11045 *f = (((void (**)(void))mat->ops)[op]); 11046 PetscFunctionReturn(PETSC_SUCCESS); 11047 } 11048 11049 /*@ 11050 MatHasOperation - Determines whether the given matrix supports the particular operation. 11051 11052 Not Collective 11053 11054 Input Parameters: 11055 + mat - the matrix 11056 - op - the operation, for example, `MATOP_GET_DIAGONAL` 11057 11058 Output Parameter: 11059 . has - either `PETSC_TRUE` or `PETSC_FALSE` 11060 11061 Level: advanced 11062 11063 Note: 11064 See `MatSetOperation()` for additional discussion on naming convention and usage of `op`. 11065 11066 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()` 11067 @*/ 11068 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has) 11069 { 11070 PetscFunctionBegin; 11071 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11072 PetscValidBoolPointer(has, 3); 11073 if (mat->ops->hasoperation) { 11074 PetscUseTypeMethod(mat, hasoperation, op, has); 11075 } else { 11076 if (((void **)mat->ops)[op]) *has = PETSC_TRUE; 11077 else { 11078 *has = PETSC_FALSE; 11079 if (op == MATOP_CREATE_SUBMATRIX) { 11080 PetscMPIInt size; 11081 11082 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 11083 if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has)); 11084 } 11085 } 11086 } 11087 PetscFunctionReturn(PETSC_SUCCESS); 11088 } 11089 11090 /*@ 11091 MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent 11092 11093 Collective 11094 11095 Input Parameter: 11096 . mat - the matrix 11097 11098 Output Parameter: 11099 . cong - either `PETSC_TRUE` or `PETSC_FALSE` 11100 11101 Level: beginner 11102 11103 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout` 11104 @*/ 11105 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong) 11106 { 11107 PetscFunctionBegin; 11108 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11109 PetscValidType(mat, 1); 11110 PetscValidBoolPointer(cong, 2); 11111 if (!mat->rmap || !mat->cmap) { 11112 *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE; 11113 PetscFunctionReturn(PETSC_SUCCESS); 11114 } 11115 if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */ 11116 PetscCall(PetscLayoutSetUp(mat->rmap)); 11117 PetscCall(PetscLayoutSetUp(mat->cmap)); 11118 PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong)); 11119 if (*cong) mat->congruentlayouts = 1; 11120 else mat->congruentlayouts = 0; 11121 } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE; 11122 PetscFunctionReturn(PETSC_SUCCESS); 11123 } 11124 11125 PetscErrorCode MatSetInf(Mat A) 11126 { 11127 PetscFunctionBegin; 11128 PetscUseTypeMethod(A, setinf); 11129 PetscFunctionReturn(PETSC_SUCCESS); 11130 } 11131 11132 /*@C 11133 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 11134 and possibly removes small values from the graph structure. 11135 11136 Collective 11137 11138 Input Parameters: 11139 + A - the matrix 11140 . sym - `PETSC_TRUE` indicates that the graph should be symmetrized 11141 . scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry 11142 - filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value 11143 11144 Output Parameter: 11145 . graph - the resulting graph 11146 11147 Level: advanced 11148 11149 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG` 11150 @*/ 11151 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph) 11152 { 11153 PetscFunctionBegin; 11154 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11155 PetscValidType(A, 1); 11156 PetscValidLogicalCollectiveBool(A, scale, 3); 11157 PetscValidPointer(graph, 5); 11158 PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph); 11159 PetscFunctionReturn(PETSC_SUCCESS); 11160 } 11161 11162 /*@ 11163 MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place, 11164 meaning the same memory is used for the matrix, and no new memory is allocated. 11165 11166 Collective 11167 11168 Input Parameter: 11169 . A - the matrix 11170 11171 Level: intermediate 11172 11173 Developer Notes: 11174 The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end 11175 of the arrays in the data structure are unneeded. 11176 11177 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatChop()` 11178 @*/ 11179 PetscErrorCode MatEliminateZeros(Mat A) 11180 { 11181 PetscFunctionBegin; 11182 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11183 PetscUseTypeMethod(A, eliminatezeros); 11184 PetscFunctionReturn(PETSC_SUCCESS); 11185 } 11186