1 /* 2 This is where the abstract matrix operations are defined 3 Portions of this code are under: 4 Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved. 5 */ 6 7 #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/ 8 #include <petsc/private/isimpl.h> 9 #include <petsc/private/vecimpl.h> 10 11 /* Logging support */ 12 PetscClassId MAT_CLASSID; 13 PetscClassId MAT_COLORING_CLASSID; 14 PetscClassId MAT_FDCOLORING_CLASSID; 15 PetscClassId MAT_TRANSPOSECOLORING_CLASSID; 16 17 PetscLogEvent MAT_Mult, MAT_MultAdd, MAT_MultTranspose; 18 PetscLogEvent MAT_MultTransposeAdd, MAT_Solve, MAT_Solves, MAT_SolveAdd, MAT_SolveTranspose, MAT_MatSolve, MAT_MatTrSolve; 19 PetscLogEvent MAT_SolveTransposeAdd, MAT_SOR, MAT_ForwardSolve, MAT_BackwardSolve, MAT_LUFactor, MAT_LUFactorSymbolic; 20 PetscLogEvent MAT_LUFactorNumeric, MAT_CholeskyFactor, MAT_CholeskyFactorSymbolic, MAT_CholeskyFactorNumeric, MAT_ILUFactor; 21 PetscLogEvent MAT_ILUFactorSymbolic, MAT_ICCFactorSymbolic, MAT_Copy, MAT_Convert, MAT_Scale, MAT_AssemblyBegin; 22 PetscLogEvent MAT_QRFactorNumeric, MAT_QRFactorSymbolic, MAT_QRFactor; 23 PetscLogEvent MAT_AssemblyEnd, MAT_SetValues, MAT_GetValues, MAT_GetRow, MAT_GetRowIJ, MAT_CreateSubMats, MAT_GetOrdering, MAT_RedundantMat, MAT_GetSeqNonzeroStructure; 24 PetscLogEvent MAT_IncreaseOverlap, MAT_Partitioning, MAT_PartitioningND, MAT_Coarsen, MAT_ZeroEntries, MAT_Load, MAT_View, MAT_AXPY, MAT_FDColoringCreate; 25 PetscLogEvent MAT_FDColoringSetUp, MAT_FDColoringApply, MAT_Transpose, MAT_FDColoringFunction, MAT_CreateSubMat; 26 PetscLogEvent MAT_TransposeColoringCreate; 27 PetscLogEvent MAT_MatMult, MAT_MatMultSymbolic, MAT_MatMultNumeric; 28 PetscLogEvent MAT_PtAP, MAT_PtAPSymbolic, MAT_PtAPNumeric, MAT_RARt, MAT_RARtSymbolic, MAT_RARtNumeric; 29 PetscLogEvent MAT_MatTransposeMult, MAT_MatTransposeMultSymbolic, MAT_MatTransposeMultNumeric; 30 PetscLogEvent MAT_TransposeMatMult, MAT_TransposeMatMultSymbolic, MAT_TransposeMatMultNumeric; 31 PetscLogEvent MAT_MatMatMult, MAT_MatMatMultSymbolic, MAT_MatMatMultNumeric; 32 PetscLogEvent MAT_MultHermitianTranspose, MAT_MultHermitianTransposeAdd; 33 PetscLogEvent MAT_Getsymtransreduced, MAT_GetBrowsOfAcols; 34 PetscLogEvent MAT_GetBrowsOfAocols, MAT_Getlocalmat, MAT_Getlocalmatcondensed, MAT_Seqstompi, MAT_Seqstompinum, MAT_Seqstompisym; 35 PetscLogEvent MAT_GetMultiProcBlock; 36 PetscLogEvent MAT_CUSPARSECopyToGPU, MAT_CUSPARSECopyFromGPU, MAT_CUSPARSEGenerateTranspose, MAT_CUSPARSESolveAnalysis; 37 PetscLogEvent MAT_HIPSPARSECopyToGPU, MAT_HIPSPARSECopyFromGPU, MAT_HIPSPARSEGenerateTranspose, MAT_HIPSPARSESolveAnalysis; 38 PetscLogEvent MAT_PreallCOO, MAT_SetVCOO; 39 PetscLogEvent MAT_SetValuesBatch; 40 PetscLogEvent MAT_ViennaCLCopyToGPU; 41 PetscLogEvent MAT_CUDACopyToGPU; 42 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU; 43 PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom; 44 PetscLogEvent MAT_FactorFactS, MAT_FactorInvS; 45 PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights; 46 PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR; 47 48 const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL}; 49 50 /*@ 51 MatSetRandom - Sets all components of a matrix to random numbers. 52 53 Logically Collective 54 55 Input Parameters: 56 + x - the matrix 57 - rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or `NULL` and 58 it will create one internally. 59 60 Example: 61 .vb 62 PetscRandomCreate(PETSC_COMM_WORLD,&rctx); 63 MatSetRandom(x,rctx); 64 PetscRandomDestroy(rctx); 65 .ve 66 67 Level: intermediate 68 69 Notes: 70 For sparse matrices that have been preallocated but not been assembled it randomly selects appropriate locations, 71 72 for sparse matrices that already have locations it fills the locations with random numbers. 73 74 It generates an error if used on sparse matrices that have not been preallocated. 75 76 .seealso: [](ch_matrices), `Mat`, `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomCreate()`, `PetscRandomDestroy()` 77 @*/ 78 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx) 79 { 80 PetscRandom randObj = NULL; 81 82 PetscFunctionBegin; 83 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 84 if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2); 85 PetscValidType(x, 1); 86 MatCheckPreallocated(x, 1); 87 88 if (!rctx) { 89 MPI_Comm comm; 90 PetscCall(PetscObjectGetComm((PetscObject)x, &comm)); 91 PetscCall(PetscRandomCreate(comm, &randObj)); 92 PetscCall(PetscRandomSetType(randObj, x->defaultrandtype)); 93 PetscCall(PetscRandomSetFromOptions(randObj)); 94 rctx = randObj; 95 } 96 PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0)); 97 PetscUseTypeMethod(x, setrandom, rctx); 98 PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0)); 99 100 PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY)); 101 PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY)); 102 PetscCall(PetscRandomDestroy(&randObj)); 103 PetscFunctionReturn(PETSC_SUCCESS); 104 } 105 106 /*@ 107 MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in 108 109 Logically Collective 110 111 Input Parameter: 112 . mat - the factored matrix 113 114 Output Parameters: 115 + pivot - the pivot value computed 116 - row - the row that the zero pivot occurred. This row value must be interpreted carefully due to row reorderings and which processes 117 the share the matrix 118 119 Level: advanced 120 121 Notes: 122 This routine does not work for factorizations done with external packages. 123 124 This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT` 125 126 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 127 128 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, 129 `MAT_FACTOR_NUMERIC_ZEROPIVOT` 130 @*/ 131 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row) 132 { 133 PetscFunctionBegin; 134 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 135 PetscValidRealPointer(pivot, 2); 136 PetscValidIntPointer(row, 3); 137 *pivot = mat->factorerror_zeropivot_value; 138 *row = mat->factorerror_zeropivot_row; 139 PetscFunctionReturn(PETSC_SUCCESS); 140 } 141 142 /*@ 143 MatFactorGetError - gets the error code from a factorization 144 145 Logically Collective 146 147 Input Parameter: 148 . mat - the factored matrix 149 150 Output Parameter: 151 . err - the error code 152 153 Level: advanced 154 155 Note: 156 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 157 158 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, 159 `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, `MatFactorError` 160 @*/ 161 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err) 162 { 163 PetscFunctionBegin; 164 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 165 PetscValidPointer(err, 2); 166 *err = mat->factorerrortype; 167 PetscFunctionReturn(PETSC_SUCCESS); 168 } 169 170 /*@ 171 MatFactorClearError - clears the error code in a factorization 172 173 Logically Collective 174 175 Input Parameter: 176 . mat - the factored matrix 177 178 Level: developer 179 180 Note: 181 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 182 183 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`, 184 `MatGetErrorCode()`, `MatFactorError` 185 @*/ 186 PetscErrorCode MatFactorClearError(Mat mat) 187 { 188 PetscFunctionBegin; 189 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 190 mat->factorerrortype = MAT_FACTOR_NOERROR; 191 mat->factorerror_zeropivot_value = 0.0; 192 mat->factorerror_zeropivot_row = 0; 193 PetscFunctionReturn(PETSC_SUCCESS); 194 } 195 196 PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero) 197 { 198 Vec r, l; 199 const PetscScalar *al; 200 PetscInt i, nz, gnz, N, n; 201 202 PetscFunctionBegin; 203 PetscCall(MatCreateVecs(mat, &r, &l)); 204 if (!cols) { /* nonzero rows */ 205 PetscCall(MatGetSize(mat, &N, NULL)); 206 PetscCall(MatGetLocalSize(mat, &n, NULL)); 207 PetscCall(VecSet(l, 0.0)); 208 PetscCall(VecSetRandom(r, NULL)); 209 PetscCall(MatMult(mat, r, l)); 210 PetscCall(VecGetArrayRead(l, &al)); 211 } else { /* nonzero columns */ 212 PetscCall(MatGetSize(mat, NULL, &N)); 213 PetscCall(MatGetLocalSize(mat, NULL, &n)); 214 PetscCall(VecSet(r, 0.0)); 215 PetscCall(VecSetRandom(l, NULL)); 216 PetscCall(MatMultTranspose(mat, l, r)); 217 PetscCall(VecGetArrayRead(r, &al)); 218 } 219 if (tol <= 0.0) { 220 for (i = 0, nz = 0; i < n; i++) 221 if (al[i] != 0.0) nz++; 222 } else { 223 for (i = 0, nz = 0; i < n; i++) 224 if (PetscAbsScalar(al[i]) > tol) nz++; 225 } 226 PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 227 if (gnz != N) { 228 PetscInt *nzr; 229 PetscCall(PetscMalloc1(nz, &nzr)); 230 if (nz) { 231 if (tol < 0) { 232 for (i = 0, nz = 0; i < n; i++) 233 if (al[i] != 0.0) nzr[nz++] = i; 234 } else { 235 for (i = 0, nz = 0; i < n; i++) 236 if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i; 237 } 238 } 239 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero)); 240 } else *nonzero = NULL; 241 if (!cols) { /* nonzero rows */ 242 PetscCall(VecRestoreArrayRead(l, &al)); 243 } else { 244 PetscCall(VecRestoreArrayRead(r, &al)); 245 } 246 PetscCall(VecDestroy(&l)); 247 PetscCall(VecDestroy(&r)); 248 PetscFunctionReturn(PETSC_SUCCESS); 249 } 250 251 /*@ 252 MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix 253 254 Input Parameter: 255 . A - the matrix 256 257 Output Parameter: 258 . keptrows - the rows that are not completely zero 259 260 Level: intermediate 261 262 Note: 263 `keptrows` is set to `NULL` if all rows are nonzero. 264 265 .seealso: [](ch_matrices), `Mat`, `MatFindZeroRows()` 266 @*/ 267 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows) 268 { 269 PetscFunctionBegin; 270 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 271 PetscValidType(mat, 1); 272 PetscValidPointer(keptrows, 2); 273 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 274 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 275 if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows); 276 else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows)); 277 PetscFunctionReturn(PETSC_SUCCESS); 278 } 279 280 /*@ 281 MatFindZeroRows - Locate all rows that are completely zero in the matrix 282 283 Input Parameter: 284 . A - the matrix 285 286 Output Parameter: 287 . zerorows - the rows that are completely zero 288 289 Level: intermediate 290 291 Note: 292 `zerorows` is set to `NULL` if no rows are zero. 293 294 .seealso: [](ch_matrices), `Mat`, `MatFindNonzeroRows()` 295 @*/ 296 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows) 297 { 298 IS keptrows; 299 PetscInt m, n; 300 301 PetscFunctionBegin; 302 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 303 PetscValidType(mat, 1); 304 PetscValidPointer(zerorows, 2); 305 PetscCall(MatFindNonzeroRows(mat, &keptrows)); 306 /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows. 307 In keeping with this convention, we set zerorows to NULL if there are no zero 308 rows. */ 309 if (keptrows == NULL) { 310 *zerorows = NULL; 311 } else { 312 PetscCall(MatGetOwnershipRange(mat, &m, &n)); 313 PetscCall(ISComplement(keptrows, m, n, zerorows)); 314 PetscCall(ISDestroy(&keptrows)); 315 } 316 PetscFunctionReturn(PETSC_SUCCESS); 317 } 318 319 /*@ 320 MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling 321 322 Not Collective 323 324 Input Parameter: 325 . A - the matrix 326 327 Output Parameter: 328 . a - the diagonal part (which is a SEQUENTIAL matrix) 329 330 Level: advanced 331 332 Notes: 333 See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix. 334 335 Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation. 336 337 .seealso: [](ch_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ` 338 @*/ 339 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a) 340 { 341 PetscFunctionBegin; 342 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 343 PetscValidType(A, 1); 344 PetscValidPointer(a, 2); 345 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 346 if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a); 347 else { 348 PetscMPIInt size; 349 350 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 351 PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name); 352 *a = A; 353 } 354 PetscFunctionReturn(PETSC_SUCCESS); 355 } 356 357 /*@ 358 MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries. 359 360 Collective 361 362 Input Parameter: 363 . mat - the matrix 364 365 Output Parameter: 366 . trace - the sum of the diagonal entries 367 368 Level: advanced 369 370 .seealso: [](ch_matrices), `Mat` 371 @*/ 372 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace) 373 { 374 Vec diag; 375 376 PetscFunctionBegin; 377 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 378 PetscValidScalarPointer(trace, 2); 379 PetscCall(MatCreateVecs(mat, &diag, NULL)); 380 PetscCall(MatGetDiagonal(mat, diag)); 381 PetscCall(VecSum(diag, trace)); 382 PetscCall(VecDestroy(&diag)); 383 PetscFunctionReturn(PETSC_SUCCESS); 384 } 385 386 /*@ 387 MatRealPart - Zeros out the imaginary part of the matrix 388 389 Logically Collective 390 391 Input Parameter: 392 . mat - the matrix 393 394 Level: advanced 395 396 .seealso: [](ch_matrices), `Mat`, `MatImaginaryPart()` 397 @*/ 398 PetscErrorCode MatRealPart(Mat mat) 399 { 400 PetscFunctionBegin; 401 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 402 PetscValidType(mat, 1); 403 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 404 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 405 MatCheckPreallocated(mat, 1); 406 PetscUseTypeMethod(mat, realpart); 407 PetscFunctionReturn(PETSC_SUCCESS); 408 } 409 410 /*@C 411 MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix 412 413 Collective 414 415 Input Parameter: 416 . mat - the matrix 417 418 Output Parameters: 419 + nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each block) 420 - ghosts - the global indices of the ghost points 421 422 Level: advanced 423 424 Note: 425 `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()` 426 427 .seealso: [](ch_matrices), `Mat`, `VecCreateGhost()` 428 @*/ 429 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[]) 430 { 431 PetscFunctionBegin; 432 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 433 PetscValidType(mat, 1); 434 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 435 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 436 if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts); 437 else { 438 if (nghosts) *nghosts = 0; 439 if (ghosts) *ghosts = NULL; 440 } 441 PetscFunctionReturn(PETSC_SUCCESS); 442 } 443 444 /*@ 445 MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part 446 447 Logically Collective 448 449 Input Parameter: 450 . mat - the matrix 451 452 Level: advanced 453 454 .seealso: [](ch_matrices), `Mat`, `MatRealPart()` 455 @*/ 456 PetscErrorCode MatImaginaryPart(Mat mat) 457 { 458 PetscFunctionBegin; 459 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 460 PetscValidType(mat, 1); 461 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 462 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 463 MatCheckPreallocated(mat, 1); 464 PetscUseTypeMethod(mat, imaginarypart); 465 PetscFunctionReturn(PETSC_SUCCESS); 466 } 467 468 /*@ 469 MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices) 470 471 Not Collective 472 473 Input Parameter: 474 . mat - the matrix 475 476 Output Parameters: 477 + missing - is any diagonal missing 478 - dd - first diagonal entry that is missing (optional) on this process 479 480 Level: advanced 481 482 .seealso: [](ch_matrices), `Mat` 483 @*/ 484 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd) 485 { 486 PetscFunctionBegin; 487 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 488 PetscValidType(mat, 1); 489 PetscValidBoolPointer(missing, 2); 490 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name); 491 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 492 PetscUseTypeMethod(mat, missingdiagonal, missing, dd); 493 PetscFunctionReturn(PETSC_SUCCESS); 494 } 495 496 /*@C 497 MatGetRow - Gets a row of a matrix. You MUST call `MatRestoreRow()` 498 for each row that you get to ensure that your application does 499 not bleed memory. 500 501 Not Collective 502 503 Input Parameters: 504 + mat - the matrix 505 - row - the row to get 506 507 Output Parameters: 508 + ncols - if not `NULL`, the number of nonzeros in the row 509 . cols - if not `NULL`, the column numbers 510 - vals - if not `NULL`, the values 511 512 Level: advanced 513 514 Notes: 515 This routine is provided for people who need to have direct access 516 to the structure of a matrix. We hope that we provide enough 517 high-level matrix routines that few users will need it. 518 519 `MatGetRow()` always returns 0-based column indices, regardless of 520 whether the internal representation is 0-based (default) or 1-based. 521 522 For better efficiency, set cols and/or vals to `NULL` if you do 523 not wish to extract these quantities. 524 525 The user can only examine the values extracted with `MatGetRow()`; 526 the values cannot be altered. To change the matrix entries, one 527 must use `MatSetValues()`. 528 529 You can only have one call to `MatGetRow()` outstanding for a particular 530 matrix at a time, per processor. `MatGetRow()` can only obtain rows 531 associated with the given processor, it cannot get rows from the 532 other processors; for that we suggest using `MatCreateSubMatrices()`, then 533 MatGetRow() on the submatrix. The row index passed to `MatGetRow()` 534 is in the global number of rows. 535 536 Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix. 537 538 Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly. 539 540 Fortran Note: 541 The calling sequence is 542 .vb 543 MatGetRow(matrix,row,ncols,cols,values,ierr) 544 Mat matrix (input) 545 integer row (input) 546 integer ncols (output) 547 integer cols(maxcols) (output) 548 double precision (or double complex) values(maxcols) output 549 .ve 550 where maxcols >= maximum nonzeros in any row of the matrix. 551 552 Caution: 553 Do not try to change the contents of the output arrays (`cols` and `vals`). 554 In some cases, this may corrupt the matrix. 555 556 .seealso: [](ch_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()` 557 @*/ 558 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 559 { 560 PetscInt incols; 561 562 PetscFunctionBegin; 563 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 564 PetscValidType(mat, 1); 565 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 566 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 567 MatCheckPreallocated(mat, 1); 568 PetscCheck(row >= mat->rmap->rstart && row < mat->rmap->rend, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Only for local rows, %" PetscInt_FMT " not in [%" PetscInt_FMT ",%" PetscInt_FMT ")", row, mat->rmap->rstart, mat->rmap->rend); 569 PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0)); 570 PetscUseTypeMethod(mat, getrow, row, &incols, (PetscInt **)cols, (PetscScalar **)vals); 571 if (ncols) *ncols = incols; 572 PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0)); 573 PetscFunctionReturn(PETSC_SUCCESS); 574 } 575 576 /*@ 577 MatConjugate - replaces the matrix values with their complex conjugates 578 579 Logically Collective 580 581 Input Parameter: 582 . mat - the matrix 583 584 Level: advanced 585 586 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()` 587 @*/ 588 PetscErrorCode MatConjugate(Mat mat) 589 { 590 PetscFunctionBegin; 591 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 592 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 593 if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) { 594 PetscUseTypeMethod(mat, conjugate); 595 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 596 } 597 PetscFunctionReturn(PETSC_SUCCESS); 598 } 599 600 /*@C 601 MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`. 602 603 Not Collective 604 605 Input Parameters: 606 + mat - the matrix 607 . row - the row to get 608 . ncols - the number of nonzeros 609 . cols - the columns of the nonzeros 610 - vals - if nonzero the column values 611 612 Level: advanced 613 614 Notes: 615 This routine should be called after you have finished examining the entries. 616 617 This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental 618 us of the array after it has been restored. If you pass `NULL`, it will 619 not zero the pointers. Use of `cols` or `vals` after `MatRestoreRow()` is invalid. 620 621 Fortran Notes: 622 The calling sequence is 623 .vb 624 MatRestoreRow(matrix,row,ncols,cols,values,ierr) 625 Mat matrix (input) 626 integer row (input) 627 integer ncols (output) 628 integer cols(maxcols) (output) 629 double precision (or double complex) values(maxcols) output 630 .ve 631 Where maxcols >= maximum nonzeros in any row of the matrix. 632 633 In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()` 634 before another call to `MatGetRow()` can be made. 635 636 .seealso: [](ch_matrices), `Mat`, `MatGetRow()` 637 @*/ 638 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 639 { 640 PetscFunctionBegin; 641 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 642 if (ncols) PetscValidIntPointer(ncols, 3); 643 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 644 if (!mat->ops->restorerow) PetscFunctionReturn(PETSC_SUCCESS); 645 PetscUseTypeMethod(mat, restorerow, row, ncols, (PetscInt **)cols, (PetscScalar **)vals); 646 if (ncols) *ncols = 0; 647 if (cols) *cols = NULL; 648 if (vals) *vals = NULL; 649 PetscFunctionReturn(PETSC_SUCCESS); 650 } 651 652 /*@ 653 MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 654 You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag. 655 656 Not Collective 657 658 Input Parameter: 659 . mat - the matrix 660 661 Level: advanced 662 663 Note: 664 The flag is to ensure that users are aware that `MatGetRow()` only provides the upper triangular part of the row for the matrices in `MATSBAIJ` format. 665 666 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()` 667 @*/ 668 PetscErrorCode MatGetRowUpperTriangular(Mat mat) 669 { 670 PetscFunctionBegin; 671 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 672 PetscValidType(mat, 1); 673 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 674 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 675 MatCheckPreallocated(mat, 1); 676 if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS); 677 PetscUseTypeMethod(mat, getrowuppertriangular); 678 PetscFunctionReturn(PETSC_SUCCESS); 679 } 680 681 /*@ 682 MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 683 684 Not Collective 685 686 Input Parameter: 687 . mat - the matrix 688 689 Level: advanced 690 691 Note: 692 This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`. 693 694 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()` 695 @*/ 696 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat) 697 { 698 PetscFunctionBegin; 699 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 700 PetscValidType(mat, 1); 701 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 702 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 703 MatCheckPreallocated(mat, 1); 704 if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS); 705 PetscUseTypeMethod(mat, restorerowuppertriangular); 706 PetscFunctionReturn(PETSC_SUCCESS); 707 } 708 709 /*@C 710 MatSetOptionsPrefix - Sets the prefix used for searching for all 711 `Mat` options in the database. 712 713 Logically Collective 714 715 Input Parameters: 716 + A - the matrix 717 - prefix - the prefix to prepend to all option names 718 719 Level: advanced 720 721 Notes: 722 A hyphen (-) must NOT be given at the beginning of the prefix name. 723 The first character of all runtime options is AUTOMATICALLY the hyphen. 724 725 This is NOT used for options for the factorization of the matrix. Normally the 726 prefix is automatically passed in from the PC calling the factorization. To set 727 it directly use `MatSetOptionsPrefixFactor()` 728 729 .seealso: [](ch_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()` 730 @*/ 731 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[]) 732 { 733 PetscFunctionBegin; 734 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 735 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix)); 736 PetscFunctionReturn(PETSC_SUCCESS); 737 } 738 739 /*@C 740 MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for 741 for matrices created with `MatGetFactor()` 742 743 Logically Collective 744 745 Input Parameters: 746 + A - the matrix 747 - prefix - the prefix to prepend to all option names for the factored matrix 748 749 Level: developer 750 751 Notes: 752 A hyphen (-) must NOT be given at the beginning of the prefix name. 753 The first character of all runtime options is AUTOMATICALLY the hyphen. 754 755 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 756 it directly when not using `KSP`/`PC` use `MatSetOptionsPrefixFactor()` 757 758 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()` 759 @*/ 760 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[]) 761 { 762 PetscFunctionBegin; 763 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 764 if (prefix) { 765 PetscValidCharPointer(prefix, 2); 766 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 767 if (prefix != A->factorprefix) { 768 PetscCall(PetscFree(A->factorprefix)); 769 PetscCall(PetscStrallocpy(prefix, &A->factorprefix)); 770 } 771 } else PetscCall(PetscFree(A->factorprefix)); 772 PetscFunctionReturn(PETSC_SUCCESS); 773 } 774 775 /*@C 776 MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for 777 for matrices created with `MatGetFactor()` 778 779 Logically Collective 780 781 Input Parameters: 782 + A - the matrix 783 - prefix - the prefix to prepend to all option names for the factored matrix 784 785 Level: developer 786 787 Notes: 788 A hyphen (-) must NOT be given at the beginning of the prefix name. 789 The first character of all runtime options is AUTOMATICALLY the hyphen. 790 791 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 792 it directly when not using `KSP`/`PC` use `MatAppendOptionsPrefixFactor()` 793 794 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`, 795 `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`, 796 `MatSetOptionsPrefix()` 797 @*/ 798 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[]) 799 { 800 size_t len1, len2, new_len; 801 802 PetscFunctionBegin; 803 PetscValidHeader(A, 1); 804 if (!prefix) PetscFunctionReturn(PETSC_SUCCESS); 805 if (!A->factorprefix) { 806 PetscCall(MatSetOptionsPrefixFactor(A, prefix)); 807 PetscFunctionReturn(PETSC_SUCCESS); 808 } 809 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 810 811 PetscCall(PetscStrlen(A->factorprefix, &len1)); 812 PetscCall(PetscStrlen(prefix, &len2)); 813 new_len = len1 + len2 + 1; 814 PetscCall(PetscRealloc(new_len * sizeof(*(A->factorprefix)), &A->factorprefix)); 815 PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1)); 816 PetscFunctionReturn(PETSC_SUCCESS); 817 } 818 819 /*@C 820 MatAppendOptionsPrefix - Appends to the prefix used for searching for all 821 matrix options in the database. 822 823 Logically Collective 824 825 Input Parameters: 826 + A - the matrix 827 - prefix - the prefix to prepend to all option names 828 829 Level: advanced 830 831 Note: 832 A hyphen (-) must NOT be given at the beginning of the prefix name. 833 The first character of all runtime options is AUTOMATICALLY the hyphen. 834 835 .seealso: [](ch_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()` 836 @*/ 837 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[]) 838 { 839 PetscFunctionBegin; 840 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 841 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix)); 842 PetscFunctionReturn(PETSC_SUCCESS); 843 } 844 845 /*@C 846 MatGetOptionsPrefix - Gets the prefix used for searching for all 847 matrix options in the database. 848 849 Not Collective 850 851 Input Parameter: 852 . A - the matrix 853 854 Output Parameter: 855 . prefix - pointer to the prefix string used 856 857 Level: advanced 858 859 Fortran Note: 860 The user should pass in a string `prefix` of 861 sufficient length to hold the prefix. 862 863 .seealso: [](ch_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()` 864 @*/ 865 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[]) 866 { 867 PetscFunctionBegin; 868 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 869 PetscValidPointer(prefix, 2); 870 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix)); 871 PetscFunctionReturn(PETSC_SUCCESS); 872 } 873 874 /*@ 875 MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by users. 876 877 Collective 878 879 Input Parameter: 880 . A - the matrix 881 882 Level: beginner 883 884 Notes: 885 The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`. 886 887 Users can reset the preallocation to access the original memory. 888 889 Currently only supported for `MATAIJ` matrices. 890 891 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()` 892 @*/ 893 PetscErrorCode MatResetPreallocation(Mat A) 894 { 895 PetscFunctionBegin; 896 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 897 PetscValidType(A, 1); 898 PetscCheck(A->insertmode == NOT_SET_VALUES, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot reset preallocation after setting some values but not yet calling MatAssemblyBegin()/MatAsssemblyEnd()"); 899 if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS); 900 PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A)); 901 PetscFunctionReturn(PETSC_SUCCESS); 902 } 903 904 /*@ 905 MatSetUp - Sets up the internal matrix data structures for later use. 906 907 Collective 908 909 Input Parameter: 910 . A - the matrix 911 912 Level: intermediate 913 914 Notes: 915 If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of 916 setting values in the matrix. 917 918 If a suitable preallocation routine is used, this function does not need to be called. 919 920 This routine is called internally by other matrix functions when needed so rarely needs to be called by users 921 922 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()` 923 @*/ 924 PetscErrorCode MatSetUp(Mat A) 925 { 926 PetscFunctionBegin; 927 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 928 if (!((PetscObject)A)->type_name) { 929 PetscMPIInt size; 930 931 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 932 PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ)); 933 } 934 if (!A->preallocated) PetscTryTypeMethod(A, setup); 935 PetscCall(PetscLayoutSetUp(A->rmap)); 936 PetscCall(PetscLayoutSetUp(A->cmap)); 937 A->preallocated = PETSC_TRUE; 938 PetscFunctionReturn(PETSC_SUCCESS); 939 } 940 941 #if defined(PETSC_HAVE_SAWS) 942 #include <petscviewersaws.h> 943 #endif 944 945 /* 946 If threadsafety is on extraneous matrices may be printed 947 948 This flag cannot be stored in the matrix because the original matrix in MatView() may assemble a new matrix which is passed into MatViewFromOptions() 949 */ 950 #if !defined(PETSC_HAVE_THREADSAFETY) 951 static PetscInt insidematview = 0; 952 #endif 953 954 /*@C 955 MatViewFromOptions - View properties of the matrix based on options set in the options database 956 957 Collective 958 959 Input Parameters: 960 + A - the matrix 961 . obj - optional additional object that provides the options prefix to use 962 - name - command line option 963 964 Options Database Key: 965 . -mat_view [viewertype]:... - the viewer and its options 966 967 Level: intermediate 968 969 Notes: 970 .vb 971 If no value is provided ascii:stdout is used 972 ascii[:[filename][:[format][:append]]] defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab, 973 for example ascii::ascii_info prints just the information about the object not all details 974 unless :append is given filename opens in write mode, overwriting what was already there 975 binary[:[filename][:[format][:append]]] defaults to the file binaryoutput 976 draw[:drawtype[:filename]] for example, draw:tikz, draw:tikz:figure.tex or draw:x 977 socket[:port] defaults to the standard output port 978 saws[:communicatorname] publishes object to the Scientific Application Webserver (SAWs) 979 .ve 980 981 .seealso: [](ch_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()` 982 @*/ 983 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[]) 984 { 985 PetscFunctionBegin; 986 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 987 #if !defined(PETSC_HAVE_THREADSAFETY) 988 if (insidematview) PetscFunctionReturn(PETSC_SUCCESS); 989 #endif 990 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 991 PetscFunctionReturn(PETSC_SUCCESS); 992 } 993 994 /*@C 995 MatView - display information about a matrix in a variety ways 996 997 Collective 998 999 Input Parameters: 1000 + mat - the matrix 1001 - viewer - visualization context 1002 1003 Options Database Keys: 1004 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 1005 . -mat_view ::ascii_info_detail - Prints more detailed info 1006 . -mat_view - Prints matrix in ASCII format 1007 . -mat_view ::ascii_matlab - Prints matrix in Matlab format 1008 . -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 1009 . -display <name> - Sets display name (default is host) 1010 . -draw_pause <sec> - Sets number of seconds to pause after display 1011 . -mat_view socket - Sends matrix to socket, can be accessed from Matlab (see Users-Manual: ch_matlab for details) 1012 . -viewer_socket_machine <machine> - 1013 . -viewer_socket_port <port> - 1014 . -mat_view binary - save matrix to file in binary format 1015 - -viewer_binary_filename <name> - 1016 1017 Level: beginner 1018 1019 Notes: 1020 The available visualization contexts include 1021 + `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices 1022 . `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD` 1023 . `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm 1024 - `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure 1025 1026 The user can open alternative visualization contexts with 1027 + `PetscViewerASCIIOpen()` - Outputs matrix to a specified file 1028 . `PetscViewerBinaryOpen()` - Outputs matrix in binary to a 1029 specified file; corresponding input uses `MatLoad()` 1030 . `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to 1031 an X window display 1032 - `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer. 1033 Currently only the `MATSEQDENSE` and `MATAIJ` 1034 matrix types support the Socket viewer. 1035 1036 The user can call `PetscViewerPushFormat()` to specify the output 1037 format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`, 1038 `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`). Available formats include 1039 + `PETSC_VIEWER_DEFAULT` - default, prints matrix contents 1040 . `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in Matlab format 1041 . `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros 1042 . `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse 1043 format common among all matrix types 1044 . `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific 1045 format (which is in many cases the same as the default) 1046 . `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix 1047 size and structure (not the matrix entries) 1048 - `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about 1049 the matrix structure 1050 1051 The ASCII viewers are only recommended for small matrices on at most a moderate number of processes, 1052 the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format. 1053 1054 In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer). 1055 1056 See the manual page for `MatLoad()` for the exact format of the binary file when the binary 1057 viewer is used. 1058 1059 See share/petsc/matlab/PetscBinaryRead.m for a Matlab code that can read in the binary file when the binary 1060 viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python. 1061 1062 One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure, 1063 and then use the following mouse functions. 1064 .vb 1065 left mouse: zoom in 1066 middle mouse: zoom out 1067 right mouse: continue with the simulation 1068 .ve 1069 1070 .seealso: [](ch_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`, 1071 `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()` 1072 @*/ 1073 PetscErrorCode MatView(Mat mat, PetscViewer viewer) 1074 { 1075 PetscInt rows, cols, rbs, cbs; 1076 PetscBool isascii, isstring, issaws; 1077 PetscViewerFormat format; 1078 PetscMPIInt size; 1079 1080 PetscFunctionBegin; 1081 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1082 PetscValidType(mat, 1); 1083 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer)); 1084 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1085 PetscCheckSameComm(mat, 1, viewer, 2); 1086 1087 PetscCall(PetscViewerGetFormat(viewer, &format)); 1088 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 1089 if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS); 1090 1091 #if !defined(PETSC_HAVE_THREADSAFETY) 1092 insidematview++; 1093 #endif 1094 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 1095 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 1096 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws)); 1097 PetscCheck((isascii && (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL)) || !mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "No viewers for factored matrix except ASCII, info, or info_detail"); 1098 1099 PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0)); 1100 if (isascii) { 1101 if (!mat->preallocated) { 1102 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n")); 1103 #if !defined(PETSC_HAVE_THREADSAFETY) 1104 insidematview--; 1105 #endif 1106 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1107 PetscFunctionReturn(PETSC_SUCCESS); 1108 } 1109 if (!mat->assembled) { 1110 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n")); 1111 #if !defined(PETSC_HAVE_THREADSAFETY) 1112 insidematview--; 1113 #endif 1114 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1115 PetscFunctionReturn(PETSC_SUCCESS); 1116 } 1117 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer)); 1118 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1119 MatNullSpace nullsp, transnullsp; 1120 1121 PetscCall(PetscViewerASCIIPushTab(viewer)); 1122 PetscCall(MatGetSize(mat, &rows, &cols)); 1123 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1124 if (rbs != 1 || cbs != 1) { 1125 if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs)); 1126 else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs)); 1127 } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols)); 1128 if (mat->factortype) { 1129 MatSolverType solver; 1130 PetscCall(MatFactorGetSolverType(mat, &solver)); 1131 PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver)); 1132 } 1133 if (mat->ops->getinfo) { 1134 MatInfo info; 1135 PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info)); 1136 PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated)); 1137 if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs)); 1138 } 1139 PetscCall(MatGetNullSpace(mat, &nullsp)); 1140 PetscCall(MatGetTransposeNullSpace(mat, &transnullsp)); 1141 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached null space\n")); 1142 if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached transposed null space\n")); 1143 PetscCall(MatGetNearNullSpace(mat, &nullsp)); 1144 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached near null space\n")); 1145 PetscCall(PetscViewerASCIIPushTab(viewer)); 1146 PetscCall(MatProductView(mat, viewer)); 1147 PetscCall(PetscViewerASCIIPopTab(viewer)); 1148 } 1149 } else if (issaws) { 1150 #if defined(PETSC_HAVE_SAWS) 1151 PetscMPIInt rank; 1152 1153 PetscCall(PetscObjectName((PetscObject)mat)); 1154 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 1155 if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer)); 1156 #endif 1157 } else if (isstring) { 1158 const char *type; 1159 PetscCall(MatGetType(mat, &type)); 1160 PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type)); 1161 PetscTryTypeMethod(mat, view, viewer); 1162 } 1163 if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) { 1164 PetscCall(PetscViewerASCIIPushTab(viewer)); 1165 PetscUseTypeMethod(mat, viewnative, viewer); 1166 PetscCall(PetscViewerASCIIPopTab(viewer)); 1167 } else if (mat->ops->view) { 1168 PetscCall(PetscViewerASCIIPushTab(viewer)); 1169 PetscUseTypeMethod(mat, view, viewer); 1170 PetscCall(PetscViewerASCIIPopTab(viewer)); 1171 } 1172 if (isascii) { 1173 PetscCall(PetscViewerGetFormat(viewer, &format)); 1174 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer)); 1175 } 1176 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1177 #if !defined(PETSC_HAVE_THREADSAFETY) 1178 insidematview--; 1179 #endif 1180 PetscFunctionReturn(PETSC_SUCCESS); 1181 } 1182 1183 #if defined(PETSC_USE_DEBUG) 1184 #include <../src/sys/totalview/tv_data_display.h> 1185 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat) 1186 { 1187 TV_add_row("Local rows", "int", &mat->rmap->n); 1188 TV_add_row("Local columns", "int", &mat->cmap->n); 1189 TV_add_row("Global rows", "int", &mat->rmap->N); 1190 TV_add_row("Global columns", "int", &mat->cmap->N); 1191 TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name); 1192 return TV_format_OK; 1193 } 1194 #endif 1195 1196 /*@C 1197 MatLoad - Loads a matrix that has been stored in binary/HDF5 format 1198 with `MatView()`. The matrix format is determined from the options database. 1199 Generates a parallel MPI matrix if the communicator has more than one 1200 processor. The default matrix type is `MATAIJ`. 1201 1202 Collective 1203 1204 Input Parameters: 1205 + mat - the newly loaded matrix, this needs to have been created with `MatCreate()` 1206 or some related function before a call to `MatLoad()` 1207 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer 1208 1209 Options Database Keys: 1210 Used with block matrix formats (`MATSEQBAIJ`, ...) to specify 1211 block size 1212 . -matload_block_size <bs> - set block size 1213 1214 Level: beginner 1215 1216 Notes: 1217 If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the 1218 `Mat` before calling this routine if you wish to set it from the options database. 1219 1220 `MatLoad()` automatically loads into the options database any options 1221 given in the file filename.info where filename is the name of the file 1222 that was passed to the `PetscViewerBinaryOpen()`. The options in the info 1223 file will be ignored if you use the -viewer_binary_skip_info option. 1224 1225 If the type or size of mat is not set before a call to `MatLoad()`, PETSc 1226 sets the default matrix type AIJ and sets the local and global sizes. 1227 If type and/or size is already set, then the same are used. 1228 1229 In parallel, each processor can load a subset of rows (or the 1230 entire matrix). This routine is especially useful when a large 1231 matrix is stored on disk and only part of it is desired on each 1232 processor. For example, a parallel solver may access only some of 1233 the rows from each processor. The algorithm used here reads 1234 relatively small blocks of data rather than reading the entire 1235 matrix and then subsetting it. 1236 1237 Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`. 1238 Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`, 1239 or the sequence like 1240 .vb 1241 `PetscViewer` v; 1242 `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v); 1243 `PetscViewerSetType`(v,`PETSCVIEWERBINARY`); 1244 `PetscViewerSetFromOptions`(v); 1245 `PetscViewerFileSetMode`(v,`FILE_MODE_READ`); 1246 `PetscViewerFileSetName`(v,"datafile"); 1247 .ve 1248 The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option 1249 $ -viewer_type {binary, hdf5} 1250 1251 See the example src/ksp/ksp/tutorials/ex27.c with the first approach, 1252 and src/mat/tutorials/ex10.c with the second approach. 1253 1254 In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks 1255 is read onto MPI rank 0 and then shipped to its destination MPI rank, one after another. 1256 Multiple objects, both matrices and vectors, can be stored within the same file. 1257 Their `PetscObject` name is ignored; they are loaded in the order of their storage. 1258 1259 Most users should not need to know the details of the binary storage 1260 format, since `MatLoad()` and `MatView()` completely hide these details. 1261 But for anyone who is interested, the standard binary matrix storage 1262 format is 1263 1264 .vb 1265 PetscInt MAT_FILE_CLASSID 1266 PetscInt number of rows 1267 PetscInt number of columns 1268 PetscInt total number of nonzeros 1269 PetscInt *number nonzeros in each row 1270 PetscInt *column indices of all nonzeros (starting index is zero) 1271 PetscScalar *values of all nonzeros 1272 .ve 1273 If PETSc was not configured with `--with-64-bit-indices` then only `MATMPIAIJ` matrices with more than `PETSC_INT_MAX` non-zeros can be 1274 stored or loaded (each MPI process part of the matrix must have less than `PETSC_INT_MAX` nonzeros). Since the total nonzero count in this 1275 case will not fit in a (32-bit) `PetscInt` the value `PETSC_INT_MAX` is used for the header entry `total number of nonzeros`. 1276 1277 PETSc automatically does the byte swapping for 1278 machines that store the bytes reversed. Thus if you write your own binary 1279 read/write routines you have to swap the bytes; see `PetscBinaryRead()` 1280 and `PetscBinaryWrite()` to see how this may be done. 1281 1282 In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used. 1283 Each processor's chunk is loaded independently by its owning MPI process. 1284 Multiple objects, both matrices and vectors, can be stored within the same file. 1285 They are looked up by their PetscObject name. 1286 1287 As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use 1288 by default the same structure and naming of the AIJ arrays and column count 1289 within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g. 1290 $ save example.mat A b -v7.3 1291 can be directly read by this routine (see Reference 1 for details). 1292 1293 Depending on your MATLAB version, this format might be a default, 1294 otherwise you can set it as default in Preferences. 1295 1296 Unless -nocompression flag is used to save the file in MATLAB, 1297 PETSc must be configured with ZLIB package. 1298 1299 See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c 1300 1301 This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5` 1302 1303 Corresponding `MatView()` is not yet implemented. 1304 1305 The loaded matrix is actually a transpose of the original one in MATLAB, 1306 unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above). 1307 With this format, matrix is automatically transposed by PETSc, 1308 unless the matrix is marked as SPD or symmetric 1309 (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`). 1310 1311 References: 1312 . * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version 1313 1314 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()` 1315 @*/ 1316 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer) 1317 { 1318 PetscBool flg; 1319 1320 PetscFunctionBegin; 1321 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1322 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1323 1324 if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ)); 1325 1326 flg = PETSC_FALSE; 1327 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL)); 1328 if (flg) { 1329 PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE)); 1330 PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE)); 1331 } 1332 flg = PETSC_FALSE; 1333 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL)); 1334 if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE)); 1335 1336 PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0)); 1337 PetscUseTypeMethod(mat, load, viewer); 1338 PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0)); 1339 PetscFunctionReturn(PETSC_SUCCESS); 1340 } 1341 1342 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant) 1343 { 1344 Mat_Redundant *redund = *redundant; 1345 1346 PetscFunctionBegin; 1347 if (redund) { 1348 if (redund->matseq) { /* via MatCreateSubMatrices() */ 1349 PetscCall(ISDestroy(&redund->isrow)); 1350 PetscCall(ISDestroy(&redund->iscol)); 1351 PetscCall(MatDestroySubMatrices(1, &redund->matseq)); 1352 } else { 1353 PetscCall(PetscFree2(redund->send_rank, redund->recv_rank)); 1354 PetscCall(PetscFree(redund->sbuf_j)); 1355 PetscCall(PetscFree(redund->sbuf_a)); 1356 for (PetscInt i = 0; i < redund->nrecvs; i++) { 1357 PetscCall(PetscFree(redund->rbuf_j[i])); 1358 PetscCall(PetscFree(redund->rbuf_a[i])); 1359 } 1360 PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a)); 1361 } 1362 1363 if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm)); 1364 PetscCall(PetscFree(redund)); 1365 } 1366 PetscFunctionReturn(PETSC_SUCCESS); 1367 } 1368 1369 /*@C 1370 MatDestroy - Frees space taken by a matrix. 1371 1372 Collective 1373 1374 Input Parameter: 1375 . A - the matrix 1376 1377 Level: beginner 1378 1379 Developer Note: 1380 Some special arrays of matrices are not destroyed in this routine but instead by the routines called by 1381 `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines. 1382 `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes 1383 if changes are needed here. 1384 1385 .seealso: [](ch_matrices), `Mat`, `MatCreate()` 1386 @*/ 1387 PetscErrorCode MatDestroy(Mat *A) 1388 { 1389 PetscFunctionBegin; 1390 if (!*A) PetscFunctionReturn(PETSC_SUCCESS); 1391 PetscValidHeaderSpecific(*A, MAT_CLASSID, 1); 1392 if (--((PetscObject)(*A))->refct > 0) { 1393 *A = NULL; 1394 PetscFunctionReturn(PETSC_SUCCESS); 1395 } 1396 1397 /* if memory was published with SAWs then destroy it */ 1398 PetscCall(PetscObjectSAWsViewOff((PetscObject)*A)); 1399 PetscTryTypeMethod((*A), destroy); 1400 1401 PetscCall(PetscFree((*A)->factorprefix)); 1402 PetscCall(PetscFree((*A)->defaultvectype)); 1403 PetscCall(PetscFree((*A)->defaultrandtype)); 1404 PetscCall(PetscFree((*A)->bsizes)); 1405 PetscCall(PetscFree((*A)->solvertype)); 1406 for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i])); 1407 if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL; 1408 PetscCall(MatDestroy_Redundant(&(*A)->redundant)); 1409 PetscCall(MatProductClear(*A)); 1410 PetscCall(MatNullSpaceDestroy(&(*A)->nullsp)); 1411 PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp)); 1412 PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp)); 1413 PetscCall(MatDestroy(&(*A)->schur)); 1414 PetscCall(PetscLayoutDestroy(&(*A)->rmap)); 1415 PetscCall(PetscLayoutDestroy(&(*A)->cmap)); 1416 PetscCall(PetscHeaderDestroy(A)); 1417 PetscFunctionReturn(PETSC_SUCCESS); 1418 } 1419 1420 /*@C 1421 MatSetValues - Inserts or adds a block of values into a matrix. 1422 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1423 MUST be called after all calls to `MatSetValues()` have been completed. 1424 1425 Not Collective 1426 1427 Input Parameters: 1428 + mat - the matrix 1429 . v - a logically two-dimensional array of values 1430 . m - the number of rows 1431 . idxm - the global indices of the rows 1432 . n - the number of columns 1433 . idxn - the global indices of the columns 1434 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1435 1436 Level: beginner 1437 1438 Notes: 1439 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1440 1441 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1442 options cannot be mixed without intervening calls to the assembly 1443 routines. 1444 1445 `MatSetValues()` uses 0-based row and column numbers in Fortran 1446 as well as in C. 1447 1448 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1449 simply ignored. This allows easily inserting element stiffness matrices 1450 with homogeneous Dirchlet boundary conditions that you don't want represented 1451 in the matrix. 1452 1453 Efficiency Alert: 1454 The routine `MatSetValuesBlocked()` may offer much better efficiency 1455 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1456 1457 Developer Note: 1458 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1459 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1460 1461 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1462 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1463 @*/ 1464 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1465 { 1466 PetscFunctionBeginHot; 1467 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1468 PetscValidType(mat, 1); 1469 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1470 PetscValidIntPointer(idxm, 3); 1471 PetscValidIntPointer(idxn, 5); 1472 MatCheckPreallocated(mat, 1); 1473 1474 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1475 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1476 1477 if (PetscDefined(USE_DEBUG)) { 1478 PetscInt i, j; 1479 1480 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1481 for (i = 0; i < m; i++) { 1482 for (j = 0; j < n; j++) { 1483 if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j])) 1484 #if defined(PETSC_USE_COMPLEX) 1485 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Inserting %g+i%g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")", (double)PetscRealPart(v[i * n + j]), (double)PetscImaginaryPart(v[i * n + j]), idxm[i], idxn[j]); 1486 #else 1487 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Inserting %g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")", (double)v[i * n + j], idxm[i], idxn[j]); 1488 #endif 1489 } 1490 } 1491 for (i = 0; i < m; i++) PetscCheck(idxm[i] < mat->rmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot insert in row %" PetscInt_FMT ", maximum is %" PetscInt_FMT, idxm[i], mat->rmap->N - 1); 1492 for (i = 0; i < n; i++) PetscCheck(idxn[i] < mat->cmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot insert in column %" PetscInt_FMT ", maximum is %" PetscInt_FMT, idxn[i], mat->cmap->N - 1); 1493 } 1494 1495 if (mat->assembled) { 1496 mat->was_assembled = PETSC_TRUE; 1497 mat->assembled = PETSC_FALSE; 1498 } 1499 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1500 PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv); 1501 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1502 PetscFunctionReturn(PETSC_SUCCESS); 1503 } 1504 1505 /*@C 1506 MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns 1507 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1508 MUST be called after all calls to `MatSetValues()` have been completed. 1509 1510 Not Collective 1511 1512 Input Parameters: 1513 + mat - the matrix 1514 . v - a logically two-dimensional array of values 1515 . ism - the rows to provide 1516 . isn - the columns to provide 1517 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1518 1519 Level: beginner 1520 1521 Notes: 1522 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1523 1524 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1525 options cannot be mixed without intervening calls to the assembly 1526 routines. 1527 1528 `MatSetValues()` uses 0-based row and column numbers in Fortran 1529 as well as in C. 1530 1531 Negative indices may be passed in `ism` and `isn`, these rows and columns are 1532 simply ignored. This allows easily inserting element stiffness matrices 1533 with homogeneous Dirchlet boundary conditions that you don't want represented 1534 in the matrix. 1535 1536 Efficiency Alert: 1537 The routine `MatSetValuesBlocked()` may offer much better efficiency 1538 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1539 1540 This is currently not optimized for any particular `ISType` 1541 1542 Developer Notes: 1543 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1544 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1545 1546 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1547 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()` 1548 @*/ 1549 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv) 1550 { 1551 PetscInt m, n; 1552 const PetscInt *rows, *cols; 1553 1554 PetscFunctionBeginHot; 1555 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1556 PetscCall(ISGetIndices(ism, &rows)); 1557 PetscCall(ISGetIndices(isn, &cols)); 1558 PetscCall(ISGetLocalSize(ism, &m)); 1559 PetscCall(ISGetLocalSize(isn, &n)); 1560 PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv)); 1561 PetscCall(ISRestoreIndices(ism, &rows)); 1562 PetscCall(ISRestoreIndices(isn, &cols)); 1563 PetscFunctionReturn(PETSC_SUCCESS); 1564 } 1565 1566 /*@ 1567 MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1568 values into a matrix 1569 1570 Not Collective 1571 1572 Input Parameters: 1573 + mat - the matrix 1574 . row - the (block) row to set 1575 - v - a logically two-dimensional array of values 1576 1577 Level: intermediate 1578 1579 Notes: 1580 The values, `v`, are column-oriented (for the block version) and sorted 1581 1582 All the nonzeros in the row must be provided 1583 1584 The matrix must have previously had its column indices set, likely by having been assembled. 1585 1586 The row must belong to this process 1587 1588 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1589 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()` 1590 @*/ 1591 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[]) 1592 { 1593 PetscInt globalrow; 1594 1595 PetscFunctionBegin; 1596 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1597 PetscValidType(mat, 1); 1598 PetscValidScalarPointer(v, 3); 1599 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow)); 1600 PetscCall(MatSetValuesRow(mat, globalrow, v)); 1601 PetscFunctionReturn(PETSC_SUCCESS); 1602 } 1603 1604 /*@ 1605 MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1606 values into a matrix 1607 1608 Not Collective 1609 1610 Input Parameters: 1611 + mat - the matrix 1612 . row - the (block) row to set 1613 - v - a logically two-dimensional (column major) array of values for block matrices with blocksize larger than one, otherwise a one dimensional array of values 1614 1615 Level: advanced 1616 1617 Notes: 1618 The values, `v`, are column-oriented for the block version. 1619 1620 All the nonzeros in the row must be provided 1621 1622 THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used. 1623 1624 The row must belong to this process 1625 1626 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1627 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()` 1628 @*/ 1629 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[]) 1630 { 1631 PetscFunctionBeginHot; 1632 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1633 PetscValidType(mat, 1); 1634 MatCheckPreallocated(mat, 1); 1635 PetscValidScalarPointer(v, 3); 1636 PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values"); 1637 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1638 mat->insertmode = INSERT_VALUES; 1639 1640 if (mat->assembled) { 1641 mat->was_assembled = PETSC_TRUE; 1642 mat->assembled = PETSC_FALSE; 1643 } 1644 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1645 PetscUseTypeMethod(mat, setvaluesrow, row, v); 1646 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1647 PetscFunctionReturn(PETSC_SUCCESS); 1648 } 1649 1650 /*@ 1651 MatSetValuesStencil - Inserts or adds a block of values into a matrix. 1652 Using structured grid indexing 1653 1654 Not Collective 1655 1656 Input Parameters: 1657 + mat - the matrix 1658 . m - number of rows being entered 1659 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered 1660 . n - number of columns being entered 1661 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered 1662 . v - a logically two-dimensional array of values 1663 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values 1664 1665 Level: beginner 1666 1667 Notes: 1668 By default the values, `v`, are row-oriented. See `MatSetOption()` for other options. 1669 1670 Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1671 options cannot be mixed without intervening calls to the assembly 1672 routines. 1673 1674 The grid coordinates are across the entire grid, not just the local portion 1675 1676 `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran 1677 as well as in C. 1678 1679 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1680 1681 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1682 or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1683 1684 The columns and rows in the stencil passed in MUST be contained within the 1685 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1686 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1687 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1688 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1689 1690 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 1691 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 1692 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 1693 `DM_BOUNDARY_PERIODIC` boundary type. 1694 1695 For indices that don't mean anything for your case (like the k index when working in 2d) or the c index when you have 1696 a single value per point) you can skip filling those indices. 1697 1698 Inspired by the structured grid interface to the HYPRE package 1699 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1700 1701 Efficiency Alert: 1702 The routine `MatSetValuesBlockedStencil()` may offer much better efficiency 1703 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1704 1705 Fortran Note: 1706 `idxm` and `idxn` should be declared as 1707 $ MatStencil idxm(4,m),idxn(4,n) 1708 and the values inserted using 1709 .vb 1710 idxm(MatStencil_i,1) = i 1711 idxm(MatStencil_j,1) = j 1712 idxm(MatStencil_k,1) = k 1713 idxm(MatStencil_c,1) = c 1714 etc 1715 .ve 1716 1717 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1718 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil` 1719 @*/ 1720 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1721 { 1722 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1723 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1724 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1725 1726 PetscFunctionBegin; 1727 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1728 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1729 PetscValidType(mat, 1); 1730 PetscValidPointer(idxm, 3); 1731 PetscValidPointer(idxn, 5); 1732 1733 if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 1734 jdxm = buf; 1735 jdxn = buf + m; 1736 } else { 1737 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1738 jdxm = bufm; 1739 jdxn = bufn; 1740 } 1741 for (i = 0; i < m; i++) { 1742 for (j = 0; j < 3 - sdim; j++) dxm++; 1743 tmp = *dxm++ - starts[0]; 1744 for (j = 0; j < dim - 1; j++) { 1745 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1746 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1747 } 1748 if (mat->stencil.noc) dxm++; 1749 jdxm[i] = tmp; 1750 } 1751 for (i = 0; i < n; i++) { 1752 for (j = 0; j < 3 - sdim; j++) dxn++; 1753 tmp = *dxn++ - starts[0]; 1754 for (j = 0; j < dim - 1; j++) { 1755 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1756 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1757 } 1758 if (mat->stencil.noc) dxn++; 1759 jdxn[i] = tmp; 1760 } 1761 PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv)); 1762 PetscCall(PetscFree2(bufm, bufn)); 1763 PetscFunctionReturn(PETSC_SUCCESS); 1764 } 1765 1766 /*@ 1767 MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix. 1768 Using structured grid indexing 1769 1770 Not Collective 1771 1772 Input Parameters: 1773 + mat - the matrix 1774 . m - number of rows being entered 1775 . idxm - grid coordinates for matrix rows being entered 1776 . n - number of columns being entered 1777 . idxn - grid coordinates for matrix columns being entered 1778 . v - a logically two-dimensional array of values 1779 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values 1780 1781 Level: beginner 1782 1783 Notes: 1784 By default the values, `v`, are row-oriented and unsorted. 1785 See `MatSetOption()` for other options. 1786 1787 Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1788 options cannot be mixed without intervening calls to the assembly 1789 routines. 1790 1791 The grid coordinates are across the entire grid, not just the local portion 1792 1793 `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran 1794 as well as in C. 1795 1796 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1797 1798 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1799 or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1800 1801 The columns and rows in the stencil passed in MUST be contained within the 1802 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1803 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1804 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1805 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1806 1807 Negative indices may be passed in idxm and idxn, these rows and columns are 1808 simply ignored. This allows easily inserting element stiffness matrices 1809 with homogeneous Dirchlet boundary conditions that you don't want represented 1810 in the matrix. 1811 1812 Inspired by the structured grid interface to the HYPRE package 1813 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1814 1815 Fortran Note: 1816 `idxm` and `idxn` should be declared as 1817 $ MatStencil idxm(4,m),idxn(4,n) 1818 and the values inserted using 1819 .vb 1820 idxm(MatStencil_i,1) = i 1821 idxm(MatStencil_j,1) = j 1822 idxm(MatStencil_k,1) = k 1823 etc 1824 .ve 1825 1826 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1827 `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`, 1828 `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` 1829 @*/ 1830 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1831 { 1832 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1833 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1834 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1835 1836 PetscFunctionBegin; 1837 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1838 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1839 PetscValidType(mat, 1); 1840 PetscValidPointer(idxm, 3); 1841 PetscValidPointer(idxn, 5); 1842 PetscValidScalarPointer(v, 6); 1843 1844 if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 1845 jdxm = buf; 1846 jdxn = buf + m; 1847 } else { 1848 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1849 jdxm = bufm; 1850 jdxn = bufn; 1851 } 1852 for (i = 0; i < m; i++) { 1853 for (j = 0; j < 3 - sdim; j++) dxm++; 1854 tmp = *dxm++ - starts[0]; 1855 for (j = 0; j < sdim - 1; j++) { 1856 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1857 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1858 } 1859 dxm++; 1860 jdxm[i] = tmp; 1861 } 1862 for (i = 0; i < n; i++) { 1863 for (j = 0; j < 3 - sdim; j++) dxn++; 1864 tmp = *dxn++ - starts[0]; 1865 for (j = 0; j < sdim - 1; j++) { 1866 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1867 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1868 } 1869 dxn++; 1870 jdxn[i] = tmp; 1871 } 1872 PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv)); 1873 PetscCall(PetscFree2(bufm, bufn)); 1874 PetscFunctionReturn(PETSC_SUCCESS); 1875 } 1876 1877 /*@ 1878 MatSetStencil - Sets the grid information for setting values into a matrix via 1879 `MatSetValuesStencil()` 1880 1881 Not Collective 1882 1883 Input Parameters: 1884 + mat - the matrix 1885 . dim - dimension of the grid 1, 2, or 3 1886 . dims - number of grid points in x, y, and z direction, including ghost points on your processor 1887 . starts - starting point of ghost nodes on your processor in x, y, and z direction 1888 - dof - number of degrees of freedom per node 1889 1890 Level: beginner 1891 1892 Notes: 1893 Inspired by the structured grid interface to the HYPRE package 1894 (www.llnl.gov/CASC/hyper) 1895 1896 For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the 1897 user. 1898 1899 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1900 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()` 1901 @*/ 1902 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof) 1903 { 1904 PetscFunctionBegin; 1905 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1906 PetscValidIntPointer(dims, 3); 1907 PetscValidIntPointer(starts, 4); 1908 1909 mat->stencil.dim = dim + (dof > 1); 1910 for (PetscInt i = 0; i < dim; i++) { 1911 mat->stencil.dims[i] = dims[dim - i - 1]; /* copy the values in backwards */ 1912 mat->stencil.starts[i] = starts[dim - i - 1]; 1913 } 1914 mat->stencil.dims[dim] = dof; 1915 mat->stencil.starts[dim] = 0; 1916 mat->stencil.noc = (PetscBool)(dof == 1); 1917 PetscFunctionReturn(PETSC_SUCCESS); 1918 } 1919 1920 /*@C 1921 MatSetValuesBlocked - Inserts or adds a block of values into a matrix. 1922 1923 Not Collective 1924 1925 Input Parameters: 1926 + mat - the matrix 1927 . v - a logically two-dimensional array of values 1928 . m - the number of block rows 1929 . idxm - the global block indices 1930 . n - the number of block columns 1931 . idxn - the global block indices 1932 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values 1933 1934 Level: intermediate 1935 1936 Notes: 1937 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call 1938 MatXXXXSetPreallocation() or `MatSetUp()` before using this routine. 1939 1940 The `m` and `n` count the NUMBER of blocks in the row direction and column direction, 1941 NOT the total number of rows/columns; for example, if the block size is 2 and 1942 you are passing in values for rows 2,3,4,5 then m would be 2 (not 4). 1943 The values in idxm would be 1 2; that is the first index for each block divided by 1944 the block size. 1945 1946 You must call `MatSetBlockSize()` when constructing this matrix (before 1947 preallocating it). 1948 1949 By default the values, `v`, are row-oriented, so the layout of 1950 `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options. 1951 1952 Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES` 1953 options cannot be mixed without intervening calls to the assembly 1954 routines. 1955 1956 `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran 1957 as well as in C. 1958 1959 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1960 simply ignored. This allows easily inserting element stiffness matrices 1961 with homogeneous Dirchlet boundary conditions that you don't want represented 1962 in the matrix. 1963 1964 Each time an entry is set within a sparse matrix via `MatSetValues()`, 1965 internal searching must be done to determine where to place the 1966 data in the matrix storage space. By instead inserting blocks of 1967 entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is 1968 reduced. 1969 1970 Example: 1971 .vb 1972 Suppose m=n=2 and block size(bs) = 2 The array is 1973 1974 1 2 | 3 4 1975 5 6 | 7 8 1976 - - - | - - - 1977 9 10 | 11 12 1978 13 14 | 15 16 1979 1980 v[] should be passed in like 1981 v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] 1982 1983 If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then 1984 v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16] 1985 .ve 1986 1987 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()` 1988 @*/ 1989 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1990 { 1991 PetscFunctionBeginHot; 1992 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1993 PetscValidType(mat, 1); 1994 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1995 PetscValidIntPointer(idxm, 3); 1996 PetscValidIntPointer(idxn, 5); 1997 MatCheckPreallocated(mat, 1); 1998 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1999 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2000 if (PetscDefined(USE_DEBUG)) { 2001 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2002 PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2003 } 2004 if (PetscDefined(USE_DEBUG)) { 2005 PetscInt rbs, cbs, M, N, i; 2006 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 2007 PetscCall(MatGetSize(mat, &M, &N)); 2008 for (i = 0; i < m; i++) PetscCheck(idxm[i] * rbs < M, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row block index %" PetscInt_FMT " (index %" PetscInt_FMT ") greater than row length %" PetscInt_FMT, i, idxm[i], M); 2009 for (i = 0; i < n; i++) PetscCheck(idxn[i] * cbs < N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column block index %" PetscInt_FMT " (index %" PetscInt_FMT ") great than column length %" PetscInt_FMT, i, idxn[i], N); 2010 } 2011 if (mat->assembled) { 2012 mat->was_assembled = PETSC_TRUE; 2013 mat->assembled = PETSC_FALSE; 2014 } 2015 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2016 if (mat->ops->setvaluesblocked) { 2017 PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv); 2018 } else { 2019 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn; 2020 PetscInt i, j, bs, cbs; 2021 2022 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 2023 if (m * bs + n * cbs <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2024 iidxm = buf; 2025 iidxn = buf + m * bs; 2026 } else { 2027 PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc)); 2028 iidxm = bufr; 2029 iidxn = bufc; 2030 } 2031 for (i = 0; i < m; i++) { 2032 for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j; 2033 } 2034 if (m != n || bs != cbs || idxm != idxn) { 2035 for (i = 0; i < n; i++) { 2036 for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j; 2037 } 2038 } else iidxn = iidxm; 2039 PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv)); 2040 PetscCall(PetscFree2(bufr, bufc)); 2041 } 2042 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2043 PetscFunctionReturn(PETSC_SUCCESS); 2044 } 2045 2046 /*@C 2047 MatGetValues - Gets a block of local values from a matrix. 2048 2049 Not Collective; can only return values that are owned by the give process 2050 2051 Input Parameters: 2052 + mat - the matrix 2053 . v - a logically two-dimensional array for storing the values 2054 . m - the number of rows 2055 . idxm - the global indices of the rows 2056 . n - the number of columns 2057 - idxn - the global indices of the columns 2058 2059 Level: advanced 2060 2061 Notes: 2062 The user must allocate space (m*n `PetscScalar`s) for the values, `v`. 2063 The values, `v`, are then returned in a row-oriented format, 2064 analogous to that used by default in `MatSetValues()`. 2065 2066 `MatGetValues()` uses 0-based row and column numbers in 2067 Fortran as well as in C. 2068 2069 `MatGetValues()` requires that the matrix has been assembled 2070 with `MatAssemblyBegin()`/`MatAssemblyEnd()`. Thus, calls to 2071 `MatSetValues()` and `MatGetValues()` CANNOT be made in succession 2072 without intermediate matrix assembly. 2073 2074 Negative row or column indices will be ignored and those locations in `v` will be 2075 left unchanged. 2076 2077 For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI process. 2078 That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable 2079 from `MatGetOwnershipRange`(mat,&rstart,&rend). 2080 2081 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()` 2082 @*/ 2083 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) 2084 { 2085 PetscFunctionBegin; 2086 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2087 PetscValidType(mat, 1); 2088 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); 2089 PetscValidIntPointer(idxm, 3); 2090 PetscValidIntPointer(idxn, 5); 2091 PetscValidScalarPointer(v, 6); 2092 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2093 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2094 MatCheckPreallocated(mat, 1); 2095 2096 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2097 PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v); 2098 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2099 PetscFunctionReturn(PETSC_SUCCESS); 2100 } 2101 2102 /*@C 2103 MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices 2104 defined previously by `MatSetLocalToGlobalMapping()` 2105 2106 Not Collective 2107 2108 Input Parameters: 2109 + mat - the matrix 2110 . nrow - number of rows 2111 . irow - the row local indices 2112 . ncol - number of columns 2113 - icol - the column local indices 2114 2115 Output Parameter: 2116 . y - a logically two-dimensional array of values 2117 2118 Level: advanced 2119 2120 Notes: 2121 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine. 2122 2123 This routine can only return values that are owned by the requesting MPI process. That is, for standard matrix formats, rows that, in the global numbering, 2124 are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can 2125 determine if the resulting global row associated with the local row r is owned by the requesting MPI process by applying the `ISLocalToGlobalMapping` set 2126 with `MatSetLocalToGlobalMapping()`. 2127 2128 Developer Note: 2129 This is labelled with C so does not automatically generate Fortran stubs and interfaces 2130 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2131 2132 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2133 `MatSetValuesLocal()`, `MatGetValues()` 2134 @*/ 2135 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[]) 2136 { 2137 PetscFunctionBeginHot; 2138 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2139 PetscValidType(mat, 1); 2140 MatCheckPreallocated(mat, 1); 2141 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */ 2142 PetscValidIntPointer(irow, 3); 2143 PetscValidIntPointer(icol, 5); 2144 if (PetscDefined(USE_DEBUG)) { 2145 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2146 PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2147 } 2148 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2149 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2150 if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y); 2151 else { 2152 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm; 2153 if ((nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2154 irowm = buf; 2155 icolm = buf + nrow; 2156 } else { 2157 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2158 irowm = bufr; 2159 icolm = bufc; 2160 } 2161 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping())."); 2162 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping())."); 2163 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm)); 2164 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm)); 2165 PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y)); 2166 PetscCall(PetscFree2(bufr, bufc)); 2167 } 2168 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2169 PetscFunctionReturn(PETSC_SUCCESS); 2170 } 2171 2172 /*@ 2173 MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and 2174 the same size. Currently, this can only be called once and creates the given matrix. 2175 2176 Not Collective 2177 2178 Input Parameters: 2179 + mat - the matrix 2180 . nb - the number of blocks 2181 . bs - the number of rows (and columns) in each block 2182 . rows - a concatenation of the rows for each block 2183 - v - a concatenation of logically two-dimensional arrays of values 2184 2185 Level: advanced 2186 2187 Note: 2188 `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values 2189 2190 In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix. 2191 2192 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 2193 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()` 2194 @*/ 2195 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[]) 2196 { 2197 PetscFunctionBegin; 2198 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2199 PetscValidType(mat, 1); 2200 PetscValidIntPointer(rows, 4); 2201 PetscValidScalarPointer(v, 5); 2202 PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2203 2204 PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0)); 2205 if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v); 2206 else { 2207 for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES)); 2208 } 2209 PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0)); 2210 PetscFunctionReturn(PETSC_SUCCESS); 2211 } 2212 2213 /*@ 2214 MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by 2215 the routine `MatSetValuesLocal()` to allow users to insert matrix entries 2216 using a local (per-processor) numbering. 2217 2218 Not Collective 2219 2220 Input Parameters: 2221 + x - the matrix 2222 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()` 2223 - cmapping - column mapping 2224 2225 Level: intermediate 2226 2227 Note: 2228 If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix 2229 2230 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()` 2231 @*/ 2232 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping) 2233 { 2234 PetscFunctionBegin; 2235 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 2236 PetscValidType(x, 1); 2237 if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2); 2238 if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3); 2239 if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping); 2240 else { 2241 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping)); 2242 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping)); 2243 } 2244 PetscFunctionReturn(PETSC_SUCCESS); 2245 } 2246 2247 /*@ 2248 MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()` 2249 2250 Not Collective 2251 2252 Input Parameter: 2253 . A - the matrix 2254 2255 Output Parameters: 2256 + rmapping - row mapping 2257 - cmapping - column mapping 2258 2259 Level: advanced 2260 2261 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()` 2262 @*/ 2263 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping) 2264 { 2265 PetscFunctionBegin; 2266 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2267 PetscValidType(A, 1); 2268 if (rmapping) { 2269 PetscValidPointer(rmapping, 2); 2270 *rmapping = A->rmap->mapping; 2271 } 2272 if (cmapping) { 2273 PetscValidPointer(cmapping, 3); 2274 *cmapping = A->cmap->mapping; 2275 } 2276 PetscFunctionReturn(PETSC_SUCCESS); 2277 } 2278 2279 /*@ 2280 MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix 2281 2282 Logically Collective 2283 2284 Input Parameters: 2285 + A - the matrix 2286 . rmap - row layout 2287 - cmap - column layout 2288 2289 Level: advanced 2290 2291 Note: 2292 The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called. 2293 2294 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()` 2295 @*/ 2296 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap) 2297 { 2298 PetscFunctionBegin; 2299 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2300 PetscCall(PetscLayoutReference(rmap, &A->rmap)); 2301 PetscCall(PetscLayoutReference(cmap, &A->cmap)); 2302 PetscFunctionReturn(PETSC_SUCCESS); 2303 } 2304 2305 /*@ 2306 MatGetLayouts - Gets the `PetscLayout` objects for rows and columns 2307 2308 Not Collective 2309 2310 Input Parameter: 2311 . A - the matrix 2312 2313 Output Parameters: 2314 + rmap - row layout 2315 - cmap - column layout 2316 2317 Level: advanced 2318 2319 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()` 2320 @*/ 2321 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap) 2322 { 2323 PetscFunctionBegin; 2324 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2325 PetscValidType(A, 1); 2326 if (rmap) { 2327 PetscValidPointer(rmap, 2); 2328 *rmap = A->rmap; 2329 } 2330 if (cmap) { 2331 PetscValidPointer(cmap, 3); 2332 *cmap = A->cmap; 2333 } 2334 PetscFunctionReturn(PETSC_SUCCESS); 2335 } 2336 2337 /*@C 2338 MatSetValuesLocal - Inserts or adds values into certain locations of a matrix, 2339 using a local numbering of the nodes. 2340 2341 Not Collective 2342 2343 Input Parameters: 2344 + mat - the matrix 2345 . nrow - number of rows 2346 . irow - the row local indices 2347 . ncol - number of columns 2348 . icol - the column local indices 2349 . y - a logically two-dimensional array of values 2350 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2351 2352 Level: intermediate 2353 2354 Notes: 2355 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 2356 `MatSetUp()` before using this routine 2357 2358 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine 2359 2360 Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2361 options cannot be mixed without intervening calls to the assembly 2362 routines. 2363 2364 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2365 MUST be called after all calls to `MatSetValuesLocal()` have been completed. 2366 2367 Developer Note: 2368 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2369 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2370 2371 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2372 `MatGetValuesLocal()` 2373 @*/ 2374 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2375 { 2376 PetscFunctionBeginHot; 2377 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2378 PetscValidType(mat, 1); 2379 MatCheckPreallocated(mat, 1); 2380 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2381 PetscValidIntPointer(irow, 3); 2382 PetscValidIntPointer(icol, 5); 2383 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2384 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2385 if (PetscDefined(USE_DEBUG)) { 2386 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2387 PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2388 } 2389 2390 if (mat->assembled) { 2391 mat->was_assembled = PETSC_TRUE; 2392 mat->assembled = PETSC_FALSE; 2393 } 2394 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2395 if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv); 2396 else { 2397 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2398 const PetscInt *irowm, *icolm; 2399 2400 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2401 bufr = buf; 2402 bufc = buf + nrow; 2403 irowm = bufr; 2404 icolm = bufc; 2405 } else { 2406 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2407 irowm = bufr; 2408 icolm = bufc; 2409 } 2410 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr)); 2411 else irowm = irow; 2412 if (mat->cmap->mapping) { 2413 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2414 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc)); 2415 } else icolm = irowm; 2416 } else icolm = icol; 2417 PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv)); 2418 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2419 } 2420 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2421 PetscFunctionReturn(PETSC_SUCCESS); 2422 } 2423 2424 /*@C 2425 MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix, 2426 using a local ordering of the nodes a block at a time. 2427 2428 Not Collective 2429 2430 Input Parameters: 2431 + x - the matrix 2432 . nrow - number of rows 2433 . irow - the row local indices 2434 . ncol - number of columns 2435 . icol - the column local indices 2436 . y - a logically two-dimensional array of values 2437 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2438 2439 Level: intermediate 2440 2441 Notes: 2442 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 2443 `MatSetUp()` before using this routine 2444 2445 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()` 2446 before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the 2447 2448 Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2449 options cannot be mixed without intervening calls to the assembly 2450 routines. 2451 2452 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2453 MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed. 2454 2455 Developer Note: 2456 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2457 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2458 2459 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, 2460 `MatSetValuesLocal()`, `MatSetValuesBlocked()` 2461 @*/ 2462 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2463 { 2464 PetscFunctionBeginHot; 2465 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2466 PetscValidType(mat, 1); 2467 MatCheckPreallocated(mat, 1); 2468 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2469 PetscValidIntPointer(irow, 3); 2470 PetscValidIntPointer(icol, 5); 2471 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2472 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2473 if (PetscDefined(USE_DEBUG)) { 2474 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2475 PetscCheck(mat->ops->setvaluesblockedlocal || mat->ops->setvaluesblocked || mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2476 } 2477 2478 if (mat->assembled) { 2479 mat->was_assembled = PETSC_TRUE; 2480 mat->assembled = PETSC_FALSE; 2481 } 2482 if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */ 2483 PetscInt irbs, rbs; 2484 PetscCall(MatGetBlockSizes(mat, &rbs, NULL)); 2485 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs)); 2486 PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs); 2487 } 2488 if (PetscUnlikelyDebug(mat->cmap->mapping)) { 2489 PetscInt icbs, cbs; 2490 PetscCall(MatGetBlockSizes(mat, NULL, &cbs)); 2491 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs)); 2492 PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs); 2493 } 2494 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2495 if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv); 2496 else { 2497 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2498 const PetscInt *irowm, *icolm; 2499 2500 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2501 bufr = buf; 2502 bufc = buf + nrow; 2503 irowm = bufr; 2504 icolm = bufc; 2505 } else { 2506 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2507 irowm = bufr; 2508 icolm = bufc; 2509 } 2510 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr)); 2511 else irowm = irow; 2512 if (mat->cmap->mapping) { 2513 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2514 PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc)); 2515 } else icolm = irowm; 2516 } else icolm = icol; 2517 PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv)); 2518 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2519 } 2520 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2521 PetscFunctionReturn(PETSC_SUCCESS); 2522 } 2523 2524 /*@ 2525 MatMultDiagonalBlock - Computes the matrix-vector product, y = Dx. Where D is defined by the inode or block structure of the diagonal 2526 2527 Collective 2528 2529 Input Parameters: 2530 + mat - the matrix 2531 - x - the vector to be multiplied 2532 2533 Output Parameter: 2534 . y - the result 2535 2536 Level: developer 2537 2538 Note: 2539 The vectors `x` and `y` cannot be the same. I.e., one cannot 2540 call `MatMultDiagonalBlock`(A,y,y). 2541 2542 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2543 @*/ 2544 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y) 2545 { 2546 PetscFunctionBegin; 2547 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2548 PetscValidType(mat, 1); 2549 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2550 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2551 2552 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2553 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2554 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2555 MatCheckPreallocated(mat, 1); 2556 2557 PetscUseTypeMethod(mat, multdiagonalblock, x, y); 2558 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2559 PetscFunctionReturn(PETSC_SUCCESS); 2560 } 2561 2562 /*@ 2563 MatMult - Computes the matrix-vector product, y = Ax. 2564 2565 Neighbor-wise Collective 2566 2567 Input Parameters: 2568 + mat - the matrix 2569 - x - the vector to be multiplied 2570 2571 Output Parameter: 2572 . y - the result 2573 2574 Level: beginner 2575 2576 Note: 2577 The vectors `x` and `y` cannot be the same. I.e., one cannot 2578 call `MatMult`(A,y,y). 2579 2580 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2581 @*/ 2582 PetscErrorCode MatMult(Mat mat, Vec x, Vec y) 2583 { 2584 PetscFunctionBegin; 2585 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2586 PetscValidType(mat, 1); 2587 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2588 VecCheckAssembled(x); 2589 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2590 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2591 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2592 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2593 PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N); 2594 PetscCheck(mat->rmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, y->map->N); 2595 PetscCheck(mat->cmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, x->map->n); 2596 PetscCheck(mat->rmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, y->map->n); 2597 PetscCall(VecSetErrorIfLocked(y, 3)); 2598 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2599 MatCheckPreallocated(mat, 1); 2600 2601 PetscCall(VecLockReadPush(x)); 2602 PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0)); 2603 PetscUseTypeMethod(mat, mult, x, y); 2604 PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0)); 2605 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2606 PetscCall(VecLockReadPop(x)); 2607 PetscFunctionReturn(PETSC_SUCCESS); 2608 } 2609 2610 /*@ 2611 MatMultTranspose - Computes matrix transpose times a vector y = A^T * x. 2612 2613 Neighbor-wise Collective 2614 2615 Input Parameters: 2616 + mat - the matrix 2617 - x - the vector to be multiplied 2618 2619 Output Parameter: 2620 . y - the result 2621 2622 Level: beginner 2623 2624 Notes: 2625 The vectors `x` and `y` cannot be the same. I.e., one cannot 2626 call `MatMultTranspose`(A,y,y). 2627 2628 For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple, 2629 use `MatMultHermitianTranspose()` 2630 2631 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()` 2632 @*/ 2633 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y) 2634 { 2635 PetscErrorCode (*op)(Mat, Vec, Vec) = NULL; 2636 2637 PetscFunctionBegin; 2638 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2639 PetscValidType(mat, 1); 2640 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2641 VecCheckAssembled(x); 2642 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2643 2644 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2645 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2646 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2647 PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N); 2648 PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N); 2649 PetscCheck(mat->cmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, y->map->n); 2650 PetscCheck(mat->rmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, x->map->n); 2651 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2652 MatCheckPreallocated(mat, 1); 2653 2654 if (!mat->ops->multtranspose) { 2655 if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult; 2656 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s does not have a multiply transpose defined or is symmetric and does not have a multiply defined", ((PetscObject)mat)->type_name); 2657 } else op = mat->ops->multtranspose; 2658 PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0)); 2659 PetscCall(VecLockReadPush(x)); 2660 PetscCall((*op)(mat, x, y)); 2661 PetscCall(VecLockReadPop(x)); 2662 PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0)); 2663 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2664 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2665 PetscFunctionReturn(PETSC_SUCCESS); 2666 } 2667 2668 /*@ 2669 MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector. 2670 2671 Neighbor-wise Collective 2672 2673 Input Parameters: 2674 + mat - the matrix 2675 - x - the vector to be multilplied 2676 2677 Output Parameter: 2678 . y - the result 2679 2680 Level: beginner 2681 2682 Notes: 2683 The vectors `x` and `y` cannot be the same. I.e., one cannot 2684 call `MatMultHermitianTranspose`(A,y,y). 2685 2686 Also called the conjugate transpose, complex conjugate transpose, or adjoint. 2687 2688 For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical. 2689 2690 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()` 2691 @*/ 2692 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y) 2693 { 2694 PetscFunctionBegin; 2695 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2696 PetscValidType(mat, 1); 2697 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2698 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2699 2700 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2701 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2702 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2703 PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N); 2704 PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N); 2705 PetscCheck(mat->cmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, y->map->n); 2706 PetscCheck(mat->rmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, x->map->n); 2707 MatCheckPreallocated(mat, 1); 2708 2709 PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0)); 2710 #if defined(PETSC_USE_COMPLEX) 2711 if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) { 2712 PetscCall(VecLockReadPush(x)); 2713 if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y); 2714 else PetscUseTypeMethod(mat, mult, x, y); 2715 PetscCall(VecLockReadPop(x)); 2716 } else { 2717 Vec w; 2718 PetscCall(VecDuplicate(x, &w)); 2719 PetscCall(VecCopy(x, w)); 2720 PetscCall(VecConjugate(w)); 2721 PetscCall(MatMultTranspose(mat, w, y)); 2722 PetscCall(VecDestroy(&w)); 2723 PetscCall(VecConjugate(y)); 2724 } 2725 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2726 #else 2727 PetscCall(MatMultTranspose(mat, x, y)); 2728 #endif 2729 PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0)); 2730 PetscFunctionReturn(PETSC_SUCCESS); 2731 } 2732 2733 /*@ 2734 MatMultAdd - Computes v3 = v2 + A * v1. 2735 2736 Neighbor-wise Collective 2737 2738 Input Parameters: 2739 + mat - the matrix 2740 . v1 - the vector to be multiplied by `mat` 2741 - v2 - the vector to be added to the result 2742 2743 Output Parameter: 2744 . v3 - the result 2745 2746 Level: beginner 2747 2748 Note: 2749 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2750 call `MatMultAdd`(A,v1,v2,v1). 2751 2752 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()` 2753 @*/ 2754 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2755 { 2756 PetscFunctionBegin; 2757 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2758 PetscValidType(mat, 1); 2759 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2760 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2761 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2762 2763 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2764 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2765 PetscCheck(mat->cmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v1->map->N); 2766 /* PetscCheck(mat->rmap->N == v2->map->N,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v2->map->N); 2767 PetscCheck(mat->rmap->N == v3->map->N,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v3->map->N); */ 2768 PetscCheck(mat->rmap->n == v3->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, v3->map->n); 2769 PetscCheck(mat->rmap->n == v2->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, v2->map->n); 2770 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2771 MatCheckPreallocated(mat, 1); 2772 2773 PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3)); 2774 PetscCall(VecLockReadPush(v1)); 2775 PetscUseTypeMethod(mat, multadd, v1, v2, v3); 2776 PetscCall(VecLockReadPop(v1)); 2777 PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3)); 2778 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2779 PetscFunctionReturn(PETSC_SUCCESS); 2780 } 2781 2782 /*@ 2783 MatMultTransposeAdd - Computes v3 = v2 + A' * v1. 2784 2785 Neighbor-wise Collective 2786 2787 Input Parameters: 2788 + mat - the matrix 2789 . v1 - the vector to be multiplied by the transpose of the matrix 2790 - v2 - the vector to be added to the result 2791 2792 Output Parameter: 2793 . v3 - the result 2794 2795 Level: beginner 2796 2797 Note: 2798 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2799 call `MatMultTransposeAdd`(A,v1,v2,v1). 2800 2801 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2802 @*/ 2803 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2804 { 2805 PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd; 2806 2807 PetscFunctionBegin; 2808 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2809 PetscValidType(mat, 1); 2810 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2811 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2812 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2813 2814 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2815 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2816 PetscCheck(mat->rmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, v1->map->N); 2817 PetscCheck(mat->cmap->N == v2->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v2->map->N); 2818 PetscCheck(mat->cmap->N == v3->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v3->map->N); 2819 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2820 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2821 MatCheckPreallocated(mat, 1); 2822 2823 PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2824 PetscCall(VecLockReadPush(v1)); 2825 PetscCall((*op)(mat, v1, v2, v3)); 2826 PetscCall(VecLockReadPop(v1)); 2827 PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2828 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2829 PetscFunctionReturn(PETSC_SUCCESS); 2830 } 2831 2832 /*@ 2833 MatMultHermitianTransposeAdd - Computes v3 = v2 + A^H * v1. 2834 2835 Neighbor-wise Collective 2836 2837 Input Parameters: 2838 + mat - the matrix 2839 . v1 - the vector to be multiplied by the Hermitian transpose 2840 - v2 - the vector to be added to the result 2841 2842 Output Parameter: 2843 . v3 - the result 2844 2845 Level: beginner 2846 2847 Note: 2848 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2849 call `MatMultHermitianTransposeAdd`(A,v1,v2,v1). 2850 2851 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2852 @*/ 2853 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2854 { 2855 PetscFunctionBegin; 2856 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2857 PetscValidType(mat, 1); 2858 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2859 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2860 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2861 2862 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2863 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2864 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2865 PetscCheck(mat->rmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, v1->map->N); 2866 PetscCheck(mat->cmap->N == v2->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v2->map->N); 2867 PetscCheck(mat->cmap->N == v3->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v3->map->N); 2868 MatCheckPreallocated(mat, 1); 2869 2870 PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2871 PetscCall(VecLockReadPush(v1)); 2872 if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3); 2873 else { 2874 Vec w, z; 2875 PetscCall(VecDuplicate(v1, &w)); 2876 PetscCall(VecCopy(v1, w)); 2877 PetscCall(VecConjugate(w)); 2878 PetscCall(VecDuplicate(v3, &z)); 2879 PetscCall(MatMultTranspose(mat, w, z)); 2880 PetscCall(VecDestroy(&w)); 2881 PetscCall(VecConjugate(z)); 2882 if (v2 != v3) { 2883 PetscCall(VecWAXPY(v3, 1.0, v2, z)); 2884 } else { 2885 PetscCall(VecAXPY(v3, 1.0, z)); 2886 } 2887 PetscCall(VecDestroy(&z)); 2888 } 2889 PetscCall(VecLockReadPop(v1)); 2890 PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2891 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2892 PetscFunctionReturn(PETSC_SUCCESS); 2893 } 2894 2895 /*@C 2896 MatGetFactorType - gets the type of factorization it is 2897 2898 Not Collective 2899 2900 Input Parameter: 2901 . mat - the matrix 2902 2903 Output Parameter: 2904 . t - the type, one of `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2905 2906 Level: intermediate 2907 2908 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2909 `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2910 @*/ 2911 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t) 2912 { 2913 PetscFunctionBegin; 2914 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2915 PetscValidType(mat, 1); 2916 PetscValidPointer(t, 2); 2917 *t = mat->factortype; 2918 PetscFunctionReturn(PETSC_SUCCESS); 2919 } 2920 2921 /*@C 2922 MatSetFactorType - sets the type of factorization it is 2923 2924 Logically Collective 2925 2926 Input Parameters: 2927 + mat - the matrix 2928 - t - the type, one of `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2929 2930 Level: intermediate 2931 2932 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2933 `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2934 @*/ 2935 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t) 2936 { 2937 PetscFunctionBegin; 2938 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2939 PetscValidType(mat, 1); 2940 mat->factortype = t; 2941 PetscFunctionReturn(PETSC_SUCCESS); 2942 } 2943 2944 /*@C 2945 MatGetInfo - Returns information about matrix storage (number of 2946 nonzeros, memory, etc.). 2947 2948 Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag 2949 2950 Input Parameters: 2951 + mat - the matrix 2952 - flag - flag indicating the type of parameters to be returned (`MAT_LOCAL` - local matrix, `MAT_GLOBAL_MAX` - maximum over all processors, `MAT_GLOBAL_SUM` - sum over all processors) 2953 2954 Output Parameter: 2955 . info - matrix information context 2956 2957 Options Database Key: 2958 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT` 2959 2960 Notes: 2961 The `MatInfo` context contains a variety of matrix data, including 2962 number of nonzeros allocated and used, number of mallocs during 2963 matrix assembly, etc. Additional information for factored matrices 2964 is provided (such as the fill ratio, number of mallocs during 2965 factorization, etc.). 2966 2967 Example: 2968 See the file ${PETSC_DIR}/include/petscmat.h for a complete list of 2969 data within the MatInfo context. For example, 2970 .vb 2971 MatInfo info; 2972 Mat A; 2973 double mal, nz_a, nz_u; 2974 2975 MatGetInfo(A, MAT_LOCAL, &info); 2976 mal = info.mallocs; 2977 nz_a = info.nz_allocated; 2978 .ve 2979 2980 Fortran users should declare info as a double precision 2981 array of dimension `MAT_INFO_SIZE`, and then extract the parameters 2982 of interest. See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h 2983 a complete list of parameter names. 2984 .vb 2985 double precision info(MAT_INFO_SIZE) 2986 double precision mal, nz_a 2987 Mat A 2988 integer ierr 2989 2990 call MatGetInfo(A, MAT_LOCAL, info, ierr) 2991 mal = info(MAT_INFO_MALLOCS) 2992 nz_a = info(MAT_INFO_NZ_ALLOCATED) 2993 .ve 2994 2995 Level: intermediate 2996 2997 Developer Note: 2998 The Fortran interface is not autogenerated as the 2999 interface definition cannot be generated correctly [due to `MatInfo` argument] 3000 3001 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()` 3002 @*/ 3003 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info) 3004 { 3005 PetscFunctionBegin; 3006 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3007 PetscValidType(mat, 1); 3008 PetscValidPointer(info, 3); 3009 MatCheckPreallocated(mat, 1); 3010 PetscUseTypeMethod(mat, getinfo, flag, info); 3011 PetscFunctionReturn(PETSC_SUCCESS); 3012 } 3013 3014 /* 3015 This is used by external packages where it is not easy to get the info from the actual 3016 matrix factorization. 3017 */ 3018 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info) 3019 { 3020 PetscFunctionBegin; 3021 PetscCall(PetscMemzero(info, sizeof(MatInfo))); 3022 PetscFunctionReturn(PETSC_SUCCESS); 3023 } 3024 3025 /*@C 3026 MatLUFactor - Performs in-place LU factorization of matrix. 3027 3028 Collective 3029 3030 Input Parameters: 3031 + mat - the matrix 3032 . row - row permutation 3033 . col - column permutation 3034 - info - options for factorization, includes 3035 .vb 3036 fill - expected fill as ratio of original fill. 3037 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3038 Run with the option -info to determine an optimal value to use 3039 .ve 3040 Level: developer 3041 3042 Notes: 3043 Most users should employ the `KSP` interface for linear solvers 3044 instead of working directly with matrix algebra routines such as this. 3045 See, e.g., `KSPCreate()`. 3046 3047 This changes the state of the matrix to a factored matrix; it cannot be used 3048 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3049 3050 This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()` 3051 when not using `KSP`. 3052 3053 Developer Note: 3054 The Fortran interface is not autogenerated as the 3055 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3056 3057 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, 3058 `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3059 @*/ 3060 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3061 { 3062 MatFactorInfo tinfo; 3063 3064 PetscFunctionBegin; 3065 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3066 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3067 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3068 if (info) PetscValidPointer(info, 4); 3069 PetscValidType(mat, 1); 3070 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3071 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3072 MatCheckPreallocated(mat, 1); 3073 if (!info) { 3074 PetscCall(MatFactorInfoInitialize(&tinfo)); 3075 info = &tinfo; 3076 } 3077 3078 PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0)); 3079 PetscUseTypeMethod(mat, lufactor, row, col, info); 3080 PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0)); 3081 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3082 PetscFunctionReturn(PETSC_SUCCESS); 3083 } 3084 3085 /*@C 3086 MatILUFactor - Performs in-place ILU factorization of matrix. 3087 3088 Collective 3089 3090 Input Parameters: 3091 + mat - the matrix 3092 . row - row permutation 3093 . col - column permutation 3094 - info - structure containing 3095 .vb 3096 levels - number of levels of fill. 3097 expected fill - as ratio of original fill. 3098 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 3099 missing diagonal entries) 3100 .ve 3101 3102 Level: developer 3103 3104 Notes: 3105 Most users should employ the `KSP` interface for linear solvers 3106 instead of working directly with matrix algebra routines such as this. 3107 See, e.g., `KSPCreate()`. 3108 3109 Probably really in-place only when level of fill is zero, otherwise allocates 3110 new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()` 3111 when not using `KSP`. 3112 3113 Developer Note: 3114 The Fortran interface is not autogenerated as the 3115 interface definition cannot be generated correctly [due to MatFactorInfo] 3116 3117 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 3118 @*/ 3119 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3120 { 3121 PetscFunctionBegin; 3122 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3123 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3124 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3125 PetscValidPointer(info, 4); 3126 PetscValidType(mat, 1); 3127 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 3128 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3129 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3130 MatCheckPreallocated(mat, 1); 3131 3132 PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0)); 3133 PetscUseTypeMethod(mat, ilufactor, row, col, info); 3134 PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0)); 3135 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3136 PetscFunctionReturn(PETSC_SUCCESS); 3137 } 3138 3139 /*@C 3140 MatLUFactorSymbolic - Performs symbolic LU factorization of matrix. 3141 Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`. 3142 3143 Collective 3144 3145 Input Parameters: 3146 + fact - the factor matrix obtained with `MatGetFactor()` 3147 . mat - the matrix 3148 . row - the row permutation 3149 . col - the column permutation 3150 - info - options for factorization, includes 3151 .vb 3152 fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use 3153 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3154 .ve 3155 3156 Level: developer 3157 3158 Notes: 3159 See [Matrix Factorization](sec_matfactor) for additional information about factorizations 3160 3161 Most users should employ the simplified `KSP` interface for linear solvers 3162 instead of working directly with matrix algebra routines such as this. 3163 See, e.g., `KSPCreate()`. 3164 3165 Developer Note: 3166 The Fortran interface is not autogenerated as the 3167 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3168 3169 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3170 @*/ 3171 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 3172 { 3173 MatFactorInfo tinfo; 3174 3175 PetscFunctionBegin; 3176 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3177 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3178 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 3179 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 3180 if (info) PetscValidPointer(info, 5); 3181 PetscValidType(fact, 1); 3182 PetscValidType(mat, 2); 3183 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3184 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3185 MatCheckPreallocated(mat, 2); 3186 if (!info) { 3187 PetscCall(MatFactorInfoInitialize(&tinfo)); 3188 info = &tinfo; 3189 } 3190 3191 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0)); 3192 PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info); 3193 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0)); 3194 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3195 PetscFunctionReturn(PETSC_SUCCESS); 3196 } 3197 3198 /*@C 3199 MatLUFactorNumeric - Performs numeric LU factorization of a matrix. 3200 Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`. 3201 3202 Collective 3203 3204 Input Parameters: 3205 + fact - the factor matrix obtained with `MatGetFactor()` 3206 . mat - the matrix 3207 - info - options for factorization 3208 3209 Level: developer 3210 3211 Notes: 3212 See `MatLUFactor()` for in-place factorization. See 3213 `MatCholeskyFactorNumeric()` for the symmetric, positive definite case. 3214 3215 Most users should employ the `KSP` interface for linear solvers 3216 instead of working directly with matrix algebra routines such as this. 3217 See, e.g., `KSPCreate()`. 3218 3219 Developer Note: 3220 The Fortran interface is not autogenerated as the 3221 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3222 3223 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()` 3224 @*/ 3225 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3226 { 3227 MatFactorInfo tinfo; 3228 3229 PetscFunctionBegin; 3230 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3231 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3232 PetscValidType(fact, 1); 3233 PetscValidType(mat, 2); 3234 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3235 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, 3236 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3237 3238 MatCheckPreallocated(mat, 2); 3239 if (!info) { 3240 PetscCall(MatFactorInfoInitialize(&tinfo)); 3241 info = &tinfo; 3242 } 3243 3244 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3245 else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0)); 3246 PetscUseTypeMethod(fact, lufactornumeric, mat, info); 3247 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3248 else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0)); 3249 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3250 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3251 PetscFunctionReturn(PETSC_SUCCESS); 3252 } 3253 3254 /*@C 3255 MatCholeskyFactor - Performs in-place Cholesky factorization of a 3256 symmetric matrix. 3257 3258 Collective 3259 3260 Input Parameters: 3261 + mat - the matrix 3262 . perm - row and column permutations 3263 - f - expected fill as ratio of original fill 3264 3265 Level: developer 3266 3267 Notes: 3268 See `MatLUFactor()` for the nonsymmetric case. See also `MatGetFactor()`, 3269 `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`. 3270 3271 Most users should employ the `KSP` interface for linear solvers 3272 instead of working directly with matrix algebra routines such as this. 3273 See, e.g., `KSPCreate()`. 3274 3275 Developer Note: 3276 The Fortran interface is not autogenerated as the 3277 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3278 3279 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()` 3280 `MatGetOrdering()` 3281 @*/ 3282 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info) 3283 { 3284 MatFactorInfo tinfo; 3285 3286 PetscFunctionBegin; 3287 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3288 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2); 3289 if (info) PetscValidPointer(info, 3); 3290 PetscValidType(mat, 1); 3291 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3292 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3293 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3294 MatCheckPreallocated(mat, 1); 3295 if (!info) { 3296 PetscCall(MatFactorInfoInitialize(&tinfo)); 3297 info = &tinfo; 3298 } 3299 3300 PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0)); 3301 PetscUseTypeMethod(mat, choleskyfactor, perm, info); 3302 PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0)); 3303 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3304 PetscFunctionReturn(PETSC_SUCCESS); 3305 } 3306 3307 /*@C 3308 MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization 3309 of a symmetric matrix. 3310 3311 Collective 3312 3313 Input Parameters: 3314 + fact - the factor matrix obtained with `MatGetFactor()` 3315 . mat - the matrix 3316 . perm - row and column permutations 3317 - info - options for factorization, includes 3318 .vb 3319 fill - expected fill as ratio of original fill. 3320 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3321 Run with the option -info to determine an optimal value to use 3322 .ve 3323 3324 Level: developer 3325 3326 Notes: 3327 See `MatLUFactorSymbolic()` for the nonsymmetric case. See also 3328 `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`. 3329 3330 Most users should employ the `KSP` interface for linear solvers 3331 instead of working directly with matrix algebra routines such as this. 3332 See, e.g., `KSPCreate()`. 3333 3334 Developer Note: 3335 The Fortran interface is not autogenerated as the 3336 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3337 3338 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()` 3339 `MatGetOrdering()` 3340 @*/ 3341 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 3342 { 3343 MatFactorInfo tinfo; 3344 3345 PetscFunctionBegin; 3346 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3347 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3348 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 3349 if (info) PetscValidPointer(info, 4); 3350 PetscValidType(fact, 1); 3351 PetscValidType(mat, 2); 3352 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3353 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3354 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3355 MatCheckPreallocated(mat, 2); 3356 if (!info) { 3357 PetscCall(MatFactorInfoInitialize(&tinfo)); 3358 info = &tinfo; 3359 } 3360 3361 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3362 PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info); 3363 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3364 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3365 PetscFunctionReturn(PETSC_SUCCESS); 3366 } 3367 3368 /*@C 3369 MatCholeskyFactorNumeric - Performs numeric Cholesky factorization 3370 of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and 3371 `MatCholeskyFactorSymbolic()`. 3372 3373 Collective 3374 3375 Input Parameters: 3376 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored 3377 . mat - the initial matrix that is to be factored 3378 - info - options for factorization 3379 3380 Level: developer 3381 3382 Note: 3383 Most users should employ the `KSP` interface for linear solvers 3384 instead of working directly with matrix algebra routines such as this. 3385 See, e.g., `KSPCreate()`. 3386 3387 Developer Note: 3388 The Fortran interface is not autogenerated as the 3389 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3390 3391 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()` 3392 @*/ 3393 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3394 { 3395 MatFactorInfo tinfo; 3396 3397 PetscFunctionBegin; 3398 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3399 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3400 PetscValidType(fact, 1); 3401 PetscValidType(mat, 2); 3402 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3403 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, 3404 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3405 MatCheckPreallocated(mat, 2); 3406 if (!info) { 3407 PetscCall(MatFactorInfoInitialize(&tinfo)); 3408 info = &tinfo; 3409 } 3410 3411 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3412 else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0)); 3413 PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info); 3414 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3415 else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0)); 3416 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3417 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3418 PetscFunctionReturn(PETSC_SUCCESS); 3419 } 3420 3421 /*@ 3422 MatQRFactor - Performs in-place QR factorization of matrix. 3423 3424 Collective 3425 3426 Input Parameters: 3427 + mat - the matrix 3428 . col - column permutation 3429 - info - options for factorization, includes 3430 .vb 3431 fill - expected fill as ratio of original fill. 3432 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3433 Run with the option -info to determine an optimal value to use 3434 .ve 3435 3436 Level: developer 3437 3438 Notes: 3439 Most users should employ the `KSP` interface for linear solvers 3440 instead of working directly with matrix algebra routines such as this. 3441 See, e.g., `KSPCreate()`. 3442 3443 This changes the state of the matrix to a factored matrix; it cannot be used 3444 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3445 3446 Developer Note: 3447 The Fortran interface is not autogenerated as the 3448 interface definition cannot be generated correctly [due to MatFactorInfo] 3449 3450 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`, 3451 `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3452 @*/ 3453 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info) 3454 { 3455 PetscFunctionBegin; 3456 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3457 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2); 3458 if (info) PetscValidPointer(info, 3); 3459 PetscValidType(mat, 1); 3460 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3461 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3462 MatCheckPreallocated(mat, 1); 3463 PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0)); 3464 PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info)); 3465 PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0)); 3466 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3467 PetscFunctionReturn(PETSC_SUCCESS); 3468 } 3469 3470 /*@ 3471 MatQRFactorSymbolic - Performs symbolic QR factorization of matrix. 3472 Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`. 3473 3474 Collective 3475 3476 Input Parameters: 3477 + fact - the factor matrix obtained with `MatGetFactor()` 3478 . mat - the matrix 3479 . col - column permutation 3480 - info - options for factorization, includes 3481 .vb 3482 fill - expected fill as ratio of original fill. 3483 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3484 Run with the option -info to determine an optimal value to use 3485 .ve 3486 3487 Level: developer 3488 3489 Note: 3490 Most users should employ the `KSP` interface for linear solvers 3491 instead of working directly with matrix algebra routines such as this. 3492 See, e.g., `KSPCreate()`. 3493 3494 Developer Note: 3495 The Fortran interface is not autogenerated as the 3496 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3497 3498 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3499 @*/ 3500 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info) 3501 { 3502 MatFactorInfo tinfo; 3503 3504 PetscFunctionBegin; 3505 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3506 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3507 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3508 if (info) PetscValidPointer(info, 4); 3509 PetscValidType(fact, 1); 3510 PetscValidType(mat, 2); 3511 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3512 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3513 MatCheckPreallocated(mat, 2); 3514 if (!info) { 3515 PetscCall(MatFactorInfoInitialize(&tinfo)); 3516 info = &tinfo; 3517 } 3518 3519 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3520 PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info)); 3521 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3522 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3523 PetscFunctionReturn(PETSC_SUCCESS); 3524 } 3525 3526 /*@ 3527 MatQRFactorNumeric - Performs numeric QR factorization of a matrix. 3528 Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`. 3529 3530 Collective 3531 3532 Input Parameters: 3533 + fact - the factor matrix obtained with `MatGetFactor()` 3534 . mat - the matrix 3535 - info - options for factorization 3536 3537 Level: developer 3538 3539 Notes: 3540 See `MatQRFactor()` for in-place factorization. 3541 3542 Most users should employ the `KSP` interface for linear solvers 3543 instead of working directly with matrix algebra routines such as this. 3544 See, e.g., `KSPCreate()`. 3545 3546 Developer Note: 3547 The Fortran interface is not autogenerated as the 3548 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3549 3550 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()` 3551 @*/ 3552 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3553 { 3554 MatFactorInfo tinfo; 3555 3556 PetscFunctionBegin; 3557 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3558 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3559 PetscValidType(fact, 1); 3560 PetscValidType(mat, 2); 3561 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3562 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, 3563 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3564 3565 MatCheckPreallocated(mat, 2); 3566 if (!info) { 3567 PetscCall(MatFactorInfoInitialize(&tinfo)); 3568 info = &tinfo; 3569 } 3570 3571 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3572 else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0)); 3573 PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info)); 3574 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3575 else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0)); 3576 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3577 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3578 PetscFunctionReturn(PETSC_SUCCESS); 3579 } 3580 3581 /*@ 3582 MatSolve - Solves A x = b, given a factored matrix. 3583 3584 Neighbor-wise Collective 3585 3586 Input Parameters: 3587 + mat - the factored matrix 3588 - b - the right-hand-side vector 3589 3590 Output Parameter: 3591 . x - the result vector 3592 3593 Level: developer 3594 3595 Notes: 3596 The vectors `b` and `x` cannot be the same. I.e., one cannot 3597 call `MatSolve`(A,x,x). 3598 3599 Most users should employ the `KSP` interface for linear solvers 3600 instead of working directly with matrix algebra routines such as this. 3601 See, e.g., `KSPCreate()`. 3602 3603 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3604 @*/ 3605 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x) 3606 { 3607 PetscFunctionBegin; 3608 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3609 PetscValidType(mat, 1); 3610 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3611 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3612 PetscCheckSameComm(mat, 1, b, 2); 3613 PetscCheckSameComm(mat, 1, x, 3); 3614 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3615 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); 3616 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); 3617 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); 3618 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3619 MatCheckPreallocated(mat, 1); 3620 3621 PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0)); 3622 if (mat->factorerrortype) { 3623 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3624 PetscCall(VecSetInf(x)); 3625 } else PetscUseTypeMethod(mat, solve, b, x); 3626 PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0)); 3627 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3628 PetscFunctionReturn(PETSC_SUCCESS); 3629 } 3630 3631 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans) 3632 { 3633 Vec b, x; 3634 PetscInt N, i; 3635 PetscErrorCode (*f)(Mat, Vec, Vec); 3636 PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE; 3637 3638 PetscFunctionBegin; 3639 if (A->factorerrortype) { 3640 PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype)); 3641 PetscCall(MatSetInf(X)); 3642 PetscFunctionReturn(PETSC_SUCCESS); 3643 } 3644 f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose; 3645 PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 3646 PetscCall(MatBoundToCPU(A, &Abound)); 3647 if (!Abound) { 3648 PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3649 PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3650 } 3651 #if PetscDefined(HAVE_CUDA) 3652 if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B)); 3653 if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X)); 3654 #elif PetscDefined(HAVE_HIP) 3655 if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B)); 3656 if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X)); 3657 #endif 3658 PetscCall(MatGetSize(B, NULL, &N)); 3659 for (i = 0; i < N; i++) { 3660 PetscCall(MatDenseGetColumnVecRead(B, i, &b)); 3661 PetscCall(MatDenseGetColumnVecWrite(X, i, &x)); 3662 PetscCall((*f)(A, b, x)); 3663 PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x)); 3664 PetscCall(MatDenseRestoreColumnVecRead(B, i, &b)); 3665 } 3666 if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B)); 3667 if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X)); 3668 PetscFunctionReturn(PETSC_SUCCESS); 3669 } 3670 3671 /*@ 3672 MatMatSolve - Solves A X = B, given a factored matrix. 3673 3674 Neighbor-wise Collective 3675 3676 Input Parameters: 3677 + A - the factored matrix 3678 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS) 3679 3680 Output Parameter: 3681 . X - the result matrix (dense matrix) 3682 3683 Level: developer 3684 3685 Note: 3686 If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`; 3687 otherwise, `B` and `X` cannot be the same. 3688 3689 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3690 @*/ 3691 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X) 3692 { 3693 PetscFunctionBegin; 3694 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3695 PetscValidType(A, 1); 3696 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3697 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3698 PetscCheckSameComm(A, 1, B, 2); 3699 PetscCheckSameComm(A, 1, X, 3); 3700 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); 3701 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); 3702 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"); 3703 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3704 MatCheckPreallocated(A, 1); 3705 3706 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3707 if (!A->ops->matsolve) { 3708 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name)); 3709 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE)); 3710 } else PetscUseTypeMethod(A, matsolve, B, X); 3711 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3712 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3713 PetscFunctionReturn(PETSC_SUCCESS); 3714 } 3715 3716 /*@ 3717 MatMatSolveTranspose - Solves A^T X = B, given a factored matrix. 3718 3719 Neighbor-wise Collective 3720 3721 Input Parameters: 3722 + A - the factored matrix 3723 - B - the right-hand-side matrix (`MATDENSE` matrix) 3724 3725 Output Parameter: 3726 . X - the result matrix (dense matrix) 3727 3728 Level: developer 3729 3730 Note: 3731 The matrices `B` and `X` cannot be the same. I.e., one cannot 3732 call `MatMatSolveTranspose`(A,X,X). 3733 3734 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()` 3735 @*/ 3736 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X) 3737 { 3738 PetscFunctionBegin; 3739 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3740 PetscValidType(A, 1); 3741 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3742 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3743 PetscCheckSameComm(A, 1, B, 2); 3744 PetscCheckSameComm(A, 1, X, 3); 3745 PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3746 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); 3747 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); 3748 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); 3749 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"); 3750 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3751 MatCheckPreallocated(A, 1); 3752 3753 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3754 if (!A->ops->matsolvetranspose) { 3755 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name)); 3756 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE)); 3757 } else PetscUseTypeMethod(A, matsolvetranspose, B, X); 3758 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3759 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3760 PetscFunctionReturn(PETSC_SUCCESS); 3761 } 3762 3763 /*@ 3764 MatMatTransposeSolve - Solves A X = B^T, given a factored matrix. 3765 3766 Neighbor-wise Collective 3767 3768 Input Parameters: 3769 + A - the factored matrix 3770 - Bt - the transpose of right-hand-side matrix as a `MATDENSE` 3771 3772 Output Parameter: 3773 . X - the result matrix (dense matrix) 3774 3775 Level: developer 3776 3777 Note: 3778 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 3779 format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`. 3780 3781 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3782 @*/ 3783 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X) 3784 { 3785 PetscFunctionBegin; 3786 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3787 PetscValidType(A, 1); 3788 PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2); 3789 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3790 PetscCheckSameComm(A, 1, Bt, 2); 3791 PetscCheckSameComm(A, 1, X, 3); 3792 3793 PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3794 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); 3795 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); 3796 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"); 3797 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3798 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3799 MatCheckPreallocated(A, 1); 3800 3801 PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0)); 3802 PetscUseTypeMethod(A, mattransposesolve, Bt, X); 3803 PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0)); 3804 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3805 PetscFunctionReturn(PETSC_SUCCESS); 3806 } 3807 3808 /*@ 3809 MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or 3810 U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U, 3811 3812 Neighbor-wise Collective 3813 3814 Input Parameters: 3815 + mat - the factored matrix 3816 - b - the right-hand-side vector 3817 3818 Output Parameter: 3819 . x - the result vector 3820 3821 Level: developer 3822 3823 Notes: 3824 `MatSolve()` should be used for most applications, as it performs 3825 a forward solve followed by a backward solve. 3826 3827 The vectors `b` and `x` cannot be the same, i.e., one cannot 3828 call `MatForwardSolve`(A,x,x). 3829 3830 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3831 the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet. 3832 `MatForwardSolve()` solves U^T*D y = b, and 3833 `MatBackwardSolve()` solves U x = y. 3834 Thus they do not provide a symmetric preconditioner. 3835 3836 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatBackwardSolve()` 3837 @*/ 3838 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x) 3839 { 3840 PetscFunctionBegin; 3841 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3842 PetscValidType(mat, 1); 3843 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3844 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3845 PetscCheckSameComm(mat, 1, b, 2); 3846 PetscCheckSameComm(mat, 1, x, 3); 3847 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3848 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); 3849 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); 3850 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); 3851 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3852 MatCheckPreallocated(mat, 1); 3853 3854 PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0)); 3855 PetscUseTypeMethod(mat, forwardsolve, b, x); 3856 PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0)); 3857 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3858 PetscFunctionReturn(PETSC_SUCCESS); 3859 } 3860 3861 /*@ 3862 MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU. 3863 D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U, 3864 3865 Neighbor-wise Collective 3866 3867 Input Parameters: 3868 + mat - the factored matrix 3869 - b - the right-hand-side vector 3870 3871 Output Parameter: 3872 . x - the result vector 3873 3874 Level: developer 3875 3876 Notes: 3877 `MatSolve()` should be used for most applications, as it performs 3878 a forward solve followed by a backward solve. 3879 3880 The vectors `b` and `x` cannot be the same. I.e., one cannot 3881 call `MatBackwardSolve`(A,x,x). 3882 3883 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3884 the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet. 3885 `MatForwardSolve()` solves U^T*D y = b, and 3886 `MatBackwardSolve()` solves U x = y. 3887 Thus they do not provide a symmetric preconditioner. 3888 3889 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatForwardSolve()` 3890 @*/ 3891 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x) 3892 { 3893 PetscFunctionBegin; 3894 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3895 PetscValidType(mat, 1); 3896 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3897 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3898 PetscCheckSameComm(mat, 1, b, 2); 3899 PetscCheckSameComm(mat, 1, x, 3); 3900 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3901 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); 3902 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); 3903 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); 3904 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3905 MatCheckPreallocated(mat, 1); 3906 3907 PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0)); 3908 PetscUseTypeMethod(mat, backwardsolve, b, x); 3909 PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0)); 3910 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3911 PetscFunctionReturn(PETSC_SUCCESS); 3912 } 3913 3914 /*@ 3915 MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix. 3916 3917 Neighbor-wise Collective 3918 3919 Input Parameters: 3920 + mat - the factored matrix 3921 . b - the right-hand-side vector 3922 - y - the vector to be added to 3923 3924 Output Parameter: 3925 . x - the result vector 3926 3927 Level: developer 3928 3929 Note: 3930 The vectors `b` and `x` cannot be the same. I.e., one cannot 3931 call `MatSolveAdd`(A,x,y,x). 3932 3933 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3934 @*/ 3935 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x) 3936 { 3937 PetscScalar one = 1.0; 3938 Vec tmp; 3939 3940 PetscFunctionBegin; 3941 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3942 PetscValidType(mat, 1); 3943 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 3944 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3945 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 3946 PetscCheckSameComm(mat, 1, b, 2); 3947 PetscCheckSameComm(mat, 1, y, 3); 3948 PetscCheckSameComm(mat, 1, x, 4); 3949 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3950 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); 3951 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); 3952 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); 3953 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); 3954 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); 3955 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3956 MatCheckPreallocated(mat, 1); 3957 3958 PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y)); 3959 if (mat->factorerrortype) { 3960 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3961 PetscCall(VecSetInf(x)); 3962 } else if (mat->ops->solveadd) { 3963 PetscUseTypeMethod(mat, solveadd, b, y, x); 3964 } else { 3965 /* do the solve then the add manually */ 3966 if (x != y) { 3967 PetscCall(MatSolve(mat, b, x)); 3968 PetscCall(VecAXPY(x, one, y)); 3969 } else { 3970 PetscCall(VecDuplicate(x, &tmp)); 3971 PetscCall(VecCopy(x, tmp)); 3972 PetscCall(MatSolve(mat, b, x)); 3973 PetscCall(VecAXPY(x, one, tmp)); 3974 PetscCall(VecDestroy(&tmp)); 3975 } 3976 } 3977 PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y)); 3978 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3979 PetscFunctionReturn(PETSC_SUCCESS); 3980 } 3981 3982 /*@ 3983 MatSolveTranspose - Solves A' x = b, given a factored matrix. 3984 3985 Neighbor-wise Collective 3986 3987 Input Parameters: 3988 + mat - the factored matrix 3989 - b - the right-hand-side vector 3990 3991 Output Parameter: 3992 . x - the result vector 3993 3994 Level: developer 3995 3996 Notes: 3997 The vectors `b` and `x` cannot be the same. I.e., one cannot 3998 call `MatSolveTranspose`(A,x,x). 3999 4000 Most users should employ the `KSP` interface for linear solvers 4001 instead of working directly with matrix algebra routines such as this. 4002 See, e.g., `KSPCreate()`. 4003 4004 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()` 4005 @*/ 4006 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x) 4007 { 4008 PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose; 4009 4010 PetscFunctionBegin; 4011 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4012 PetscValidType(mat, 1); 4013 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4014 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 4015 PetscCheckSameComm(mat, 1, b, 2); 4016 PetscCheckSameComm(mat, 1, x, 3); 4017 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4018 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); 4019 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); 4020 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4021 MatCheckPreallocated(mat, 1); 4022 PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0)); 4023 if (mat->factorerrortype) { 4024 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4025 PetscCall(VecSetInf(x)); 4026 } else { 4027 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name); 4028 PetscCall((*f)(mat, b, x)); 4029 } 4030 PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0)); 4031 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4032 PetscFunctionReturn(PETSC_SUCCESS); 4033 } 4034 4035 /*@ 4036 MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a 4037 factored matrix. 4038 4039 Neighbor-wise Collective 4040 4041 Input Parameters: 4042 + mat - the factored matrix 4043 . b - the right-hand-side vector 4044 - y - the vector to be added to 4045 4046 Output Parameter: 4047 . x - the result vector 4048 4049 Level: developer 4050 4051 Note: 4052 The vectors `b` and `x` cannot be the same. I.e., one cannot 4053 call `MatSolveTransposeAdd`(A,x,y,x). 4054 4055 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()` 4056 @*/ 4057 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x) 4058 { 4059 PetscScalar one = 1.0; 4060 Vec tmp; 4061 PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd; 4062 4063 PetscFunctionBegin; 4064 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4065 PetscValidType(mat, 1); 4066 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4067 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4068 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4069 PetscCheckSameComm(mat, 1, b, 2); 4070 PetscCheckSameComm(mat, 1, y, 3); 4071 PetscCheckSameComm(mat, 1, x, 4); 4072 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4073 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); 4074 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); 4075 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); 4076 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); 4077 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4078 MatCheckPreallocated(mat, 1); 4079 4080 PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y)); 4081 if (mat->factorerrortype) { 4082 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4083 PetscCall(VecSetInf(x)); 4084 } else if (f) { 4085 PetscCall((*f)(mat, b, y, x)); 4086 } else { 4087 /* do the solve then the add manually */ 4088 if (x != y) { 4089 PetscCall(MatSolveTranspose(mat, b, x)); 4090 PetscCall(VecAXPY(x, one, y)); 4091 } else { 4092 PetscCall(VecDuplicate(x, &tmp)); 4093 PetscCall(VecCopy(x, tmp)); 4094 PetscCall(MatSolveTranspose(mat, b, x)); 4095 PetscCall(VecAXPY(x, one, tmp)); 4096 PetscCall(VecDestroy(&tmp)); 4097 } 4098 } 4099 PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y)); 4100 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4101 PetscFunctionReturn(PETSC_SUCCESS); 4102 } 4103 4104 /*@ 4105 MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps. 4106 4107 Neighbor-wise Collective 4108 4109 Input Parameters: 4110 + mat - the matrix 4111 . b - the right hand side 4112 . omega - the relaxation factor 4113 . flag - flag indicating the type of SOR (see below) 4114 . shift - diagonal shift 4115 . its - the number of iterations 4116 - lits - the number of local iterations 4117 4118 Output Parameter: 4119 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess) 4120 4121 SOR Flags: 4122 + `SOR_FORWARD_SWEEP` - forward SOR 4123 . `SOR_BACKWARD_SWEEP` - backward SOR 4124 . `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR) 4125 . `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR 4126 . `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR 4127 . `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR 4128 . `SOR_EISENSTAT` - SOR with Eisenstat trick 4129 . `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies 4130 upper/lower triangular part of matrix to 4131 vector (with omega) 4132 - `SOR_ZERO_INITIAL_GUESS` - zero initial guess 4133 4134 Level: developer 4135 4136 Notes: 4137 `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and 4138 `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings 4139 on each processor. 4140 4141 Application programmers will not generally use `MatSOR()` directly, 4142 but instead will employ the `KSP`/`PC` interface. 4143 4144 For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing 4145 4146 Most users should employ the `KSP` interface for linear solvers 4147 instead of working directly with matrix algebra routines such as this. 4148 See, e.g., `KSPCreate()`. 4149 4150 Vectors `x` and `b` CANNOT be the same 4151 4152 The flags are implemented as bitwise inclusive or operations. 4153 For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`) 4154 to specify a zero initial guess for SSOR. 4155 4156 Developer Note: 4157 We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes 4158 4159 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()` 4160 @*/ 4161 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x) 4162 { 4163 PetscFunctionBegin; 4164 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4165 PetscValidType(mat, 1); 4166 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4167 PetscValidHeaderSpecific(x, VEC_CLASSID, 8); 4168 PetscCheckSameComm(mat, 1, b, 2); 4169 PetscCheckSameComm(mat, 1, x, 8); 4170 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4171 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4172 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); 4173 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); 4174 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); 4175 PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its); 4176 PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits); 4177 PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same"); 4178 4179 MatCheckPreallocated(mat, 1); 4180 PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0)); 4181 PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x); 4182 PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0)); 4183 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4184 PetscFunctionReturn(PETSC_SUCCESS); 4185 } 4186 4187 /* 4188 Default matrix copy routine. 4189 */ 4190 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str) 4191 { 4192 PetscInt i, rstart = 0, rend = 0, nz; 4193 const PetscInt *cwork; 4194 const PetscScalar *vwork; 4195 4196 PetscFunctionBegin; 4197 if (B->assembled) PetscCall(MatZeroEntries(B)); 4198 if (str == SAME_NONZERO_PATTERN) { 4199 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 4200 for (i = rstart; i < rend; i++) { 4201 PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork)); 4202 PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES)); 4203 PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork)); 4204 } 4205 } else { 4206 PetscCall(MatAYPX(B, 0.0, A, str)); 4207 } 4208 PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 4209 PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 4210 PetscFunctionReturn(PETSC_SUCCESS); 4211 } 4212 4213 /*@ 4214 MatCopy - Copies a matrix to another matrix. 4215 4216 Collective 4217 4218 Input Parameters: 4219 + A - the matrix 4220 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN` 4221 4222 Output Parameter: 4223 . B - where the copy is put 4224 4225 Level: intermediate 4226 4227 Notes: 4228 If you use `SAME_NONZERO_PATTERN` then the two matrices must have the same nonzero pattern or the routine will crash. 4229 4230 `MatCopy()` copies the matrix entries of a matrix to another existing 4231 matrix (after first zeroing the second matrix). A related routine is 4232 `MatConvert()`, which first creates a new matrix and then copies the data. 4233 4234 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()` 4235 @*/ 4236 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str) 4237 { 4238 PetscInt i; 4239 4240 PetscFunctionBegin; 4241 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 4242 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 4243 PetscValidType(A, 1); 4244 PetscValidType(B, 2); 4245 PetscCheckSameComm(A, 1, B, 2); 4246 MatCheckPreallocated(B, 2); 4247 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4248 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4249 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, 4250 A->cmap->N, B->cmap->N); 4251 MatCheckPreallocated(A, 1); 4252 if (A == B) PetscFunctionReturn(PETSC_SUCCESS); 4253 4254 PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0)); 4255 if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str); 4256 else PetscCall(MatCopy_Basic(A, B, str)); 4257 4258 B->stencil.dim = A->stencil.dim; 4259 B->stencil.noc = A->stencil.noc; 4260 for (i = 0; i <= A->stencil.dim; i++) { 4261 B->stencil.dims[i] = A->stencil.dims[i]; 4262 B->stencil.starts[i] = A->stencil.starts[i]; 4263 } 4264 4265 PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0)); 4266 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4267 PetscFunctionReturn(PETSC_SUCCESS); 4268 } 4269 4270 /*@C 4271 MatConvert - Converts a matrix to another matrix, either of the same 4272 or different type. 4273 4274 Collective 4275 4276 Input Parameters: 4277 + mat - the matrix 4278 . newtype - new matrix type. Use `MATSAME` to create a new matrix of the 4279 same type as the original matrix. 4280 - reuse - denotes if the destination matrix is to be created or reused. 4281 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 4282 `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). 4283 4284 Output Parameter: 4285 . M - pointer to place new matrix 4286 4287 Level: intermediate 4288 4289 Notes: 4290 `MatConvert()` first creates a new matrix and then copies the data from 4291 the first matrix. A related routine is `MatCopy()`, which copies the matrix 4292 entries of one matrix to another already existing matrix context. 4293 4294 Cannot be used to convert a sequential matrix to parallel or parallel to sequential, 4295 the MPI communicator of the generated matrix is always the same as the communicator 4296 of the input matrix. 4297 4298 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 4299 @*/ 4300 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M) 4301 { 4302 PetscBool sametype, issame, flg; 4303 PetscBool3 issymmetric, ishermitian; 4304 char convname[256], mtype[256]; 4305 Mat B; 4306 4307 PetscFunctionBegin; 4308 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4309 PetscValidType(mat, 1); 4310 PetscValidPointer(M, 4); 4311 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4312 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4313 MatCheckPreallocated(mat, 1); 4314 4315 PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg)); 4316 if (flg) newtype = mtype; 4317 4318 PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype)); 4319 PetscCall(PetscStrcmp(newtype, "same", &issame)); 4320 PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix"); 4321 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"); 4322 4323 if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) { 4324 PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4325 PetscFunctionReturn(PETSC_SUCCESS); 4326 } 4327 4328 /* Cache Mat options because some converters use MatHeaderReplace */ 4329 issymmetric = mat->symmetric; 4330 ishermitian = mat->hermitian; 4331 4332 if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) { 4333 PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4334 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4335 } else { 4336 PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL; 4337 const char *prefix[3] = {"seq", "mpi", ""}; 4338 PetscInt i; 4339 /* 4340 Order of precedence: 4341 0) See if newtype is a superclass of the current matrix. 4342 1) See if a specialized converter is known to the current matrix. 4343 2) See if a specialized converter is known to the desired matrix class. 4344 3) See if a good general converter is registered for the desired class 4345 (as of 6/27/03 only MATMPIADJ falls into this category). 4346 4) See if a good general converter is known for the current matrix. 4347 5) Use a really basic converter. 4348 */ 4349 4350 /* 0) See if newtype is a superclass of the current matrix. 4351 i.e mat is mpiaij and newtype is aij */ 4352 for (i = 0; i < 2; i++) { 4353 PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname))); 4354 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4355 PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg)); 4356 PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg)); 4357 if (flg) { 4358 if (reuse == MAT_INPLACE_MATRIX) { 4359 PetscCall(PetscInfo(mat, "Early return\n")); 4360 PetscFunctionReturn(PETSC_SUCCESS); 4361 } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) { 4362 PetscCall(PetscInfo(mat, "Calling MatDuplicate\n")); 4363 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4364 PetscFunctionReturn(PETSC_SUCCESS); 4365 } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) { 4366 PetscCall(PetscInfo(mat, "Calling MatCopy\n")); 4367 PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN)); 4368 PetscFunctionReturn(PETSC_SUCCESS); 4369 } 4370 } 4371 } 4372 /* 1) See if a specialized converter is known to the current matrix and the desired class */ 4373 for (i = 0; i < 3; i++) { 4374 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4375 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4376 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4377 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4378 PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname))); 4379 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4380 PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv)); 4381 PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv)); 4382 if (conv) goto foundconv; 4383 } 4384 4385 /* 2) See if a specialized converter is known to the desired matrix class. */ 4386 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B)); 4387 PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 4388 PetscCall(MatSetType(B, newtype)); 4389 for (i = 0; i < 3; i++) { 4390 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4391 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4392 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4393 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4394 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4395 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4396 PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv)); 4397 PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv)); 4398 if (conv) { 4399 PetscCall(MatDestroy(&B)); 4400 goto foundconv; 4401 } 4402 } 4403 4404 /* 3) See if a good general converter is registered for the desired class */ 4405 conv = B->ops->convertfrom; 4406 PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv)); 4407 PetscCall(MatDestroy(&B)); 4408 if (conv) goto foundconv; 4409 4410 /* 4) See if a good general converter is known for the current matrix */ 4411 if (mat->ops->convert) conv = mat->ops->convert; 4412 PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv)); 4413 if (conv) goto foundconv; 4414 4415 /* 5) Use a really basic converter. */ 4416 PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n")); 4417 conv = MatConvert_Basic; 4418 4419 foundconv: 4420 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4421 PetscCall((*conv)(mat, newtype, reuse, M)); 4422 if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) { 4423 /* the block sizes must be same if the mappings are copied over */ 4424 (*M)->rmap->bs = mat->rmap->bs; 4425 (*M)->cmap->bs = mat->cmap->bs; 4426 PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping)); 4427 PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping)); 4428 (*M)->rmap->mapping = mat->rmap->mapping; 4429 (*M)->cmap->mapping = mat->cmap->mapping; 4430 } 4431 (*M)->stencil.dim = mat->stencil.dim; 4432 (*M)->stencil.noc = mat->stencil.noc; 4433 for (i = 0; i <= mat->stencil.dim; i++) { 4434 (*M)->stencil.dims[i] = mat->stencil.dims[i]; 4435 (*M)->stencil.starts[i] = mat->stencil.starts[i]; 4436 } 4437 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4438 } 4439 PetscCall(PetscObjectStateIncrease((PetscObject)*M)); 4440 4441 /* Copy Mat options */ 4442 if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE)); 4443 else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE)); 4444 if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE)); 4445 else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE)); 4446 PetscFunctionReturn(PETSC_SUCCESS); 4447 } 4448 4449 /*@C 4450 MatFactorGetSolverType - Returns name of the package providing the factorization routines 4451 4452 Not Collective 4453 4454 Input Parameter: 4455 . mat - the matrix, must be a factored matrix 4456 4457 Output Parameter: 4458 . type - the string name of the package (do not free this string) 4459 4460 Level: intermediate 4461 4462 Fortran Note: 4463 Pass in an empty string and the package name will be copied into it. Make sure the string is long enough. 4464 4465 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()` 4466 @*/ 4467 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type) 4468 { 4469 PetscErrorCode (*conv)(Mat, MatSolverType *); 4470 4471 PetscFunctionBegin; 4472 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4473 PetscValidType(mat, 1); 4474 PetscValidPointer(type, 2); 4475 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 4476 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv)); 4477 if (conv) PetscCall((*conv)(mat, type)); 4478 else *type = MATSOLVERPETSC; 4479 PetscFunctionReturn(PETSC_SUCCESS); 4480 } 4481 4482 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType; 4483 struct _MatSolverTypeForSpecifcType { 4484 MatType mtype; 4485 /* no entry for MAT_FACTOR_NONE */ 4486 PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *); 4487 MatSolverTypeForSpecifcType next; 4488 }; 4489 4490 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder; 4491 struct _MatSolverTypeHolder { 4492 char *name; 4493 MatSolverTypeForSpecifcType handlers; 4494 MatSolverTypeHolder next; 4495 }; 4496 4497 static MatSolverTypeHolder MatSolverTypeHolders = NULL; 4498 4499 /*@C 4500 MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type 4501 4502 Input Parameters: 4503 + package - name of the package, for example petsc or superlu 4504 . mtype - the matrix type that works with this package 4505 . ftype - the type of factorization supported by the package 4506 - createfactor - routine that will create the factored matrix ready to be used 4507 4508 Level: developer 4509 4510 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()` 4511 @*/ 4512 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *)) 4513 { 4514 MatSolverTypeHolder next = MatSolverTypeHolders, prev = NULL; 4515 PetscBool flg; 4516 MatSolverTypeForSpecifcType inext, iprev = NULL; 4517 4518 PetscFunctionBegin; 4519 PetscCall(MatInitializePackage()); 4520 if (!next) { 4521 PetscCall(PetscNew(&MatSolverTypeHolders)); 4522 PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name)); 4523 PetscCall(PetscNew(&MatSolverTypeHolders->handlers)); 4524 PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype)); 4525 MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor; 4526 PetscFunctionReturn(PETSC_SUCCESS); 4527 } 4528 while (next) { 4529 PetscCall(PetscStrcasecmp(package, next->name, &flg)); 4530 if (flg) { 4531 PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers"); 4532 inext = next->handlers; 4533 while (inext) { 4534 PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg)); 4535 if (flg) { 4536 inext->createfactor[(int)ftype - 1] = createfactor; 4537 PetscFunctionReturn(PETSC_SUCCESS); 4538 } 4539 iprev = inext; 4540 inext = inext->next; 4541 } 4542 PetscCall(PetscNew(&iprev->next)); 4543 PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype)); 4544 iprev->next->createfactor[(int)ftype - 1] = createfactor; 4545 PetscFunctionReturn(PETSC_SUCCESS); 4546 } 4547 prev = next; 4548 next = next->next; 4549 } 4550 PetscCall(PetscNew(&prev->next)); 4551 PetscCall(PetscStrallocpy(package, &prev->next->name)); 4552 PetscCall(PetscNew(&prev->next->handlers)); 4553 PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype)); 4554 prev->next->handlers->createfactor[(int)ftype - 1] = createfactor; 4555 PetscFunctionReturn(PETSC_SUCCESS); 4556 } 4557 4558 /*@C 4559 MatSolverTypeGet - Gets the function that creates the factor matrix if it exist 4560 4561 Input Parameters: 4562 + type - name of the package, for example petsc or superlu 4563 . ftype - the type of factorization supported by the type 4564 - mtype - the matrix type that works with this type 4565 4566 Output Parameters: 4567 + foundtype - `PETSC_TRUE` if the type was registered 4568 . foundmtype - `PETSC_TRUE` if the type supports the requested mtype 4569 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found 4570 4571 Level: developer 4572 4573 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()` 4574 @*/ 4575 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *)) 4576 { 4577 MatSolverTypeHolder next = MatSolverTypeHolders; 4578 PetscBool flg; 4579 MatSolverTypeForSpecifcType inext; 4580 4581 PetscFunctionBegin; 4582 if (foundtype) *foundtype = PETSC_FALSE; 4583 if (foundmtype) *foundmtype = PETSC_FALSE; 4584 if (createfactor) *createfactor = NULL; 4585 4586 if (type) { 4587 while (next) { 4588 PetscCall(PetscStrcasecmp(type, next->name, &flg)); 4589 if (flg) { 4590 if (foundtype) *foundtype = PETSC_TRUE; 4591 inext = next->handlers; 4592 while (inext) { 4593 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4594 if (flg) { 4595 if (foundmtype) *foundmtype = PETSC_TRUE; 4596 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4597 PetscFunctionReturn(PETSC_SUCCESS); 4598 } 4599 inext = inext->next; 4600 } 4601 } 4602 next = next->next; 4603 } 4604 } else { 4605 while (next) { 4606 inext = next->handlers; 4607 while (inext) { 4608 PetscCall(PetscStrcmp(mtype, inext->mtype, &flg)); 4609 if (flg && inext->createfactor[(int)ftype - 1]) { 4610 if (foundtype) *foundtype = PETSC_TRUE; 4611 if (foundmtype) *foundmtype = PETSC_TRUE; 4612 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4613 PetscFunctionReturn(PETSC_SUCCESS); 4614 } 4615 inext = inext->next; 4616 } 4617 next = next->next; 4618 } 4619 /* try with base classes inext->mtype */ 4620 next = MatSolverTypeHolders; 4621 while (next) { 4622 inext = next->handlers; 4623 while (inext) { 4624 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4625 if (flg && inext->createfactor[(int)ftype - 1]) { 4626 if (foundtype) *foundtype = PETSC_TRUE; 4627 if (foundmtype) *foundmtype = PETSC_TRUE; 4628 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4629 PetscFunctionReturn(PETSC_SUCCESS); 4630 } 4631 inext = inext->next; 4632 } 4633 next = next->next; 4634 } 4635 } 4636 PetscFunctionReturn(PETSC_SUCCESS); 4637 } 4638 4639 PetscErrorCode MatSolverTypeDestroy(void) 4640 { 4641 MatSolverTypeHolder next = MatSolverTypeHolders, prev; 4642 MatSolverTypeForSpecifcType inext, iprev; 4643 4644 PetscFunctionBegin; 4645 while (next) { 4646 PetscCall(PetscFree(next->name)); 4647 inext = next->handlers; 4648 while (inext) { 4649 PetscCall(PetscFree(inext->mtype)); 4650 iprev = inext; 4651 inext = inext->next; 4652 PetscCall(PetscFree(iprev)); 4653 } 4654 prev = next; 4655 next = next->next; 4656 PetscCall(PetscFree(prev)); 4657 } 4658 MatSolverTypeHolders = NULL; 4659 PetscFunctionReturn(PETSC_SUCCESS); 4660 } 4661 4662 /*@C 4663 MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4664 4665 Logically Collective 4666 4667 Input Parameter: 4668 . mat - the matrix 4669 4670 Output Parameter: 4671 . flg - `PETSC_TRUE` if uses the ordering 4672 4673 Level: developer 4674 4675 Note: 4676 Most internal PETSc factorizations use the ordering passed to the factorization routine but external 4677 packages do not, thus we want to skip generating the ordering when it is not needed or used. 4678 4679 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4680 @*/ 4681 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg) 4682 { 4683 PetscFunctionBegin; 4684 *flg = mat->canuseordering; 4685 PetscFunctionReturn(PETSC_SUCCESS); 4686 } 4687 4688 /*@C 4689 MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object 4690 4691 Logically Collective 4692 4693 Input Parameters: 4694 + mat - the matrix obtained with `MatGetFactor()` 4695 - ftype - the factorization type to be used 4696 4697 Output Parameter: 4698 . otype - the preferred ordering type 4699 4700 Level: developer 4701 4702 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4703 @*/ 4704 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype) 4705 { 4706 PetscFunctionBegin; 4707 *otype = mat->preferredordering[ftype]; 4708 PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering"); 4709 PetscFunctionReturn(PETSC_SUCCESS); 4710 } 4711 4712 /*@C 4713 MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic() 4714 4715 Collective 4716 4717 Input Parameters: 4718 + mat - the matrix 4719 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4720 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4721 4722 Output Parameter: 4723 . f - the factor matrix used with MatXXFactorSymbolic() calls. Can be `NULL` in some cases, see notes below. 4724 4725 Options Database Key: 4726 . -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory. 4727 One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices. 4728 4729 Level: intermediate 4730 4731 Notes: 4732 The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization 4733 types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime. 4734 4735 Users usually access the factorization solvers via `KSP` 4736 4737 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4738 such as pastix, superlu, mumps etc. 4739 4740 PETSc must have been ./configure to use the external solver, using the option --download-package 4741 4742 Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption 4743 where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set 4744 call `MatSetOptionsPrefixFactor()` on the originating matrix or `MatSetOptionsPrefix()` on the resulting factor matrix. 4745 4746 Developer Note: 4747 This should actually be called `MatCreateFactor()` since it creates a new factor object 4748 4749 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, 4750 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4751 @*/ 4752 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f) 4753 { 4754 PetscBool foundtype, foundmtype; 4755 PetscErrorCode (*conv)(Mat, MatFactorType, Mat *); 4756 4757 PetscFunctionBegin; 4758 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4759 PetscValidType(mat, 1); 4760 4761 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4762 MatCheckPreallocated(mat, 1); 4763 4764 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv)); 4765 if (!foundtype) { 4766 if (type) { 4767 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], 4768 ((PetscObject)mat)->type_name, type); 4769 } else { 4770 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); 4771 } 4772 } 4773 PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name); 4774 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); 4775 4776 PetscCall((*conv)(mat, ftype, f)); 4777 if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix)); 4778 PetscFunctionReturn(PETSC_SUCCESS); 4779 } 4780 4781 /*@C 4782 MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type 4783 4784 Not Collective 4785 4786 Input Parameters: 4787 + mat - the matrix 4788 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4789 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4790 4791 Output Parameter: 4792 . flg - PETSC_TRUE if the factorization is available 4793 4794 Level: intermediate 4795 4796 Notes: 4797 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4798 such as pastix, superlu, mumps etc. 4799 4800 PETSc must have been ./configure to use the external solver, using the option --download-package 4801 4802 Developer Note: 4803 This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object 4804 4805 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactor()`, `MatSolverTypeRegister()`, 4806 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4807 @*/ 4808 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg) 4809 { 4810 PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *); 4811 4812 PetscFunctionBegin; 4813 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4814 PetscValidType(mat, 1); 4815 PetscValidBoolPointer(flg, 4); 4816 4817 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4818 MatCheckPreallocated(mat, 1); 4819 4820 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv)); 4821 *flg = gconv ? PETSC_TRUE : PETSC_FALSE; 4822 PetscFunctionReturn(PETSC_SUCCESS); 4823 } 4824 4825 /*@ 4826 MatDuplicate - Duplicates a matrix including the non-zero structure. 4827 4828 Collective 4829 4830 Input Parameters: 4831 + mat - the matrix 4832 - op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`. 4833 See the manual page for `MatDuplicateOption()` for an explanation of these options. 4834 4835 Output Parameter: 4836 . M - pointer to place new matrix 4837 4838 Level: intermediate 4839 4840 Notes: 4841 You cannot change the nonzero pattern for the parent or child matrix if you use `MAT_SHARE_NONZERO_PATTERN`. 4842 4843 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. 4844 4845 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 4846 is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated. 4847 User should not use `MatDuplicate()` to create new matrix M if M is intended to be reused as the product of matrix operation. 4848 4849 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption` 4850 @*/ 4851 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M) 4852 { 4853 Mat B; 4854 VecType vtype; 4855 PetscInt i; 4856 PetscObject dm, container_h, container_d; 4857 void (*viewf)(void); 4858 4859 PetscFunctionBegin; 4860 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4861 PetscValidType(mat, 1); 4862 PetscValidPointer(M, 3); 4863 PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix"); 4864 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4865 MatCheckPreallocated(mat, 1); 4866 4867 *M = NULL; 4868 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4869 PetscUseTypeMethod(mat, duplicate, op, M); 4870 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4871 B = *M; 4872 4873 PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf)); 4874 if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf)); 4875 PetscCall(MatGetVecType(mat, &vtype)); 4876 PetscCall(MatSetVecType(B, vtype)); 4877 4878 B->stencil.dim = mat->stencil.dim; 4879 B->stencil.noc = mat->stencil.noc; 4880 for (i = 0; i <= mat->stencil.dim; i++) { 4881 B->stencil.dims[i] = mat->stencil.dims[i]; 4882 B->stencil.starts[i] = mat->stencil.starts[i]; 4883 } 4884 4885 B->nooffproczerorows = mat->nooffproczerorows; 4886 B->nooffprocentries = mat->nooffprocentries; 4887 4888 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm)); 4889 if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm)); 4890 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h)); 4891 if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h)); 4892 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d)); 4893 if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d)); 4894 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4895 PetscFunctionReturn(PETSC_SUCCESS); 4896 } 4897 4898 /*@ 4899 MatGetDiagonal - Gets the diagonal of a matrix as a `Vec` 4900 4901 Logically Collective 4902 4903 Input Parameter: 4904 . mat - the matrix 4905 4906 Output Parameter: 4907 . v - the diagonal of the matrix 4908 4909 Level: intermediate 4910 4911 Note: 4912 If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries 4913 of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v` 4914 is larger than `ndiag`, the values of the remaining entries are unspecified. 4915 4916 Currently only correct in parallel for square matrices. 4917 4918 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()` 4919 @*/ 4920 PetscErrorCode MatGetDiagonal(Mat mat, Vec v) 4921 { 4922 PetscFunctionBegin; 4923 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4924 PetscValidType(mat, 1); 4925 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4926 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4927 MatCheckPreallocated(mat, 1); 4928 if (PetscDefined(USE_DEBUG)) { 4929 PetscInt nv, row, col, ndiag; 4930 4931 PetscCall(VecGetLocalSize(v, &nv)); 4932 PetscCall(MatGetLocalSize(mat, &row, &col)); 4933 ndiag = PetscMin(row, col); 4934 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); 4935 } 4936 4937 PetscUseTypeMethod(mat, getdiagonal, v); 4938 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4939 PetscFunctionReturn(PETSC_SUCCESS); 4940 } 4941 4942 /*@C 4943 MatGetRowMin - Gets the minimum value (of the real part) of each 4944 row of the matrix 4945 4946 Logically Collective 4947 4948 Input Parameter: 4949 . mat - the matrix 4950 4951 Output Parameters: 4952 + v - the vector for storing the maximums 4953 - idx - the indices of the column found for each row (optional) 4954 4955 Level: intermediate 4956 4957 Note: 4958 The result of this call are the same as if one converted the matrix to dense format 4959 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 4960 4961 This code is only implemented for a couple of matrix formats. 4962 4963 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, 4964 `MatGetRowMax()` 4965 @*/ 4966 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[]) 4967 { 4968 PetscFunctionBegin; 4969 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4970 PetscValidType(mat, 1); 4971 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4972 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4973 4974 if (!mat->cmap->N) { 4975 PetscCall(VecSet(v, PETSC_MAX_REAL)); 4976 if (idx) { 4977 PetscInt i, m = mat->rmap->n; 4978 for (i = 0; i < m; i++) idx[i] = -1; 4979 } 4980 } else { 4981 MatCheckPreallocated(mat, 1); 4982 } 4983 PetscUseTypeMethod(mat, getrowmin, v, idx); 4984 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4985 PetscFunctionReturn(PETSC_SUCCESS); 4986 } 4987 4988 /*@C 4989 MatGetRowMinAbs - Gets the minimum value (in absolute value) of each 4990 row of the matrix 4991 4992 Logically Collective 4993 4994 Input Parameter: 4995 . mat - the matrix 4996 4997 Output Parameters: 4998 + v - the vector for storing the minimums 4999 - idx - the indices of the column found for each row (or `NULL` if not needed) 5000 5001 Level: intermediate 5002 5003 Notes: 5004 if a row is completely empty or has only 0.0 values then the idx[] value for that 5005 row is 0 (the first column). 5006 5007 This code is only implemented for a couple of matrix formats. 5008 5009 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()` 5010 @*/ 5011 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[]) 5012 { 5013 PetscFunctionBegin; 5014 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5015 PetscValidType(mat, 1); 5016 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5017 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5018 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5019 5020 if (!mat->cmap->N) { 5021 PetscCall(VecSet(v, 0.0)); 5022 if (idx) { 5023 PetscInt i, m = mat->rmap->n; 5024 for (i = 0; i < m; i++) idx[i] = -1; 5025 } 5026 } else { 5027 MatCheckPreallocated(mat, 1); 5028 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5029 PetscUseTypeMethod(mat, getrowminabs, v, idx); 5030 } 5031 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5032 PetscFunctionReturn(PETSC_SUCCESS); 5033 } 5034 5035 /*@C 5036 MatGetRowMax - Gets the maximum value (of the real part) of each 5037 row of the matrix 5038 5039 Logically Collective 5040 5041 Input Parameter: 5042 . mat - the matrix 5043 5044 Output Parameters: 5045 + v - the vector for storing the maximums 5046 - idx - the indices of the column found for each row (optional) 5047 5048 Level: intermediate 5049 5050 Notes: 5051 The result of this call are the same as if one converted the matrix to dense format 5052 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5053 5054 This code is only implemented for a couple of matrix formats. 5055 5056 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5057 @*/ 5058 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[]) 5059 { 5060 PetscFunctionBegin; 5061 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5062 PetscValidType(mat, 1); 5063 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5064 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5065 5066 if (!mat->cmap->N) { 5067 PetscCall(VecSet(v, PETSC_MIN_REAL)); 5068 if (idx) { 5069 PetscInt i, m = mat->rmap->n; 5070 for (i = 0; i < m; i++) idx[i] = -1; 5071 } 5072 } else { 5073 MatCheckPreallocated(mat, 1); 5074 PetscUseTypeMethod(mat, getrowmax, v, idx); 5075 } 5076 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5077 PetscFunctionReturn(PETSC_SUCCESS); 5078 } 5079 5080 /*@C 5081 MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each 5082 row of the matrix 5083 5084 Logically Collective 5085 5086 Input Parameter: 5087 . mat - the matrix 5088 5089 Output Parameters: 5090 + v - the vector for storing the maximums 5091 - idx - the indices of the column found for each row (or `NULL` if not needed) 5092 5093 Level: intermediate 5094 5095 Notes: 5096 if a row is completely empty or has only 0.0 values then the idx[] value for that 5097 row is 0 (the first column). 5098 5099 This code is only implemented for a couple of matrix formats. 5100 5101 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5102 @*/ 5103 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[]) 5104 { 5105 PetscFunctionBegin; 5106 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5107 PetscValidType(mat, 1); 5108 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5109 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5110 5111 if (!mat->cmap->N) { 5112 PetscCall(VecSet(v, 0.0)); 5113 if (idx) { 5114 PetscInt i, m = mat->rmap->n; 5115 for (i = 0; i < m; i++) idx[i] = -1; 5116 } 5117 } else { 5118 MatCheckPreallocated(mat, 1); 5119 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5120 PetscUseTypeMethod(mat, getrowmaxabs, v, idx); 5121 } 5122 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5123 PetscFunctionReturn(PETSC_SUCCESS); 5124 } 5125 5126 /*@ 5127 MatGetRowSum - Gets the sum of each row of the matrix 5128 5129 Logically or Neighborhood Collective 5130 5131 Input Parameter: 5132 . mat - the matrix 5133 5134 Output Parameter: 5135 . v - the vector for storing the sum of rows 5136 5137 Level: intermediate 5138 5139 Notes: 5140 This code is slow since it is not currently specialized for different formats 5141 5142 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()` 5143 @*/ 5144 PetscErrorCode MatGetRowSum(Mat mat, Vec v) 5145 { 5146 Vec ones; 5147 5148 PetscFunctionBegin; 5149 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5150 PetscValidType(mat, 1); 5151 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5152 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5153 MatCheckPreallocated(mat, 1); 5154 PetscCall(MatCreateVecs(mat, &ones, NULL)); 5155 PetscCall(VecSet(ones, 1.)); 5156 PetscCall(MatMult(mat, ones, v)); 5157 PetscCall(VecDestroy(&ones)); 5158 PetscFunctionReturn(PETSC_SUCCESS); 5159 } 5160 5161 /*@ 5162 MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) 5163 when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B) 5164 5165 Collective 5166 5167 Input Parameter: 5168 . mat - the matrix to provide the transpose 5169 5170 Output Parameter: 5171 . 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 5172 5173 Level: advanced 5174 5175 Note: 5176 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 5177 routine allows bypassing that call. 5178 5179 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5180 @*/ 5181 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B) 5182 { 5183 PetscContainer rB = NULL; 5184 MatParentState *rb = NULL; 5185 5186 PetscFunctionBegin; 5187 PetscCall(PetscNew(&rb)); 5188 rb->id = ((PetscObject)mat)->id; 5189 rb->state = 0; 5190 PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate)); 5191 PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB)); 5192 PetscCall(PetscContainerSetPointer(rB, rb)); 5193 PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault)); 5194 PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB)); 5195 PetscCall(PetscObjectDereference((PetscObject)rB)); 5196 PetscFunctionReturn(PETSC_SUCCESS); 5197 } 5198 5199 /*@ 5200 MatTranspose - Computes an in-place or out-of-place transpose of a matrix. 5201 5202 Collective 5203 5204 Input Parameters: 5205 + mat - the matrix to transpose 5206 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5207 5208 Output Parameter: 5209 . B - the transpose 5210 5211 Level: intermediate 5212 5213 Notes: 5214 If you use `MAT_INPLACE_MATRIX` then you must pass in &mat for B 5215 5216 `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 5217 transpose, call `MatTransposeSetPrecursor`(mat,B) before calling this routine. 5218 5219 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. 5220 5221 Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed. 5222 5223 If mat is unchanged from the last call this function returns immediately without recomputing the result 5224 5225 If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()` 5226 5227 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`, 5228 `MatTransposeSymbolic()`, `MatCreateTranspose()` 5229 @*/ 5230 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B) 5231 { 5232 PetscContainer rB = NULL; 5233 MatParentState *rb = NULL; 5234 5235 PetscFunctionBegin; 5236 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5237 PetscValidType(mat, 1); 5238 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5239 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5240 PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first"); 5241 PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX"); 5242 MatCheckPreallocated(mat, 1); 5243 if (reuse == MAT_REUSE_MATRIX) { 5244 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5245 PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor()."); 5246 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5247 PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5248 if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS); 5249 } 5250 5251 PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0)); 5252 if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) { 5253 PetscUseTypeMethod(mat, transpose, reuse, B); 5254 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5255 } 5256 PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0)); 5257 5258 if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B)); 5259 if (reuse != MAT_INPLACE_MATRIX) { 5260 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5261 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5262 rb->state = ((PetscObject)mat)->state; 5263 rb->nonzerostate = mat->nonzerostate; 5264 } 5265 PetscFunctionReturn(PETSC_SUCCESS); 5266 } 5267 5268 /*@ 5269 MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix. 5270 5271 Collective 5272 5273 Input Parameter: 5274 . A - the matrix to transpose 5275 5276 Output Parameter: 5277 . 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 5278 numerical portion. 5279 5280 Level: intermediate 5281 5282 Note: 5283 This is not supported for many matrix types, use `MatTranspose()` in those cases 5284 5285 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5286 @*/ 5287 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B) 5288 { 5289 PetscFunctionBegin; 5290 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5291 PetscValidType(A, 1); 5292 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5293 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5294 PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0)); 5295 PetscUseTypeMethod(A, transposesymbolic, B); 5296 PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0)); 5297 5298 PetscCall(MatTransposeSetPrecursor(A, *B)); 5299 PetscFunctionReturn(PETSC_SUCCESS); 5300 } 5301 5302 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B) 5303 { 5304 PetscContainer rB; 5305 MatParentState *rb; 5306 5307 PetscFunctionBegin; 5308 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5309 PetscValidType(A, 1); 5310 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5311 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5312 PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB)); 5313 PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()"); 5314 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5315 PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5316 PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure"); 5317 PetscFunctionReturn(PETSC_SUCCESS); 5318 } 5319 5320 /*@ 5321 MatIsTranspose - Test whether a matrix is another one's transpose, 5322 or its own, in which case it tests symmetry. 5323 5324 Collective 5325 5326 Input Parameters: 5327 + A - the matrix to test 5328 . B - the matrix to test against, this can equal the first parameter 5329 - tol - tolerance, differences between entries smaller than this are counted as zero 5330 5331 Output Parameter: 5332 . flg - the result 5333 5334 Level: intermediate 5335 5336 Notes: 5337 Only available for `MATAIJ` matrices. 5338 5339 The sequential algorithm has a running time of the order of the number of nonzeros; the parallel 5340 test involves parallel copies of the block-offdiagonal parts of the matrix. 5341 5342 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()` 5343 @*/ 5344 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5345 { 5346 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5347 5348 PetscFunctionBegin; 5349 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5350 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5351 PetscValidBoolPointer(flg, 4); 5352 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f)); 5353 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g)); 5354 *flg = PETSC_FALSE; 5355 if (f && g) { 5356 PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test"); 5357 PetscCall((*f)(A, B, tol, flg)); 5358 } else { 5359 MatType mattype; 5360 5361 PetscCall(MatGetType(f ? B : A, &mattype)); 5362 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype); 5363 } 5364 PetscFunctionReturn(PETSC_SUCCESS); 5365 } 5366 5367 /*@ 5368 MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate. 5369 5370 Collective 5371 5372 Input Parameters: 5373 + mat - the matrix to transpose and complex conjugate 5374 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5375 5376 Output Parameter: 5377 . B - the Hermitian transpose 5378 5379 Level: intermediate 5380 5381 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse` 5382 @*/ 5383 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B) 5384 { 5385 PetscFunctionBegin; 5386 PetscCall(MatTranspose(mat, reuse, B)); 5387 #if defined(PETSC_USE_COMPLEX) 5388 PetscCall(MatConjugate(*B)); 5389 #endif 5390 PetscFunctionReturn(PETSC_SUCCESS); 5391 } 5392 5393 /*@ 5394 MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose, 5395 5396 Collective 5397 5398 Input Parameters: 5399 + A - the matrix to test 5400 . B - the matrix to test against, this can equal the first parameter 5401 - tol - tolerance, differences between entries smaller than this are counted as zero 5402 5403 Output Parameter: 5404 . flg - the result 5405 5406 Level: intermediate 5407 5408 Notes: 5409 Only available for `MATAIJ` matrices. 5410 5411 The sequential algorithm 5412 has a running time of the order of the number of nonzeros; the parallel 5413 test involves parallel copies of the block-offdiagonal parts of the matrix. 5414 5415 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()` 5416 @*/ 5417 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5418 { 5419 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5420 5421 PetscFunctionBegin; 5422 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5423 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5424 PetscValidBoolPointer(flg, 4); 5425 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f)); 5426 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g)); 5427 if (f && g) { 5428 PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test"); 5429 PetscCall((*f)(A, B, tol, flg)); 5430 } 5431 PetscFunctionReturn(PETSC_SUCCESS); 5432 } 5433 5434 /*@ 5435 MatPermute - Creates a new matrix with rows and columns permuted from the 5436 original. 5437 5438 Collective 5439 5440 Input Parameters: 5441 + mat - the matrix to permute 5442 . row - row permutation, each processor supplies only the permutation for its rows 5443 - col - column permutation, each processor supplies only the permutation for its columns 5444 5445 Output Parameter: 5446 . B - the permuted matrix 5447 5448 Level: advanced 5449 5450 Note: 5451 The index sets map from row/col of permuted matrix to row/col of original matrix. 5452 The index sets should be on the same communicator as mat and have the same local sizes. 5453 5454 Developer Note: 5455 If you want to implement `MatPermute()` for a matrix type, and your approach doesn't 5456 exploit the fact that row and col are permutations, consider implementing the 5457 more general `MatCreateSubMatrix()` instead. 5458 5459 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()` 5460 @*/ 5461 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B) 5462 { 5463 PetscFunctionBegin; 5464 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5465 PetscValidType(mat, 1); 5466 PetscValidHeaderSpecific(row, IS_CLASSID, 2); 5467 PetscValidHeaderSpecific(col, IS_CLASSID, 3); 5468 PetscValidPointer(B, 4); 5469 PetscCheckSameComm(mat, 1, row, 2); 5470 if (row != col) PetscCheckSameComm(row, 2, col, 3); 5471 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5472 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5473 PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name); 5474 MatCheckPreallocated(mat, 1); 5475 5476 if (mat->ops->permute) { 5477 PetscUseTypeMethod(mat, permute, row, col, B); 5478 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5479 } else { 5480 PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B)); 5481 } 5482 PetscFunctionReturn(PETSC_SUCCESS); 5483 } 5484 5485 /*@ 5486 MatEqual - Compares two matrices. 5487 5488 Collective 5489 5490 Input Parameters: 5491 + A - the first matrix 5492 - B - the second matrix 5493 5494 Output Parameter: 5495 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise. 5496 5497 Level: intermediate 5498 5499 .seealso: [](ch_matrices), `Mat` 5500 @*/ 5501 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg) 5502 { 5503 PetscFunctionBegin; 5504 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5505 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5506 PetscValidType(A, 1); 5507 PetscValidType(B, 2); 5508 PetscValidBoolPointer(flg, 3); 5509 PetscCheckSameComm(A, 1, B, 2); 5510 MatCheckPreallocated(A, 1); 5511 MatCheckPreallocated(B, 2); 5512 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5513 PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5514 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, 5515 B->cmap->N); 5516 if (A->ops->equal && A->ops->equal == B->ops->equal) { 5517 PetscUseTypeMethod(A, equal, B, flg); 5518 } else { 5519 PetscCall(MatMultEqual(A, B, 10, flg)); 5520 } 5521 PetscFunctionReturn(PETSC_SUCCESS); 5522 } 5523 5524 /*@ 5525 MatDiagonalScale - Scales a matrix on the left and right by diagonal 5526 matrices that are stored as vectors. Either of the two scaling 5527 matrices can be `NULL`. 5528 5529 Collective 5530 5531 Input Parameters: 5532 + mat - the matrix to be scaled 5533 . l - the left scaling vector (or `NULL`) 5534 - r - the right scaling vector (or `NULL`) 5535 5536 Level: intermediate 5537 5538 Note: 5539 `MatDiagonalScale()` computes A = LAR, where 5540 L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector) 5541 The L scales the rows of the matrix, the R scales the columns of the matrix. 5542 5543 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()` 5544 @*/ 5545 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r) 5546 { 5547 PetscFunctionBegin; 5548 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5549 PetscValidType(mat, 1); 5550 if (l) { 5551 PetscValidHeaderSpecific(l, VEC_CLASSID, 2); 5552 PetscCheckSameComm(mat, 1, l, 2); 5553 } 5554 if (r) { 5555 PetscValidHeaderSpecific(r, VEC_CLASSID, 3); 5556 PetscCheckSameComm(mat, 1, r, 3); 5557 } 5558 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5559 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5560 MatCheckPreallocated(mat, 1); 5561 if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS); 5562 5563 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5564 PetscUseTypeMethod(mat, diagonalscale, l, r); 5565 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5566 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5567 if (l != r) mat->symmetric = PETSC_BOOL3_FALSE; 5568 PetscFunctionReturn(PETSC_SUCCESS); 5569 } 5570 5571 /*@ 5572 MatScale - Scales all elements of a matrix by a given number. 5573 5574 Logically Collective 5575 5576 Input Parameters: 5577 + mat - the matrix to be scaled 5578 - a - the scaling value 5579 5580 Level: intermediate 5581 5582 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 5583 @*/ 5584 PetscErrorCode MatScale(Mat mat, PetscScalar a) 5585 { 5586 PetscFunctionBegin; 5587 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5588 PetscValidType(mat, 1); 5589 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5590 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5591 PetscValidLogicalCollectiveScalar(mat, a, 2); 5592 MatCheckPreallocated(mat, 1); 5593 5594 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5595 if (a != (PetscScalar)1.0) { 5596 PetscUseTypeMethod(mat, scale, a); 5597 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5598 } 5599 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5600 PetscFunctionReturn(PETSC_SUCCESS); 5601 } 5602 5603 /*@ 5604 MatNorm - Calculates various norms of a matrix. 5605 5606 Collective 5607 5608 Input Parameters: 5609 + mat - the matrix 5610 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY` 5611 5612 Output Parameter: 5613 . nrm - the resulting norm 5614 5615 Level: intermediate 5616 5617 .seealso: [](ch_matrices), `Mat` 5618 @*/ 5619 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm) 5620 { 5621 PetscFunctionBegin; 5622 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5623 PetscValidType(mat, 1); 5624 PetscValidRealPointer(nrm, 3); 5625 5626 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5627 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5628 MatCheckPreallocated(mat, 1); 5629 5630 PetscUseTypeMethod(mat, norm, type, nrm); 5631 PetscFunctionReturn(PETSC_SUCCESS); 5632 } 5633 5634 /* 5635 This variable is used to prevent counting of MatAssemblyBegin() that 5636 are called from within a MatAssemblyEnd(). 5637 */ 5638 static PetscInt MatAssemblyEnd_InUse = 0; 5639 /*@ 5640 MatAssemblyBegin - Begins assembling the matrix. This routine should 5641 be called after completing all calls to `MatSetValues()`. 5642 5643 Collective 5644 5645 Input Parameters: 5646 + mat - the matrix 5647 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5648 5649 Level: beginner 5650 5651 Notes: 5652 `MatSetValues()` generally caches the values that belong to other MPI processes. The matrix is ready to 5653 use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called. 5654 5655 Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES` 5656 in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before 5657 using the matrix. 5658 5659 ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the 5660 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 5661 a global collective operation requiring all processes that share the matrix. 5662 5663 Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed 5664 out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros 5665 before `MAT_FINAL_ASSEMBLY` so the space is not compressed out. 5666 5667 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()` 5668 @*/ 5669 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type) 5670 { 5671 PetscFunctionBegin; 5672 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5673 PetscValidType(mat, 1); 5674 MatCheckPreallocated(mat, 1); 5675 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?"); 5676 if (mat->assembled) { 5677 mat->was_assembled = PETSC_TRUE; 5678 mat->assembled = PETSC_FALSE; 5679 } 5680 5681 if (!MatAssemblyEnd_InUse) { 5682 PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0)); 5683 PetscTryTypeMethod(mat, assemblybegin, type); 5684 PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0)); 5685 } else PetscTryTypeMethod(mat, assemblybegin, type); 5686 PetscFunctionReturn(PETSC_SUCCESS); 5687 } 5688 5689 /*@ 5690 MatAssembled - Indicates if a matrix has been assembled and is ready for 5691 use; for example, in matrix-vector product. 5692 5693 Not Collective 5694 5695 Input Parameter: 5696 . mat - the matrix 5697 5698 Output Parameter: 5699 . assembled - `PETSC_TRUE` or `PETSC_FALSE` 5700 5701 Level: advanced 5702 5703 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()` 5704 @*/ 5705 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled) 5706 { 5707 PetscFunctionBegin; 5708 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5709 PetscValidBoolPointer(assembled, 2); 5710 *assembled = mat->assembled; 5711 PetscFunctionReturn(PETSC_SUCCESS); 5712 } 5713 5714 /*@ 5715 MatAssemblyEnd - Completes assembling the matrix. This routine should 5716 be called after `MatAssemblyBegin()`. 5717 5718 Collective 5719 5720 Input Parameters: 5721 + mat - the matrix 5722 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5723 5724 Options Database Keys: 5725 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 5726 . -mat_view ::ascii_info_detail - Prints more detailed info 5727 . -mat_view - Prints matrix in ASCII format 5728 . -mat_view ::ascii_matlab - Prints matrix in Matlab format 5729 . -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 5730 . -display <name> - Sets display name (default is host) 5731 . -draw_pause <sec> - Sets number of seconds to pause after display 5732 . -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See [Using MATLAB with PETSc](ch_matlab)) 5733 . -viewer_socket_machine <machine> - Machine to use for socket 5734 . -viewer_socket_port <port> - Port number to use for socket 5735 - -mat_view binary:filename[:append] - Save matrix to file in binary format 5736 5737 Level: beginner 5738 5739 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()` 5740 @*/ 5741 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type) 5742 { 5743 static PetscInt inassm = 0; 5744 PetscBool flg = PETSC_FALSE; 5745 5746 PetscFunctionBegin; 5747 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5748 PetscValidType(mat, 1); 5749 5750 inassm++; 5751 MatAssemblyEnd_InUse++; 5752 if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */ 5753 PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0)); 5754 PetscTryTypeMethod(mat, assemblyend, type); 5755 PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0)); 5756 } else PetscTryTypeMethod(mat, assemblyend, type); 5757 5758 /* Flush assembly is not a true assembly */ 5759 if (type != MAT_FLUSH_ASSEMBLY) { 5760 if (mat->num_ass) { 5761 if (!mat->symmetry_eternal) { 5762 mat->symmetric = PETSC_BOOL3_UNKNOWN; 5763 mat->hermitian = PETSC_BOOL3_UNKNOWN; 5764 } 5765 if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN; 5766 if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN; 5767 } 5768 mat->num_ass++; 5769 mat->assembled = PETSC_TRUE; 5770 mat->ass_nonzerostate = mat->nonzerostate; 5771 } 5772 5773 mat->insertmode = NOT_SET_VALUES; 5774 MatAssemblyEnd_InUse--; 5775 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5776 if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) { 5777 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 5778 5779 if (mat->checksymmetryonassembly) { 5780 PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg)); 5781 if (flg) { 5782 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5783 } else { 5784 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5785 } 5786 } 5787 if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL)); 5788 } 5789 inassm--; 5790 PetscFunctionReturn(PETSC_SUCCESS); 5791 } 5792 5793 /*@ 5794 MatSetOption - Sets a parameter option for a matrix. Some options 5795 may be specific to certain storage formats. Some options 5796 determine how values will be inserted (or added). Sorted, 5797 row-oriented input will generally assemble the fastest. The default 5798 is row-oriented. 5799 5800 Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption` 5801 5802 Input Parameters: 5803 + mat - the matrix 5804 . option - the option, one of those listed below (and possibly others), 5805 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5806 5807 Options Describing Matrix Structure: 5808 + `MAT_SPD` - symmetric positive definite 5809 . `MAT_SYMMETRIC` - symmetric in terms of both structure and value 5810 . `MAT_HERMITIAN` - transpose is the complex conjugation 5811 . `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure 5812 . `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix 5813 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix 5814 - `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix 5815 5816 These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they 5817 do not need to be computed (usually at a high cost) 5818 5819 Options For Use with `MatSetValues()`: 5820 Insert a logically dense subblock, which can be 5821 . `MAT_ROW_ORIENTED` - row-oriented (default) 5822 5823 These options reflect the data you pass in with `MatSetValues()`; it has 5824 nothing to do with how the data is stored internally in the matrix 5825 data structure. 5826 5827 When (re)assembling a matrix, we can restrict the input for 5828 efficiency/debugging purposes. These options include 5829 + `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow) 5830 . `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated 5831 . `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries 5832 . `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry 5833 . `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly 5834 . `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if 5835 any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves 5836 performance for very large process counts. 5837 - `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset 5838 of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly 5839 functions, instead sending only neighbor messages. 5840 5841 Level: intermediate 5842 5843 Notes: 5844 Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg! 5845 5846 Some options are relevant only for particular matrix types and 5847 are thus ignored by others. Other options are not supported by 5848 certain matrix types and will generate an error message if set. 5849 5850 If using Fortran to compute a matrix, one may need to 5851 use the column-oriented option (or convert to the row-oriented 5852 format). 5853 5854 `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion 5855 that would generate a new entry in the nonzero structure is instead 5856 ignored. Thus, if memory has not already been allocated for this particular 5857 data, then the insertion is ignored. For dense matrices, in which 5858 the entire array is allocated, no entries are ever ignored. 5859 Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction 5860 5861 `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion 5862 that would generate a new entry in the nonzero structure instead produces 5863 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 5864 5865 `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion 5866 that would generate a new entry that has not been preallocated will 5867 instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats 5868 only.) This is a useful flag when debugging matrix memory preallocation. 5869 If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 5870 5871 `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for 5872 other processors should be dropped, rather than stashed. 5873 This is useful if you know that the "owning" processor is also 5874 always generating the correct matrix entries, so that PETSc need 5875 not transfer duplicate entries generated on another processor. 5876 5877 `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the 5878 searches during matrix assembly. When this flag is set, the hash table 5879 is created during the first matrix assembly. This hash table is 5880 used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()` 5881 to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag 5882 should be used with `MAT_USE_HASH_TABLE` flag. This option is currently 5883 supported by `MATMPIBAIJ` format only. 5884 5885 `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries 5886 are kept in the nonzero structure 5887 5888 `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating 5889 a zero location in the matrix 5890 5891 `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types 5892 5893 `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the 5894 zero row routines and thus improves performance for very large process counts. 5895 5896 `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular 5897 part of the matrix (since they should match the upper triangular part). 5898 5899 `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a 5900 single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common 5901 with finite difference schemes with non-periodic boundary conditions. 5902 5903 Developer Note: 5904 `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other 5905 places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRIC` or `MAT_SPD` would need to be changed back 5906 to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had 5907 not changed. 5908 5909 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()` 5910 @*/ 5911 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg) 5912 { 5913 PetscFunctionBegin; 5914 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5915 if (op > 0) { 5916 PetscValidLogicalCollectiveEnum(mat, op, 2); 5917 PetscValidLogicalCollectiveBool(mat, flg, 3); 5918 } 5919 5920 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); 5921 5922 switch (op) { 5923 case MAT_FORCE_DIAGONAL_ENTRIES: 5924 mat->force_diagonals = flg; 5925 PetscFunctionReturn(PETSC_SUCCESS); 5926 case MAT_NO_OFF_PROC_ENTRIES: 5927 mat->nooffprocentries = flg; 5928 PetscFunctionReturn(PETSC_SUCCESS); 5929 case MAT_SUBSET_OFF_PROC_ENTRIES: 5930 mat->assembly_subset = flg; 5931 if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */ 5932 #if !defined(PETSC_HAVE_MPIUNI) 5933 PetscCall(MatStashScatterDestroy_BTS(&mat->stash)); 5934 #endif 5935 mat->stash.first_assembly_done = PETSC_FALSE; 5936 } 5937 PetscFunctionReturn(PETSC_SUCCESS); 5938 case MAT_NO_OFF_PROC_ZERO_ROWS: 5939 mat->nooffproczerorows = flg; 5940 PetscFunctionReturn(PETSC_SUCCESS); 5941 case MAT_SPD: 5942 if (flg) { 5943 mat->spd = PETSC_BOOL3_TRUE; 5944 mat->symmetric = PETSC_BOOL3_TRUE; 5945 mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5946 } else { 5947 mat->spd = PETSC_BOOL3_FALSE; 5948 } 5949 break; 5950 case MAT_SYMMETRIC: 5951 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5952 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5953 #if !defined(PETSC_USE_COMPLEX) 5954 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5955 #endif 5956 break; 5957 case MAT_HERMITIAN: 5958 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5959 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5960 #if !defined(PETSC_USE_COMPLEX) 5961 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5962 #endif 5963 break; 5964 case MAT_STRUCTURALLY_SYMMETRIC: 5965 mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5966 break; 5967 case MAT_SYMMETRY_ETERNAL: 5968 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"); 5969 mat->symmetry_eternal = flg; 5970 if (flg) mat->structural_symmetry_eternal = PETSC_TRUE; 5971 break; 5972 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 5973 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"); 5974 mat->structural_symmetry_eternal = flg; 5975 break; 5976 case MAT_SPD_ETERNAL: 5977 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"); 5978 mat->spd_eternal = flg; 5979 if (flg) { 5980 mat->structural_symmetry_eternal = PETSC_TRUE; 5981 mat->symmetry_eternal = PETSC_TRUE; 5982 } 5983 break; 5984 case MAT_STRUCTURE_ONLY: 5985 mat->structure_only = flg; 5986 break; 5987 case MAT_SORTED_FULL: 5988 mat->sortedfull = flg; 5989 break; 5990 default: 5991 break; 5992 } 5993 PetscTryTypeMethod(mat, setoption, op, flg); 5994 PetscFunctionReturn(PETSC_SUCCESS); 5995 } 5996 5997 /*@ 5998 MatGetOption - Gets a parameter option that has been set for a matrix. 5999 6000 Logically Collective 6001 6002 Input Parameters: 6003 + mat - the matrix 6004 - option - the option, this only responds to certain options, check the code for which ones 6005 6006 Output Parameter: 6007 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 6008 6009 Level: intermediate 6010 6011 Notes: 6012 Can only be called after `MatSetSizes()` and `MatSetType()` have been set. 6013 6014 Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or 6015 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6016 6017 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, 6018 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6019 @*/ 6020 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg) 6021 { 6022 PetscFunctionBegin; 6023 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6024 PetscValidType(mat, 1); 6025 6026 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); 6027 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()"); 6028 6029 switch (op) { 6030 case MAT_NO_OFF_PROC_ENTRIES: 6031 *flg = mat->nooffprocentries; 6032 break; 6033 case MAT_NO_OFF_PROC_ZERO_ROWS: 6034 *flg = mat->nooffproczerorows; 6035 break; 6036 case MAT_SYMMETRIC: 6037 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()"); 6038 break; 6039 case MAT_HERMITIAN: 6040 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()"); 6041 break; 6042 case MAT_STRUCTURALLY_SYMMETRIC: 6043 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()"); 6044 break; 6045 case MAT_SPD: 6046 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()"); 6047 break; 6048 case MAT_SYMMETRY_ETERNAL: 6049 *flg = mat->symmetry_eternal; 6050 break; 6051 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6052 *flg = mat->symmetry_eternal; 6053 break; 6054 default: 6055 break; 6056 } 6057 PetscFunctionReturn(PETSC_SUCCESS); 6058 } 6059 6060 /*@ 6061 MatZeroEntries - Zeros all entries of a matrix. For sparse matrices 6062 this routine retains the old nonzero structure. 6063 6064 Logically Collective 6065 6066 Input Parameter: 6067 . mat - the matrix 6068 6069 Level: intermediate 6070 6071 Note: 6072 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. 6073 See the Performance chapter of the users manual for information on preallocating matrices. 6074 6075 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()` 6076 @*/ 6077 PetscErrorCode MatZeroEntries(Mat mat) 6078 { 6079 PetscFunctionBegin; 6080 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6081 PetscValidType(mat, 1); 6082 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6083 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"); 6084 MatCheckPreallocated(mat, 1); 6085 6086 PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0)); 6087 PetscUseTypeMethod(mat, zeroentries); 6088 PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0)); 6089 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6090 PetscFunctionReturn(PETSC_SUCCESS); 6091 } 6092 6093 /*@ 6094 MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal) 6095 of a set of rows and columns of a matrix. 6096 6097 Collective 6098 6099 Input Parameters: 6100 + mat - the matrix 6101 . numRows - the number of rows/columns to zero 6102 . rows - the global row indices 6103 . diag - value put in the diagonal of the eliminated rows 6104 . x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call 6105 - b - optional vector of the right hand side, that will be adjusted by provided solution entries 6106 6107 Level: intermediate 6108 6109 Notes: 6110 This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6111 6112 For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`. 6113 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 6114 6115 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6116 Krylov method to take advantage of the known solution on the zeroed rows. 6117 6118 For the parallel case, all processes that share the matrix (i.e., 6119 those in the communicator used for matrix creation) MUST call this 6120 routine, regardless of whether any rows being zeroed are owned by 6121 them. 6122 6123 Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix. 6124 6125 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6126 list only rows local to itself). 6127 6128 The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine. 6129 6130 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6131 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6132 @*/ 6133 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6134 { 6135 PetscFunctionBegin; 6136 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6137 PetscValidType(mat, 1); 6138 if (numRows) PetscValidIntPointer(rows, 3); 6139 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6140 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6141 MatCheckPreallocated(mat, 1); 6142 6143 PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b); 6144 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6145 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6146 PetscFunctionReturn(PETSC_SUCCESS); 6147 } 6148 6149 /*@ 6150 MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal) 6151 of a set of rows and columns of a matrix. 6152 6153 Collective 6154 6155 Input Parameters: 6156 + mat - the matrix 6157 . is - the rows to zero 6158 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6159 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6160 - b - optional vector of right hand side, that will be adjusted by provided solution 6161 6162 Level: intermediate 6163 6164 Note: 6165 See `MatZeroRowsColumns()` for details on how this routine operates. 6166 6167 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6168 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()` 6169 @*/ 6170 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6171 { 6172 PetscInt numRows; 6173 const PetscInt *rows; 6174 6175 PetscFunctionBegin; 6176 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6177 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6178 PetscValidType(mat, 1); 6179 PetscValidType(is, 2); 6180 PetscCall(ISGetLocalSize(is, &numRows)); 6181 PetscCall(ISGetIndices(is, &rows)); 6182 PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b)); 6183 PetscCall(ISRestoreIndices(is, &rows)); 6184 PetscFunctionReturn(PETSC_SUCCESS); 6185 } 6186 6187 /*@ 6188 MatZeroRows - Zeros all entries (except possibly the main diagonal) 6189 of a set of rows of a matrix. 6190 6191 Collective 6192 6193 Input Parameters: 6194 + mat - the matrix 6195 . numRows - the number of rows to zero 6196 . rows - the global row indices 6197 . diag - value put in the diagonal of the zeroed rows 6198 . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call 6199 - b - optional vector of right hand side, that will be adjusted by provided solution entries 6200 6201 Level: intermediate 6202 6203 Notes: 6204 This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6205 6206 For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`. 6207 6208 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6209 Krylov method to take advantage of the known solution on the zeroed rows. 6210 6211 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) 6212 from the matrix. 6213 6214 Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix 6215 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 6216 formats this does not alter the nonzero structure. 6217 6218 If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure 6219 of the matrix is not changed the values are 6220 merely zeroed. 6221 6222 The user can set a value in the diagonal entry (or for the `MATAIJ` format 6223 formats can optionally remove the main diagonal entry from the 6224 nonzero structure as well, by passing 0.0 as the final argument). 6225 6226 For the parallel case, all processes that share the matrix (i.e., 6227 those in the communicator used for matrix creation) MUST call this 6228 routine, regardless of whether any rows being zeroed are owned by 6229 them. 6230 6231 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6232 list only rows local to itself). 6233 6234 You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it 6235 owns that are to be zeroed. This saves a global synchronization in the implementation. 6236 6237 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6238 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE` 6239 @*/ 6240 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6241 { 6242 PetscFunctionBegin; 6243 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6244 PetscValidType(mat, 1); 6245 if (numRows) PetscValidIntPointer(rows, 3); 6246 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6247 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6248 MatCheckPreallocated(mat, 1); 6249 6250 PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b); 6251 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6252 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6253 PetscFunctionReturn(PETSC_SUCCESS); 6254 } 6255 6256 /*@ 6257 MatZeroRowsIS - Zeros all entries (except possibly the main diagonal) 6258 of a set of rows of a matrix. 6259 6260 Collective 6261 6262 Input Parameters: 6263 + mat - the matrix 6264 . is - index set of rows to remove (if `NULL` then no row is removed) 6265 . diag - value put in all diagonals of eliminated rows 6266 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6267 - b - optional vector of right hand side, that will be adjusted by provided solution 6268 6269 Level: intermediate 6270 6271 Note: 6272 See `MatZeroRows()` for details on how this routine operates. 6273 6274 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6275 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6276 @*/ 6277 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6278 { 6279 PetscInt numRows = 0; 6280 const PetscInt *rows = NULL; 6281 6282 PetscFunctionBegin; 6283 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6284 PetscValidType(mat, 1); 6285 if (is) { 6286 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6287 PetscCall(ISGetLocalSize(is, &numRows)); 6288 PetscCall(ISGetIndices(is, &rows)); 6289 } 6290 PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b)); 6291 if (is) PetscCall(ISRestoreIndices(is, &rows)); 6292 PetscFunctionReturn(PETSC_SUCCESS); 6293 } 6294 6295 /*@ 6296 MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal) 6297 of a set of rows of a matrix. These rows must be local to the process. 6298 6299 Collective 6300 6301 Input Parameters: 6302 + mat - the matrix 6303 . numRows - the number of rows to remove 6304 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6305 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6306 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6307 - b - optional vector of right hand side, that will be adjusted by provided solution 6308 6309 Level: intermediate 6310 6311 Notes: 6312 See `MatZeroRows()` for details on how this routine operates. 6313 6314 The grid coordinates are across the entire grid, not just the local portion 6315 6316 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6317 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6318 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6319 `DM_BOUNDARY_PERIODIC` boundary type. 6320 6321 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 6322 a single value per point) you can skip filling those indices. 6323 6324 Fortran Note: 6325 `idxm` and `idxn` should be declared as 6326 $ MatStencil idxm(4, m) 6327 and the values inserted using 6328 .vb 6329 idxm(MatStencil_i, 1) = i 6330 idxm(MatStencil_j, 1) = j 6331 idxm(MatStencil_k, 1) = k 6332 idxm(MatStencil_c, 1) = c 6333 etc 6334 .ve 6335 6336 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6337 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6338 @*/ 6339 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6340 { 6341 PetscInt dim = mat->stencil.dim; 6342 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6343 PetscInt *dims = mat->stencil.dims + 1; 6344 PetscInt *starts = mat->stencil.starts; 6345 PetscInt *dxm = (PetscInt *)rows; 6346 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6347 6348 PetscFunctionBegin; 6349 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6350 PetscValidType(mat, 1); 6351 if (numRows) PetscValidPointer(rows, 3); 6352 6353 PetscCall(PetscMalloc1(numRows, &jdxm)); 6354 for (i = 0; i < numRows; ++i) { 6355 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6356 for (j = 0; j < 3 - sdim; ++j) dxm++; 6357 /* Local index in X dir */ 6358 tmp = *dxm++ - starts[0]; 6359 /* Loop over remaining dimensions */ 6360 for (j = 0; j < dim - 1; ++j) { 6361 /* If nonlocal, set index to be negative */ 6362 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6363 /* Update local index */ 6364 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6365 } 6366 /* Skip component slot if necessary */ 6367 if (mat->stencil.noc) dxm++; 6368 /* Local row number */ 6369 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6370 } 6371 PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b)); 6372 PetscCall(PetscFree(jdxm)); 6373 PetscFunctionReturn(PETSC_SUCCESS); 6374 } 6375 6376 /*@ 6377 MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal) 6378 of a set of rows and columns of a matrix. 6379 6380 Collective 6381 6382 Input Parameters: 6383 + mat - the matrix 6384 . numRows - the number of rows/columns to remove 6385 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6386 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6387 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6388 - b - optional vector of right hand side, that will be adjusted by provided solution 6389 6390 Level: intermediate 6391 6392 Notes: 6393 See `MatZeroRowsColumns()` for details on how this routine operates. 6394 6395 The grid coordinates are across the entire grid, not just the local portion 6396 6397 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6398 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6399 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6400 `DM_BOUNDARY_PERIODIC` boundary type. 6401 6402 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 6403 a single value per point) you can skip filling those indices. 6404 6405 Fortran Note: 6406 `idxm` and `idxn` should be declared as 6407 $ MatStencil idxm(4, m) 6408 and the values inserted using 6409 .vb 6410 idxm(MatStencil_i, 1) = i 6411 idxm(MatStencil_j, 1) = j 6412 idxm(MatStencil_k, 1) = k 6413 idxm(MatStencil_c, 1) = c 6414 etc 6415 .ve 6416 6417 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6418 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()` 6419 @*/ 6420 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6421 { 6422 PetscInt dim = mat->stencil.dim; 6423 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6424 PetscInt *dims = mat->stencil.dims + 1; 6425 PetscInt *starts = mat->stencil.starts; 6426 PetscInt *dxm = (PetscInt *)rows; 6427 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6428 6429 PetscFunctionBegin; 6430 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6431 PetscValidType(mat, 1); 6432 if (numRows) PetscValidPointer(rows, 3); 6433 6434 PetscCall(PetscMalloc1(numRows, &jdxm)); 6435 for (i = 0; i < numRows; ++i) { 6436 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6437 for (j = 0; j < 3 - sdim; ++j) dxm++; 6438 /* Local index in X dir */ 6439 tmp = *dxm++ - starts[0]; 6440 /* Loop over remaining dimensions */ 6441 for (j = 0; j < dim - 1; ++j) { 6442 /* If nonlocal, set index to be negative */ 6443 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6444 /* Update local index */ 6445 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6446 } 6447 /* Skip component slot if necessary */ 6448 if (mat->stencil.noc) dxm++; 6449 /* Local row number */ 6450 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6451 } 6452 PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b)); 6453 PetscCall(PetscFree(jdxm)); 6454 PetscFunctionReturn(PETSC_SUCCESS); 6455 } 6456 6457 /*@C 6458 MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal) 6459 of a set of rows of a matrix; using local numbering of rows. 6460 6461 Collective 6462 6463 Input Parameters: 6464 + mat - the matrix 6465 . numRows - the number of rows to remove 6466 . rows - the local row indices 6467 . diag - value put in all diagonals of eliminated rows 6468 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6469 - b - optional vector of right hand side, that will be adjusted by provided solution 6470 6471 Level: intermediate 6472 6473 Notes: 6474 Before calling `MatZeroRowsLocal()`, the user must first set the 6475 local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`. 6476 6477 See `MatZeroRows()` for details on how this routine operates. 6478 6479 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`, 6480 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6481 @*/ 6482 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6483 { 6484 PetscFunctionBegin; 6485 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6486 PetscValidType(mat, 1); 6487 if (numRows) PetscValidIntPointer(rows, 3); 6488 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6489 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6490 MatCheckPreallocated(mat, 1); 6491 6492 if (mat->ops->zerorowslocal) { 6493 PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b); 6494 } else { 6495 IS is, newis; 6496 const PetscInt *newRows; 6497 6498 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6499 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6500 PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis)); 6501 PetscCall(ISGetIndices(newis, &newRows)); 6502 PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b); 6503 PetscCall(ISRestoreIndices(newis, &newRows)); 6504 PetscCall(ISDestroy(&newis)); 6505 PetscCall(ISDestroy(&is)); 6506 } 6507 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6508 PetscFunctionReturn(PETSC_SUCCESS); 6509 } 6510 6511 /*@ 6512 MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal) 6513 of a set of rows of a matrix; using local numbering of rows. 6514 6515 Collective 6516 6517 Input Parameters: 6518 + mat - the matrix 6519 . is - index set of rows to remove 6520 . diag - value put in all diagonals of eliminated rows 6521 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6522 - b - optional vector of right hand side, that will be adjusted by provided solution 6523 6524 Level: intermediate 6525 6526 Notes: 6527 Before calling `MatZeroRowsLocalIS()`, the user must first set the 6528 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6529 6530 See `MatZeroRows()` for details on how this routine operates. 6531 6532 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6533 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6534 @*/ 6535 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6536 { 6537 PetscInt numRows; 6538 const PetscInt *rows; 6539 6540 PetscFunctionBegin; 6541 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6542 PetscValidType(mat, 1); 6543 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6544 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6545 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6546 MatCheckPreallocated(mat, 1); 6547 6548 PetscCall(ISGetLocalSize(is, &numRows)); 6549 PetscCall(ISGetIndices(is, &rows)); 6550 PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b)); 6551 PetscCall(ISRestoreIndices(is, &rows)); 6552 PetscFunctionReturn(PETSC_SUCCESS); 6553 } 6554 6555 /*@ 6556 MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal) 6557 of a set of rows and columns of a matrix; using local numbering of rows. 6558 6559 Collective 6560 6561 Input Parameters: 6562 + mat - the matrix 6563 . numRows - the number of rows to remove 6564 . rows - the global row indices 6565 . diag - value put in all diagonals of eliminated rows 6566 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6567 - b - optional vector of right hand side, that will be adjusted by provided solution 6568 6569 Level: intermediate 6570 6571 Notes: 6572 Before calling `MatZeroRowsColumnsLocal()`, the user must first set the 6573 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6574 6575 See `MatZeroRowsColumns()` for details on how this routine operates. 6576 6577 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6578 `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6579 @*/ 6580 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6581 { 6582 IS is, newis; 6583 const PetscInt *newRows; 6584 6585 PetscFunctionBegin; 6586 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6587 PetscValidType(mat, 1); 6588 if (numRows) PetscValidIntPointer(rows, 3); 6589 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6590 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6591 MatCheckPreallocated(mat, 1); 6592 6593 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6594 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6595 PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis)); 6596 PetscCall(ISGetIndices(newis, &newRows)); 6597 PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b); 6598 PetscCall(ISRestoreIndices(newis, &newRows)); 6599 PetscCall(ISDestroy(&newis)); 6600 PetscCall(ISDestroy(&is)); 6601 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6602 PetscFunctionReturn(PETSC_SUCCESS); 6603 } 6604 6605 /*@ 6606 MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal) 6607 of a set of rows and columns of a matrix; using local numbering of rows. 6608 6609 Collective 6610 6611 Input Parameters: 6612 + mat - the matrix 6613 . is - index set of rows to remove 6614 . diag - value put in all diagonals of eliminated rows 6615 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6616 - b - optional vector of right hand side, that will be adjusted by provided solution 6617 6618 Level: intermediate 6619 6620 Notes: 6621 Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the 6622 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6623 6624 See `MatZeroRowsColumns()` for details on how this routine operates. 6625 6626 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6627 `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6628 @*/ 6629 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6630 { 6631 PetscInt numRows; 6632 const PetscInt *rows; 6633 6634 PetscFunctionBegin; 6635 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6636 PetscValidType(mat, 1); 6637 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6638 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6639 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6640 MatCheckPreallocated(mat, 1); 6641 6642 PetscCall(ISGetLocalSize(is, &numRows)); 6643 PetscCall(ISGetIndices(is, &rows)); 6644 PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b)); 6645 PetscCall(ISRestoreIndices(is, &rows)); 6646 PetscFunctionReturn(PETSC_SUCCESS); 6647 } 6648 6649 /*@C 6650 MatGetSize - Returns the numbers of rows and columns in a matrix. 6651 6652 Not Collective 6653 6654 Input Parameter: 6655 . mat - the matrix 6656 6657 Output Parameters: 6658 + m - the number of global rows 6659 - n - the number of global columns 6660 6661 Level: beginner 6662 6663 Note: 6664 Both output parameters can be `NULL` on input. 6665 6666 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()` 6667 @*/ 6668 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n) 6669 { 6670 PetscFunctionBegin; 6671 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6672 if (m) *m = mat->rmap->N; 6673 if (n) *n = mat->cmap->N; 6674 PetscFunctionReturn(PETSC_SUCCESS); 6675 } 6676 6677 /*@C 6678 MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns 6679 of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`. 6680 6681 Not Collective 6682 6683 Input Parameter: 6684 . mat - the matrix 6685 6686 Output Parameters: 6687 + m - the number of local rows, use `NULL` to not obtain this value 6688 - n - the number of local columns, use `NULL` to not obtain this value 6689 6690 Level: beginner 6691 6692 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()` 6693 @*/ 6694 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n) 6695 { 6696 PetscFunctionBegin; 6697 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6698 if (m) PetscValidIntPointer(m, 2); 6699 if (n) PetscValidIntPointer(n, 3); 6700 if (m) *m = mat->rmap->n; 6701 if (n) *n = mat->cmap->n; 6702 PetscFunctionReturn(PETSC_SUCCESS); 6703 } 6704 6705 /*@C 6706 MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by 6707 this processor. (The columns of the "diagonal block" for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts. 6708 6709 Not Collective, unless matrix has not been allocated, then collective 6710 6711 Input Parameter: 6712 . mat - the matrix 6713 6714 Output Parameters: 6715 + m - the global index of the first local column, use `NULL` to not obtain this value 6716 - n - one more than the global index of the last local column, use `NULL` to not obtain this value 6717 6718 Level: developer 6719 6720 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout` 6721 @*/ 6722 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n) 6723 { 6724 PetscFunctionBegin; 6725 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6726 PetscValidType(mat, 1); 6727 if (m) PetscValidIntPointer(m, 2); 6728 if (n) PetscValidIntPointer(n, 3); 6729 MatCheckPreallocated(mat, 1); 6730 if (m) *m = mat->cmap->rstart; 6731 if (n) *n = mat->cmap->rend; 6732 PetscFunctionReturn(PETSC_SUCCESS); 6733 } 6734 6735 /*@C 6736 MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6737 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 6738 vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts 6739 6740 Not Collective 6741 6742 Input Parameter: 6743 . mat - the matrix 6744 6745 Output Parameters: 6746 + m - the global index of the first local row, use `NULL` to not obtain this value 6747 - n - one more than the global index of the last local row, use `NULL` to not obtain this value 6748 6749 Level: beginner 6750 6751 Note: 6752 This function requires that the matrix be preallocated. If you have not preallocated, consider using 6753 `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N) 6754 and then `MPI_Scan()` to calculate prefix sums of the local sizes. 6755 6756 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, 6757 `PetscLayout` 6758 @*/ 6759 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n) 6760 { 6761 PetscFunctionBegin; 6762 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6763 PetscValidType(mat, 1); 6764 if (m) PetscValidIntPointer(m, 2); 6765 if (n) PetscValidIntPointer(n, 3); 6766 MatCheckPreallocated(mat, 1); 6767 if (m) *m = mat->rmap->rstart; 6768 if (n) *n = mat->rmap->rend; 6769 PetscFunctionReturn(PETSC_SUCCESS); 6770 } 6771 6772 /*@C 6773 MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6774 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 6775 vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts 6776 6777 Not Collective, unless matrix has not been allocated 6778 6779 Input Parameter: 6780 . mat - the matrix 6781 6782 Output Parameter: 6783 . ranges - start of each processors portion plus one more than the total length at the end 6784 6785 Level: beginner 6786 6787 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout` 6788 @*/ 6789 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges) 6790 { 6791 PetscFunctionBegin; 6792 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6793 PetscValidType(mat, 1); 6794 MatCheckPreallocated(mat, 1); 6795 PetscCall(PetscLayoutGetRanges(mat->rmap, ranges)); 6796 PetscFunctionReturn(PETSC_SUCCESS); 6797 } 6798 6799 /*@C 6800 MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by 6801 each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts. 6802 6803 Not Collective, unless matrix has not been allocated 6804 6805 Input Parameter: 6806 . mat - the matrix 6807 6808 Output Parameter: 6809 . ranges - start of each processors portion plus one more then the total length at the end 6810 6811 Level: beginner 6812 6813 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()` 6814 @*/ 6815 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges) 6816 { 6817 PetscFunctionBegin; 6818 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6819 PetscValidType(mat, 1); 6820 MatCheckPreallocated(mat, 1); 6821 PetscCall(PetscLayoutGetRanges(mat->cmap, ranges)); 6822 PetscFunctionReturn(PETSC_SUCCESS); 6823 } 6824 6825 /*@C 6826 MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this 6827 corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership 6828 is more complicated. See :any:`<sec_matlayout>` for details on matrix layouts. 6829 6830 Not Collective 6831 6832 Input Parameter: 6833 . A - matrix 6834 6835 Output Parameters: 6836 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value 6837 - cols - columns in which this process owns elements, use `NULL` to not obtain this value 6838 6839 Level: intermediate 6840 6841 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK`` 6842 @*/ 6843 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols) 6844 { 6845 PetscErrorCode (*f)(Mat, IS *, IS *); 6846 6847 PetscFunctionBegin; 6848 MatCheckPreallocated(A, 1); 6849 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f)); 6850 if (f) { 6851 PetscCall((*f)(A, rows, cols)); 6852 } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */ 6853 if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows)); 6854 if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols)); 6855 } 6856 PetscFunctionReturn(PETSC_SUCCESS); 6857 } 6858 6859 /*@C 6860 MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()` 6861 Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()` 6862 to complete the factorization. 6863 6864 Collective 6865 6866 Input Parameters: 6867 + fact - the factorized matrix obtained with `MatGetFactor()` 6868 . mat - the matrix 6869 . row - row permutation 6870 . col - column permutation 6871 - info - structure containing 6872 .vb 6873 levels - number of levels of fill. 6874 expected fill - as ratio of original fill. 6875 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 6876 missing diagonal entries) 6877 .ve 6878 6879 Level: developer 6880 6881 Notes: 6882 See [Matrix Factorization](sec_matfactor) for additional information. 6883 6884 Most users should employ the `KSP` interface for linear solvers 6885 instead of working directly with matrix algebra routines such as this. 6886 See, e.g., `KSPCreate()`. 6887 6888 Uses the definition of level of fill as in Y. Saad, 2003 6889 6890 Developer Note: 6891 The Fortran interface is not autogenerated as the 6892 interface definition cannot be generated correctly [due to `MatFactorInfo`] 6893 6894 References: 6895 . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003 6896 6897 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 6898 `MatGetOrdering()`, `MatFactorInfo` 6899 @*/ 6900 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 6901 { 6902 PetscFunctionBegin; 6903 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 6904 PetscValidType(mat, 2); 6905 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 6906 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 6907 PetscValidPointer(info, 5); 6908 PetscValidPointer(fact, 1); 6909 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels); 6910 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 6911 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6912 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6913 MatCheckPreallocated(mat, 2); 6914 6915 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0)); 6916 PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info); 6917 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0)); 6918 PetscFunctionReturn(PETSC_SUCCESS); 6919 } 6920 6921 /*@C 6922 MatICCFactorSymbolic - Performs symbolic incomplete 6923 Cholesky factorization for a symmetric matrix. Use 6924 `MatCholeskyFactorNumeric()` to complete the factorization. 6925 6926 Collective 6927 6928 Input Parameters: 6929 + fact - the factorized matrix obtained with `MatGetFactor()` 6930 . mat - the matrix to be factored 6931 . perm - row and column permutation 6932 - info - structure containing 6933 .vb 6934 levels - number of levels of fill. 6935 expected fill - as ratio of original fill. 6936 .ve 6937 6938 Level: developer 6939 6940 Notes: 6941 Most users should employ the `KSP` interface for linear solvers 6942 instead of working directly with matrix algebra routines such as this. 6943 See, e.g., `KSPCreate()`. 6944 6945 This uses the definition of level of fill as in Y. Saad, 2003 6946 6947 Developer Note: 6948 The Fortran interface is not autogenerated as the 6949 interface definition cannot be generated correctly [due to `MatFactorInfo`] 6950 6951 References: 6952 . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003 6953 6954 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 6955 @*/ 6956 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 6957 { 6958 PetscFunctionBegin; 6959 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 6960 PetscValidType(mat, 2); 6961 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 6962 PetscValidPointer(info, 4); 6963 PetscValidPointer(fact, 1); 6964 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6965 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels); 6966 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 6967 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6968 MatCheckPreallocated(mat, 2); 6969 6970 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 6971 PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info); 6972 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 6973 PetscFunctionReturn(PETSC_SUCCESS); 6974 } 6975 6976 /*@C 6977 MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat 6978 points to an array of valid matrices, they may be reused to store the new 6979 submatrices. 6980 6981 Collective 6982 6983 Input Parameters: 6984 + mat - the matrix 6985 . n - the number of submatrixes to be extracted (on this processor, may be zero) 6986 . irow - index set of rows to extract 6987 . icol - index set of columns to extract 6988 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 6989 6990 Output Parameter: 6991 . submat - the array of submatrices 6992 6993 Level: advanced 6994 6995 Notes: 6996 `MatCreateSubMatrices()` can extract ONLY sequential submatrices 6997 (from both sequential and parallel matrices). Use `MatCreateSubMatrix()` 6998 to extract a parallel submatrix. 6999 7000 Some matrix types place restrictions on the row and column 7001 indices, such as that they be sorted or that they be equal to each other. 7002 7003 The index sets may not have duplicate entries. 7004 7005 When extracting submatrices from a parallel matrix, each processor can 7006 form a different submatrix by setting the rows and columns of its 7007 individual index sets according to the local submatrix desired. 7008 7009 When finished using the submatrices, the user should destroy 7010 them with `MatDestroySubMatrices()`. 7011 7012 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 7013 original matrix has not changed from that last call to `MatCreateSubMatrices()`. 7014 7015 This routine creates the matrices in submat; you should NOT create them before 7016 calling it. It also allocates the array of matrix pointers submat. 7017 7018 For `MATBAIJ` matrices the index sets must respect the block structure, that is if they 7019 request one row/column in a block, they must request all rows/columns that are in 7020 that block. For example, if the block size is 2 you cannot request just row 0 and 7021 column 0. 7022 7023 Fortran Note: 7024 The Fortran interface is slightly different from that given below; it 7025 requires one to pass in as `submat` a `Mat` (integer) array of size at least n+1. 7026 7027 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7028 @*/ 7029 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7030 { 7031 PetscInt i; 7032 PetscBool eq; 7033 7034 PetscFunctionBegin; 7035 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7036 PetscValidType(mat, 1); 7037 if (n) { 7038 PetscValidPointer(irow, 3); 7039 for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3); 7040 PetscValidPointer(icol, 4); 7041 for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4); 7042 } 7043 PetscValidPointer(submat, 6); 7044 if (n && scall == MAT_REUSE_MATRIX) { 7045 PetscValidPointer(*submat, 6); 7046 for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6); 7047 } 7048 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7049 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7050 MatCheckPreallocated(mat, 1); 7051 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7052 PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat); 7053 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7054 for (i = 0; i < n; i++) { 7055 (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */ 7056 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7057 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7058 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 7059 if (mat->boundtocpu && mat->bindingpropagates) { 7060 PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE)); 7061 PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE)); 7062 } 7063 #endif 7064 } 7065 PetscFunctionReturn(PETSC_SUCCESS); 7066 } 7067 7068 /*@C 7069 MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms). 7070 7071 Collective 7072 7073 Input Parameters: 7074 + mat - the matrix 7075 . n - the number of submatrixes to be extracted 7076 . irow - index set of rows to extract 7077 . icol - index set of columns to extract 7078 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7079 7080 Output Parameter: 7081 . submat - the array of submatrices 7082 7083 Level: advanced 7084 7085 Note: 7086 This is used by `PCGASM` 7087 7088 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7089 @*/ 7090 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7091 { 7092 PetscInt i; 7093 PetscBool eq; 7094 7095 PetscFunctionBegin; 7096 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7097 PetscValidType(mat, 1); 7098 if (n) { 7099 PetscValidPointer(irow, 3); 7100 PetscValidHeaderSpecific(*irow, IS_CLASSID, 3); 7101 PetscValidPointer(icol, 4); 7102 PetscValidHeaderSpecific(*icol, IS_CLASSID, 4); 7103 } 7104 PetscValidPointer(submat, 6); 7105 if (n && scall == MAT_REUSE_MATRIX) { 7106 PetscValidPointer(*submat, 6); 7107 PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6); 7108 } 7109 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7110 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7111 MatCheckPreallocated(mat, 1); 7112 7113 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7114 PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat); 7115 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7116 for (i = 0; i < n; i++) { 7117 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7118 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7119 } 7120 PetscFunctionReturn(PETSC_SUCCESS); 7121 } 7122 7123 /*@C 7124 MatDestroyMatrices - Destroys an array of matrices. 7125 7126 Collective 7127 7128 Input Parameters: 7129 + n - the number of local matrices 7130 - mat - the matrices (this is a pointer to the array of matrices) 7131 7132 Level: advanced 7133 7134 Note: 7135 Frees not only the matrices, but also the array that contains the matrices 7136 7137 Fortran Note: 7138 This does not free the array. 7139 7140 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()` 7141 @*/ 7142 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[]) 7143 { 7144 PetscInt i; 7145 7146 PetscFunctionBegin; 7147 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7148 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7149 PetscValidPointer(mat, 2); 7150 7151 for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i])); 7152 7153 /* memory is allocated even if n = 0 */ 7154 PetscCall(PetscFree(*mat)); 7155 PetscFunctionReturn(PETSC_SUCCESS); 7156 } 7157 7158 /*@C 7159 MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`. 7160 7161 Collective 7162 7163 Input Parameters: 7164 + n - the number of local matrices 7165 - mat - the matrices (this is a pointer to the array of matrices, just to match the calling 7166 sequence of `MatCreateSubMatrices()`) 7167 7168 Level: advanced 7169 7170 Note: 7171 Frees not only the matrices, but also the array that contains the matrices 7172 7173 Fortran Note: 7174 This does not free the array. 7175 7176 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7177 @*/ 7178 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[]) 7179 { 7180 Mat mat0; 7181 7182 PetscFunctionBegin; 7183 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7184 /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */ 7185 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7186 PetscValidPointer(mat, 2); 7187 7188 mat0 = (*mat)[0]; 7189 if (mat0 && mat0->ops->destroysubmatrices) { 7190 PetscCall((*mat0->ops->destroysubmatrices)(n, mat)); 7191 } else { 7192 PetscCall(MatDestroyMatrices(n, mat)); 7193 } 7194 PetscFunctionReturn(PETSC_SUCCESS); 7195 } 7196 7197 /*@C 7198 MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process 7199 7200 Collective 7201 7202 Input Parameter: 7203 . mat - the matrix 7204 7205 Output Parameter: 7206 . matstruct - the sequential matrix with the nonzero structure of mat 7207 7208 Level: developer 7209 7210 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7211 @*/ 7212 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct) 7213 { 7214 PetscFunctionBegin; 7215 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7216 PetscValidPointer(matstruct, 2); 7217 7218 PetscValidType(mat, 1); 7219 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7220 MatCheckPreallocated(mat, 1); 7221 7222 PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7223 PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct); 7224 PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7225 PetscFunctionReturn(PETSC_SUCCESS); 7226 } 7227 7228 /*@C 7229 MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`. 7230 7231 Collective 7232 7233 Input Parameter: 7234 . mat - the matrix (this is a pointer to the array of matrices, just to match the calling 7235 sequence of `MatGetSeqNonzeroStructure()`) 7236 7237 Level: advanced 7238 7239 Note: 7240 Frees not only the matrices, but also the array that contains the matrices 7241 7242 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()` 7243 @*/ 7244 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat) 7245 { 7246 PetscFunctionBegin; 7247 PetscValidPointer(mat, 1); 7248 PetscCall(MatDestroy(mat)); 7249 PetscFunctionReturn(PETSC_SUCCESS); 7250 } 7251 7252 /*@ 7253 MatIncreaseOverlap - Given a set of submatrices indicated by index sets, 7254 replaces the index sets by larger ones that represent submatrices with 7255 additional overlap. 7256 7257 Collective 7258 7259 Input Parameters: 7260 + mat - the matrix 7261 . n - the number of index sets 7262 . is - the array of index sets (these index sets will changed during the call) 7263 - ov - the additional overlap requested 7264 7265 Options Database Key: 7266 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7267 7268 Level: developer 7269 7270 Note: 7271 The computed overlap preserves the matrix block sizes when the blocks are square. 7272 That is: if a matrix nonzero for a given block would increase the overlap all columns associated with 7273 that block are included in the overlap regardless of whether each specific column would increase the overlap. 7274 7275 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()` 7276 @*/ 7277 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov) 7278 { 7279 PetscInt i, bs, cbs; 7280 7281 PetscFunctionBegin; 7282 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7283 PetscValidType(mat, 1); 7284 PetscValidLogicalCollectiveInt(mat, n, 2); 7285 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7286 if (n) { 7287 PetscValidPointer(is, 3); 7288 for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3); 7289 } 7290 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7291 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7292 MatCheckPreallocated(mat, 1); 7293 7294 if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS); 7295 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7296 PetscUseTypeMethod(mat, increaseoverlap, n, is, ov); 7297 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7298 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 7299 if (bs == cbs) { 7300 for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs)); 7301 } 7302 PetscFunctionReturn(PETSC_SUCCESS); 7303 } 7304 7305 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt); 7306 7307 /*@ 7308 MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across 7309 a sub communicator, replaces the index sets by larger ones that represent submatrices with 7310 additional overlap. 7311 7312 Collective 7313 7314 Input Parameters: 7315 + mat - the matrix 7316 . n - the number of index sets 7317 . is - the array of index sets (these index sets will changed during the call) 7318 - ov - the additional overlap requested 7319 7320 ` Options Database Key: 7321 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7322 7323 Level: developer 7324 7325 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()` 7326 @*/ 7327 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov) 7328 { 7329 PetscInt i; 7330 7331 PetscFunctionBegin; 7332 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7333 PetscValidType(mat, 1); 7334 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7335 if (n) { 7336 PetscValidPointer(is, 3); 7337 PetscValidHeaderSpecific(*is, IS_CLASSID, 3); 7338 } 7339 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7340 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7341 MatCheckPreallocated(mat, 1); 7342 if (!ov) PetscFunctionReturn(PETSC_SUCCESS); 7343 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7344 for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov)); 7345 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7346 PetscFunctionReturn(PETSC_SUCCESS); 7347 } 7348 7349 /*@ 7350 MatGetBlockSize - Returns the matrix block size. 7351 7352 Not Collective 7353 7354 Input Parameter: 7355 . mat - the matrix 7356 7357 Output Parameter: 7358 . bs - block size 7359 7360 Level: intermediate 7361 7362 Notes: 7363 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7364 7365 If the block size has not been set yet this routine returns 1. 7366 7367 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()` 7368 @*/ 7369 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs) 7370 { 7371 PetscFunctionBegin; 7372 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7373 PetscValidIntPointer(bs, 2); 7374 *bs = PetscAbs(mat->rmap->bs); 7375 PetscFunctionReturn(PETSC_SUCCESS); 7376 } 7377 7378 /*@ 7379 MatGetBlockSizes - Returns the matrix block row and column sizes. 7380 7381 Not Collective 7382 7383 Input Parameter: 7384 . mat - the matrix 7385 7386 Output Parameters: 7387 + rbs - row block size 7388 - cbs - column block size 7389 7390 Level: intermediate 7391 7392 Notes: 7393 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7394 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7395 7396 If a block size has not been set yet this routine returns 1. 7397 7398 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()` 7399 @*/ 7400 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs) 7401 { 7402 PetscFunctionBegin; 7403 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7404 if (rbs) PetscValidIntPointer(rbs, 2); 7405 if (cbs) PetscValidIntPointer(cbs, 3); 7406 if (rbs) *rbs = PetscAbs(mat->rmap->bs); 7407 if (cbs) *cbs = PetscAbs(mat->cmap->bs); 7408 PetscFunctionReturn(PETSC_SUCCESS); 7409 } 7410 7411 /*@ 7412 MatSetBlockSize - Sets the matrix block size. 7413 7414 Logically Collective 7415 7416 Input Parameters: 7417 + mat - the matrix 7418 - bs - block size 7419 7420 Level: intermediate 7421 7422 Notes: 7423 Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix. 7424 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7425 7426 For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size 7427 is compatible with the matrix local sizes. 7428 7429 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()` 7430 @*/ 7431 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs) 7432 { 7433 PetscFunctionBegin; 7434 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7435 PetscValidLogicalCollectiveInt(mat, bs, 2); 7436 PetscCall(MatSetBlockSizes(mat, bs, bs)); 7437 PetscFunctionReturn(PETSC_SUCCESS); 7438 } 7439 7440 typedef struct { 7441 PetscInt n; 7442 IS *is; 7443 Mat *mat; 7444 PetscObjectState nonzerostate; 7445 Mat C; 7446 } EnvelopeData; 7447 7448 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata) 7449 { 7450 for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i])); 7451 PetscCall(PetscFree(edata->is)); 7452 PetscCall(PetscFree(edata)); 7453 return PETSC_SUCCESS; 7454 } 7455 7456 /* 7457 MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores 7458 the sizes of these blocks in the matrix. An individual block may lie over several processes. 7459 7460 Collective 7461 7462 Input Parameter: 7463 . mat - the matrix 7464 7465 Notes: 7466 There can be zeros within the blocks 7467 7468 The blocks can overlap between processes, including laying on more than two processes 7469 7470 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()` 7471 */ 7472 static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat) 7473 { 7474 PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend; 7475 PetscInt *diag, *odiag, sc; 7476 VecScatter scatter; 7477 PetscScalar *seqv; 7478 const PetscScalar *parv; 7479 const PetscInt *ia, *ja; 7480 PetscBool set, flag, done; 7481 Mat AA = mat, A; 7482 MPI_Comm comm; 7483 PetscMPIInt rank, size, tag; 7484 MPI_Status status; 7485 PetscContainer container; 7486 EnvelopeData *edata; 7487 Vec seq, par; 7488 IS isglobal; 7489 7490 PetscFunctionBegin; 7491 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7492 PetscCall(MatIsSymmetricKnown(mat, &set, &flag)); 7493 if (!set || !flag) { 7494 /* TOO: only needs nonzero structure of transpose */ 7495 PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA)); 7496 PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN)); 7497 } 7498 PetscCall(MatAIJGetLocalMat(AA, &A)); 7499 PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7500 PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix"); 7501 7502 PetscCall(MatGetLocalSize(mat, &n, NULL)); 7503 PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag)); 7504 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 7505 PetscCallMPI(MPI_Comm_size(comm, &size)); 7506 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7507 7508 PetscCall(PetscMalloc2(n, &sizes, n, &starts)); 7509 7510 if (rank > 0) { 7511 PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7512 PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7513 } 7514 PetscCall(MatGetOwnershipRange(mat, &rstart, NULL)); 7515 for (i = 0; i < n; i++) { 7516 env = PetscMax(env, ja[ia[i + 1] - 1]); 7517 II = rstart + i; 7518 if (env == II) { 7519 starts[lblocks] = tbs; 7520 sizes[lblocks++] = 1 + II - tbs; 7521 tbs = 1 + II; 7522 } 7523 } 7524 if (rank < size - 1) { 7525 PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm)); 7526 PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm)); 7527 } 7528 7529 PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7530 if (!set || !flag) PetscCall(MatDestroy(&AA)); 7531 PetscCall(MatDestroy(&A)); 7532 7533 PetscCall(PetscNew(&edata)); 7534 PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate)); 7535 edata->n = lblocks; 7536 /* create IS needed for extracting blocks from the original matrix */ 7537 PetscCall(PetscMalloc1(lblocks, &edata->is)); 7538 for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i])); 7539 7540 /* Create the resulting inverse matrix structure with preallocation information */ 7541 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C)); 7542 PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 7543 PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat)); 7544 PetscCall(MatSetType(edata->C, MATAIJ)); 7545 7546 /* Communicate the start and end of each row, from each block to the correct rank */ 7547 /* TODO: Use PetscSF instead of VecScatter */ 7548 for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i]; 7549 PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq)); 7550 PetscCall(VecGetArrayWrite(seq, &seqv)); 7551 for (PetscInt i = 0; i < lblocks; i++) { 7552 for (PetscInt j = 0; j < sizes[i]; j++) { 7553 seqv[cnt] = starts[i]; 7554 seqv[cnt + 1] = starts[i] + sizes[i]; 7555 cnt += 2; 7556 } 7557 } 7558 PetscCall(VecRestoreArrayWrite(seq, &seqv)); 7559 PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 7560 sc -= cnt; 7561 PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par)); 7562 PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal)); 7563 PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter)); 7564 PetscCall(ISDestroy(&isglobal)); 7565 PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7566 PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7567 PetscCall(VecScatterDestroy(&scatter)); 7568 PetscCall(VecDestroy(&seq)); 7569 PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend)); 7570 PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag)); 7571 PetscCall(VecGetArrayRead(par, &parv)); 7572 cnt = 0; 7573 PetscCall(MatGetSize(mat, NULL, &n)); 7574 for (PetscInt i = 0; i < mat->rmap->n; i++) { 7575 PetscInt start, end, d = 0, od = 0; 7576 7577 start = (PetscInt)PetscRealPart(parv[cnt]); 7578 end = (PetscInt)PetscRealPart(parv[cnt + 1]); 7579 cnt += 2; 7580 7581 if (start < cstart) { 7582 od += cstart - start + n - cend; 7583 d += cend - cstart; 7584 } else if (start < cend) { 7585 od += n - cend; 7586 d += cend - start; 7587 } else od += n - start; 7588 if (end <= cstart) { 7589 od -= cstart - end + n - cend; 7590 d -= cend - cstart; 7591 } else if (end < cend) { 7592 od -= n - cend; 7593 d -= cend - end; 7594 } else od -= n - end; 7595 7596 odiag[i] = od; 7597 diag[i] = d; 7598 } 7599 PetscCall(VecRestoreArrayRead(par, &parv)); 7600 PetscCall(VecDestroy(&par)); 7601 PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL)); 7602 PetscCall(PetscFree2(diag, odiag)); 7603 PetscCall(PetscFree2(sizes, starts)); 7604 7605 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container)); 7606 PetscCall(PetscContainerSetPointer(container, edata)); 7607 PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy)); 7608 PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container)); 7609 PetscCall(PetscObjectDereference((PetscObject)container)); 7610 PetscFunctionReturn(PETSC_SUCCESS); 7611 } 7612 7613 /*@ 7614 MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A 7615 7616 Collective 7617 7618 Input Parameters: 7619 + A - the matrix 7620 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine 7621 7622 Output Parameter: 7623 . C - matrix with inverted block diagonal of `A` 7624 7625 Level: advanced 7626 7627 Note: 7628 For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal. 7629 7630 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()` 7631 @*/ 7632 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C) 7633 { 7634 PetscContainer container; 7635 EnvelopeData *edata; 7636 PetscObjectState nonzerostate; 7637 7638 PetscFunctionBegin; 7639 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7640 if (!container) { 7641 PetscCall(MatComputeVariableBlockEnvelope(A)); 7642 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7643 } 7644 PetscCall(PetscContainerGetPointer(container, (void **)&edata)); 7645 PetscCall(MatGetNonzeroState(A, &nonzerostate)); 7646 PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure"); 7647 PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output"); 7648 7649 PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat)); 7650 *C = edata->C; 7651 7652 for (PetscInt i = 0; i < edata->n; i++) { 7653 Mat D; 7654 PetscScalar *dvalues; 7655 7656 PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D)); 7657 PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE)); 7658 PetscCall(MatSeqDenseInvert(D)); 7659 PetscCall(MatDenseGetArray(D, &dvalues)); 7660 PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES)); 7661 PetscCall(MatDestroy(&D)); 7662 } 7663 PetscCall(MatDestroySubMatrices(edata->n, &edata->mat)); 7664 PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY)); 7665 PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY)); 7666 PetscFunctionReturn(PETSC_SUCCESS); 7667 } 7668 7669 /*@ 7670 MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size 7671 7672 Logically Collective 7673 7674 Input Parameters: 7675 + mat - the matrix 7676 . nblocks - the number of blocks on this process, each block can only exist on a single process 7677 - bsizes - the block sizes 7678 7679 Level: intermediate 7680 7681 Notes: 7682 Currently used by `PCVPBJACOBI` for `MATAIJ` matrices 7683 7684 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. 7685 7686 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, 7687 `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI` 7688 @*/ 7689 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes) 7690 { 7691 PetscInt i, ncnt = 0, nlocal; 7692 7693 PetscFunctionBegin; 7694 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7695 PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero"); 7696 PetscCall(MatGetLocalSize(mat, &nlocal, NULL)); 7697 for (i = 0; i < nblocks; i++) ncnt += bsizes[i]; 7698 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); 7699 PetscCall(PetscFree(mat->bsizes)); 7700 mat->nblocks = nblocks; 7701 PetscCall(PetscMalloc1(nblocks, &mat->bsizes)); 7702 PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks)); 7703 PetscFunctionReturn(PETSC_SUCCESS); 7704 } 7705 7706 /*@C 7707 MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size 7708 7709 Logically Collective; No Fortran Support 7710 7711 Input Parameter: 7712 . mat - the matrix 7713 7714 Output Parameters: 7715 + nblocks - the number of blocks on this process 7716 - bsizes - the block sizes 7717 7718 Level: intermediate 7719 7720 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()` 7721 @*/ 7722 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes) 7723 { 7724 PetscFunctionBegin; 7725 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7726 *nblocks = mat->nblocks; 7727 *bsizes = mat->bsizes; 7728 PetscFunctionReturn(PETSC_SUCCESS); 7729 } 7730 7731 /*@ 7732 MatSetBlockSizes - Sets the matrix block row and column sizes. 7733 7734 Logically Collective 7735 7736 Input Parameters: 7737 + mat - the matrix 7738 . rbs - row block size 7739 - cbs - column block size 7740 7741 Level: intermediate 7742 7743 Notes: 7744 Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix. 7745 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7746 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7747 7748 For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes 7749 are compatible with the matrix local sizes. 7750 7751 The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`. 7752 7753 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()` 7754 @*/ 7755 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs) 7756 { 7757 PetscFunctionBegin; 7758 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7759 PetscValidLogicalCollectiveInt(mat, rbs, 2); 7760 PetscValidLogicalCollectiveInt(mat, cbs, 3); 7761 PetscTryTypeMethod(mat, setblocksizes, rbs, cbs); 7762 if (mat->rmap->refcnt) { 7763 ISLocalToGlobalMapping l2g = NULL; 7764 PetscLayout nmap = NULL; 7765 7766 PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap)); 7767 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g)); 7768 PetscCall(PetscLayoutDestroy(&mat->rmap)); 7769 mat->rmap = nmap; 7770 mat->rmap->mapping = l2g; 7771 } 7772 if (mat->cmap->refcnt) { 7773 ISLocalToGlobalMapping l2g = NULL; 7774 PetscLayout nmap = NULL; 7775 7776 PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap)); 7777 if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g)); 7778 PetscCall(PetscLayoutDestroy(&mat->cmap)); 7779 mat->cmap = nmap; 7780 mat->cmap->mapping = l2g; 7781 } 7782 PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs)); 7783 PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs)); 7784 PetscFunctionReturn(PETSC_SUCCESS); 7785 } 7786 7787 /*@ 7788 MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices 7789 7790 Logically Collective 7791 7792 Input Parameters: 7793 + mat - the matrix 7794 . fromRow - matrix from which to copy row block size 7795 - fromCol - matrix from which to copy column block size (can be same as fromRow) 7796 7797 Level: developer 7798 7799 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()` 7800 @*/ 7801 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol) 7802 { 7803 PetscFunctionBegin; 7804 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7805 PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2); 7806 PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3); 7807 if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs)); 7808 if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs)); 7809 PetscFunctionReturn(PETSC_SUCCESS); 7810 } 7811 7812 /*@ 7813 MatResidual - Default routine to calculate the residual r = b - Ax 7814 7815 Collective 7816 7817 Input Parameters: 7818 + mat - the matrix 7819 . b - the right-hand-side 7820 - x - the approximate solution 7821 7822 Output Parameter: 7823 . r - location to store the residual 7824 7825 Level: developer 7826 7827 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()` 7828 @*/ 7829 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r) 7830 { 7831 PetscFunctionBegin; 7832 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7833 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 7834 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 7835 PetscValidHeaderSpecific(r, VEC_CLASSID, 4); 7836 PetscValidType(mat, 1); 7837 MatCheckPreallocated(mat, 1); 7838 PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0)); 7839 if (!mat->ops->residual) { 7840 PetscCall(MatMult(mat, x, r)); 7841 PetscCall(VecAYPX(r, -1.0, b)); 7842 } else { 7843 PetscUseTypeMethod(mat, residual, b, x, r); 7844 } 7845 PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0)); 7846 PetscFunctionReturn(PETSC_SUCCESS); 7847 } 7848 7849 /*MC 7850 MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix 7851 7852 Synopsis: 7853 MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 7854 7855 Not Collective 7856 7857 Input Parameters: 7858 + A - the matrix 7859 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7860 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7861 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7862 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7863 always used. 7864 7865 Output Parameters: 7866 + n - number of local rows in the (possibly compressed) matrix 7867 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 7868 . ja - the column indices 7869 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7870 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7871 7872 Level: developer 7873 7874 Note: 7875 Use `MatRestoreRowIJF90()` when you no longer need access to the data 7876 7877 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()` 7878 M*/ 7879 7880 /*MC 7881 MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()` 7882 7883 Synopsis: 7884 MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 7885 7886 Not Collective 7887 7888 Input Parameters: 7889 + A - the matrix 7890 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7891 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7892 inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7893 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7894 always used. 7895 . n - number of local rows in the (possibly compressed) matrix 7896 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 7897 . ja - the column indices 7898 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7899 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7900 7901 Level: developer 7902 7903 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()` 7904 M*/ 7905 7906 /*@C 7907 MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix 7908 7909 Collective 7910 7911 Input Parameters: 7912 + mat - the matrix 7913 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7914 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7915 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7916 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7917 always used. 7918 7919 Output Parameters: 7920 + n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed 7921 . 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 7922 . ja - the column indices, use `NULL` if not needed 7923 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7924 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7925 7926 Level: developer 7927 7928 Notes: 7929 You CANNOT change any of the ia[] or ja[] values. 7930 7931 Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values. 7932 7933 Fortran Notes: 7934 Use 7935 .vb 7936 PetscInt, pointer :: ia(:),ja(:) 7937 call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr) 7938 ! Access the ith and jth entries via ia(i) and ja(j) 7939 .ve 7940 `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()` 7941 7942 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()` 7943 @*/ 7944 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7945 { 7946 PetscFunctionBegin; 7947 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7948 PetscValidType(mat, 1); 7949 if (n) PetscValidIntPointer(n, 5); 7950 if (ia) PetscValidPointer(ia, 6); 7951 if (ja) PetscValidPointer(ja, 7); 7952 if (done) PetscValidBoolPointer(done, 8); 7953 MatCheckPreallocated(mat, 1); 7954 if (!mat->ops->getrowij && done) *done = PETSC_FALSE; 7955 else { 7956 if (done) *done = PETSC_TRUE; 7957 PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0)); 7958 PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done); 7959 PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0)); 7960 } 7961 PetscFunctionReturn(PETSC_SUCCESS); 7962 } 7963 7964 /*@C 7965 MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices. 7966 7967 Collective 7968 7969 Input Parameters: 7970 + mat - the matrix 7971 . shift - 1 or zero indicating we want the indices starting at 0 or 1 7972 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be 7973 symmetrized 7974 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7975 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7976 always used. 7977 . n - number of columns in the (possibly compressed) matrix 7978 . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix 7979 - ja - the row indices 7980 7981 Output Parameter: 7982 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned 7983 7984 Level: developer 7985 7986 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 7987 @*/ 7988 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7989 { 7990 PetscFunctionBegin; 7991 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7992 PetscValidType(mat, 1); 7993 PetscValidIntPointer(n, 5); 7994 if (ia) PetscValidPointer(ia, 6); 7995 if (ja) PetscValidPointer(ja, 7); 7996 PetscValidBoolPointer(done, 8); 7997 MatCheckPreallocated(mat, 1); 7998 if (!mat->ops->getcolumnij) *done = PETSC_FALSE; 7999 else { 8000 *done = PETSC_TRUE; 8001 PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8002 } 8003 PetscFunctionReturn(PETSC_SUCCESS); 8004 } 8005 8006 /*@C 8007 MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`. 8008 8009 Collective 8010 8011 Input Parameters: 8012 + mat - the matrix 8013 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8014 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8015 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8016 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8017 always used. 8018 . n - size of (possibly compressed) matrix 8019 . ia - the row pointers 8020 - ja - the column indices 8021 8022 Output Parameter: 8023 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8024 8025 Level: developer 8026 8027 Note: 8028 This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental 8029 us of the array after it has been restored. If you pass `NULL`, it will 8030 not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid. 8031 8032 Fortran Note: 8033 `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()` 8034 8035 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()` 8036 @*/ 8037 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8038 { 8039 PetscFunctionBegin; 8040 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8041 PetscValidType(mat, 1); 8042 if (ia) PetscValidPointer(ia, 6); 8043 if (ja) PetscValidPointer(ja, 7); 8044 if (done) PetscValidBoolPointer(done, 8); 8045 MatCheckPreallocated(mat, 1); 8046 8047 if (!mat->ops->restorerowij && done) *done = PETSC_FALSE; 8048 else { 8049 if (done) *done = PETSC_TRUE; 8050 PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8051 if (n) *n = 0; 8052 if (ia) *ia = NULL; 8053 if (ja) *ja = NULL; 8054 } 8055 PetscFunctionReturn(PETSC_SUCCESS); 8056 } 8057 8058 /*@C 8059 MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`. 8060 8061 Collective 8062 8063 Input Parameters: 8064 + mat - the matrix 8065 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8066 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8067 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8068 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8069 always used. 8070 8071 Output Parameters: 8072 + n - size of (possibly compressed) matrix 8073 . ia - the column pointers 8074 . ja - the row indices 8075 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8076 8077 Level: developer 8078 8079 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()` 8080 @*/ 8081 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8082 { 8083 PetscFunctionBegin; 8084 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8085 PetscValidType(mat, 1); 8086 if (ia) PetscValidPointer(ia, 6); 8087 if (ja) PetscValidPointer(ja, 7); 8088 PetscValidBoolPointer(done, 8); 8089 MatCheckPreallocated(mat, 1); 8090 8091 if (!mat->ops->restorecolumnij) *done = PETSC_FALSE; 8092 else { 8093 *done = PETSC_TRUE; 8094 PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8095 if (n) *n = 0; 8096 if (ia) *ia = NULL; 8097 if (ja) *ja = NULL; 8098 } 8099 PetscFunctionReturn(PETSC_SUCCESS); 8100 } 8101 8102 /*@C 8103 MatColoringPatch -Used inside matrix coloring routines that use `MatGetRowIJ()` and/or `MatGetColumnIJ()`. 8104 8105 Collective 8106 8107 Input Parameters: 8108 + mat - the matrix 8109 . ncolors - maximum color value 8110 . n - number of entries in colorarray 8111 - colorarray - array indicating color for each column 8112 8113 Output Parameter: 8114 . iscoloring - coloring generated using colorarray information 8115 8116 Level: developer 8117 8118 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()` 8119 @*/ 8120 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring) 8121 { 8122 PetscFunctionBegin; 8123 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8124 PetscValidType(mat, 1); 8125 PetscValidIntPointer(colorarray, 4); 8126 PetscValidPointer(iscoloring, 5); 8127 MatCheckPreallocated(mat, 1); 8128 8129 if (!mat->ops->coloringpatch) { 8130 PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring)); 8131 } else { 8132 PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring); 8133 } 8134 PetscFunctionReturn(PETSC_SUCCESS); 8135 } 8136 8137 /*@ 8138 MatSetUnfactored - Resets a factored matrix to be treated as unfactored. 8139 8140 Logically Collective 8141 8142 Input Parameter: 8143 . mat - the factored matrix to be reset 8144 8145 Level: developer 8146 8147 Notes: 8148 This routine should be used only with factored matrices formed by in-place 8149 factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE` 8150 format). This option can save memory, for example, when solving nonlinear 8151 systems with a matrix-free Newton-Krylov method and a matrix-based, in-place 8152 ILU(0) preconditioner. 8153 8154 One can specify in-place ILU(0) factorization by calling 8155 .vb 8156 PCType(pc,PCILU); 8157 PCFactorSeUseInPlace(pc); 8158 .ve 8159 or by using the options -pc_type ilu -pc_factor_in_place 8160 8161 In-place factorization ILU(0) can also be used as a local 8162 solver for the blocks within the block Jacobi or additive Schwarz 8163 methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc 8164 for details on setting local solver options. 8165 8166 Most users should employ the `KSP` interface for linear solvers 8167 instead of working directly with matrix algebra routines such as this. 8168 See, e.g., `KSPCreate()`. 8169 8170 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()` 8171 @*/ 8172 PetscErrorCode MatSetUnfactored(Mat mat) 8173 { 8174 PetscFunctionBegin; 8175 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8176 PetscValidType(mat, 1); 8177 MatCheckPreallocated(mat, 1); 8178 mat->factortype = MAT_FACTOR_NONE; 8179 if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS); 8180 PetscUseTypeMethod(mat, setunfactored); 8181 PetscFunctionReturn(PETSC_SUCCESS); 8182 } 8183 8184 /*MC 8185 MatDenseGetArrayF90 - Accesses a matrix array from Fortran 8186 8187 Synopsis: 8188 MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8189 8190 Not Collective 8191 8192 Input Parameter: 8193 . x - matrix 8194 8195 Output Parameters: 8196 + xx_v - the Fortran pointer to the array 8197 - ierr - error code 8198 8199 Example of Usage: 8200 .vb 8201 PetscScalar, pointer xx_v(:,:) 8202 .... 8203 call MatDenseGetArrayF90(x,xx_v,ierr) 8204 a = xx_v(3) 8205 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8206 .ve 8207 8208 Level: advanced 8209 8210 .seealso: [](ch_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()` 8211 M*/ 8212 8213 /*MC 8214 MatDenseRestoreArrayF90 - Restores a matrix array that has been 8215 accessed with `MatDenseGetArrayF90()`. 8216 8217 Synopsis: 8218 MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8219 8220 Not Collective 8221 8222 Input Parameters: 8223 + x - matrix 8224 - xx_v - the Fortran90 pointer to the array 8225 8226 Output Parameter: 8227 . ierr - error code 8228 8229 Example of Usage: 8230 .vb 8231 PetscScalar, pointer xx_v(:,:) 8232 .... 8233 call MatDenseGetArrayF90(x,xx_v,ierr) 8234 a = xx_v(3) 8235 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8236 .ve 8237 8238 Level: advanced 8239 8240 .seealso: [](ch_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()` 8241 M*/ 8242 8243 /*MC 8244 MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran. 8245 8246 Synopsis: 8247 MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8248 8249 Not Collective 8250 8251 Input Parameter: 8252 . x - matrix 8253 8254 Output Parameters: 8255 + xx_v - the Fortran pointer to the array 8256 - ierr - error code 8257 8258 Example of Usage: 8259 .vb 8260 PetscScalar, pointer xx_v(:) 8261 .... 8262 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8263 a = xx_v(3) 8264 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8265 .ve 8266 8267 Level: advanced 8268 8269 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()` 8270 M*/ 8271 8272 /*MC 8273 MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been 8274 accessed with `MatSeqAIJGetArrayF90()`. 8275 8276 Synopsis: 8277 MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8278 8279 Not Collective 8280 8281 Input Parameters: 8282 + x - matrix 8283 - xx_v - the Fortran90 pointer to the array 8284 8285 Output Parameter: 8286 . ierr - error code 8287 8288 Example of Usage: 8289 .vb 8290 PetscScalar, pointer xx_v(:) 8291 .... 8292 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8293 a = xx_v(3) 8294 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8295 .ve 8296 8297 Level: advanced 8298 8299 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()` 8300 M*/ 8301 8302 /*@ 8303 MatCreateSubMatrix - Gets a single submatrix on the same number of processors 8304 as the original matrix. 8305 8306 Collective 8307 8308 Input Parameters: 8309 + mat - the original matrix 8310 . isrow - parallel `IS` containing the rows this processor should obtain 8311 . 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. 8312 - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 8313 8314 Output Parameter: 8315 . newmat - the new submatrix, of the same type as the original matrix 8316 8317 Level: advanced 8318 8319 Notes: 8320 The submatrix will be able to be multiplied with vectors using the same layout as `iscol`. 8321 8322 Some matrix types place restrictions on the row and column indices, such 8323 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; 8324 for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row. 8325 8326 The index sets may not have duplicate entries. 8327 8328 The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`, 8329 the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls 8330 to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX` 8331 will reuse the matrix generated the first time. You should call `MatDestroy()` on `newmat` when 8332 you are finished using it. 8333 8334 The communicator of the newly obtained matrix is ALWAYS the same as the communicator of 8335 the input matrix. 8336 8337 If `iscol` is `NULL` then all columns are obtained (not supported in Fortran). 8338 8339 Example usage: 8340 Consider the following 8x8 matrix with 34 non-zero values, that is 8341 assembled across 3 processors. Let's assume that proc0 owns 3 rows, 8342 proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 8343 as follows 8344 .vb 8345 1 2 0 | 0 3 0 | 0 4 8346 Proc0 0 5 6 | 7 0 0 | 8 0 8347 9 0 10 | 11 0 0 | 12 0 8348 ------------------------------------- 8349 13 0 14 | 15 16 17 | 0 0 8350 Proc1 0 18 0 | 19 20 21 | 0 0 8351 0 0 0 | 22 23 0 | 24 0 8352 ------------------------------------- 8353 Proc2 25 26 27 | 0 0 28 | 29 0 8354 30 0 0 | 31 32 33 | 0 34 8355 .ve 8356 8357 Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6]. The resulting submatrix is 8358 8359 .vb 8360 2 0 | 0 3 0 | 0 8361 Proc0 5 6 | 7 0 0 | 8 8362 ------------------------------- 8363 Proc1 18 0 | 19 20 21 | 0 8364 ------------------------------- 8365 Proc2 26 27 | 0 0 28 | 29 8366 0 0 | 31 32 33 | 0 8367 .ve 8368 8369 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()` 8370 @*/ 8371 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat) 8372 { 8373 PetscMPIInt size; 8374 Mat *local; 8375 IS iscoltmp; 8376 PetscBool flg; 8377 8378 PetscFunctionBegin; 8379 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8380 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 8381 if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 8382 PetscValidPointer(newmat, 5); 8383 if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5); 8384 PetscValidType(mat, 1); 8385 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8386 PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX"); 8387 8388 MatCheckPreallocated(mat, 1); 8389 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8390 8391 if (!iscol || isrow == iscol) { 8392 PetscBool stride; 8393 PetscMPIInt grabentirematrix = 0, grab; 8394 PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride)); 8395 if (stride) { 8396 PetscInt first, step, n, rstart, rend; 8397 PetscCall(ISStrideGetInfo(isrow, &first, &step)); 8398 if (step == 1) { 8399 PetscCall(MatGetOwnershipRange(mat, &rstart, &rend)); 8400 if (rstart == first) { 8401 PetscCall(ISGetLocalSize(isrow, &n)); 8402 if (n == rend - rstart) grabentirematrix = 1; 8403 } 8404 } 8405 } 8406 PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat))); 8407 if (grab) { 8408 PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n")); 8409 if (cll == MAT_INITIAL_MATRIX) { 8410 *newmat = mat; 8411 PetscCall(PetscObjectReference((PetscObject)mat)); 8412 } 8413 PetscFunctionReturn(PETSC_SUCCESS); 8414 } 8415 } 8416 8417 if (!iscol) { 8418 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp)); 8419 } else { 8420 iscoltmp = iscol; 8421 } 8422 8423 /* if original matrix is on just one processor then use submatrix generated */ 8424 if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) { 8425 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat)); 8426 goto setproperties; 8427 } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) { 8428 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local)); 8429 *newmat = *local; 8430 PetscCall(PetscFree(local)); 8431 goto setproperties; 8432 } else if (!mat->ops->createsubmatrix) { 8433 /* Create a new matrix type that implements the operation using the full matrix */ 8434 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8435 switch (cll) { 8436 case MAT_INITIAL_MATRIX: 8437 PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat)); 8438 break; 8439 case MAT_REUSE_MATRIX: 8440 PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp)); 8441 break; 8442 default: 8443 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX"); 8444 } 8445 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8446 goto setproperties; 8447 } 8448 8449 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8450 PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat); 8451 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8452 8453 setproperties: 8454 PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg)); 8455 if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat)); 8456 if (!iscol) PetscCall(ISDestroy(&iscoltmp)); 8457 if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat)); 8458 PetscFunctionReturn(PETSC_SUCCESS); 8459 } 8460 8461 /*@ 8462 MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix 8463 8464 Not Collective 8465 8466 Input Parameters: 8467 + A - the matrix we wish to propagate options from 8468 - B - the matrix we wish to propagate options to 8469 8470 Level: beginner 8471 8472 Note: 8473 Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL` 8474 8475 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, MatIsStructurallySymmetricKnown()` 8476 @*/ 8477 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B) 8478 { 8479 PetscFunctionBegin; 8480 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8481 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 8482 B->symmetry_eternal = A->symmetry_eternal; 8483 B->structural_symmetry_eternal = A->structural_symmetry_eternal; 8484 B->symmetric = A->symmetric; 8485 B->structurally_symmetric = A->structurally_symmetric; 8486 B->spd = A->spd; 8487 B->hermitian = A->hermitian; 8488 PetscFunctionReturn(PETSC_SUCCESS); 8489 } 8490 8491 /*@ 8492 MatStashSetInitialSize - sets the sizes of the matrix stash, that is 8493 used during the assembly process to store values that belong to 8494 other processors. 8495 8496 Not Collective 8497 8498 Input Parameters: 8499 + mat - the matrix 8500 . size - the initial size of the stash. 8501 - bsize - the initial size of the block-stash(if used). 8502 8503 Options Database Keys: 8504 + -matstash_initial_size <size> or <size0,size1,...sizep-1> 8505 - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1> 8506 8507 Level: intermediate 8508 8509 Notes: 8510 The block-stash is used for values set with `MatSetValuesBlocked()` while 8511 the stash is used for values set with `MatSetValues()` 8512 8513 Run with the option -info and look for output of the form 8514 MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs. 8515 to determine the appropriate value, MM, to use for size and 8516 MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs. 8517 to determine the value, BMM to use for bsize 8518 8519 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()` 8520 @*/ 8521 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize) 8522 { 8523 PetscFunctionBegin; 8524 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8525 PetscValidType(mat, 1); 8526 PetscCall(MatStashSetInitialSize_Private(&mat->stash, size)); 8527 PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize)); 8528 PetscFunctionReturn(PETSC_SUCCESS); 8529 } 8530 8531 /*@ 8532 MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of 8533 the matrix 8534 8535 Neighbor-wise Collective 8536 8537 Input Parameters: 8538 + mat - the matrix 8539 . x - the vector to be multiplied by the interpolation operator 8540 - y - the vector to be added to the result 8541 8542 Output Parameter: 8543 . w - the resulting vector 8544 8545 Level: intermediate 8546 8547 Notes: 8548 `w` may be the same vector as `y`. 8549 8550 This allows one to use either the restriction or interpolation (its transpose) 8551 matrix to do the interpolation 8552 8553 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8554 @*/ 8555 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w) 8556 { 8557 PetscInt M, N, Ny; 8558 8559 PetscFunctionBegin; 8560 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8561 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8562 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8563 PetscValidHeaderSpecific(w, VEC_CLASSID, 4); 8564 PetscCall(MatGetSize(A, &M, &N)); 8565 PetscCall(VecGetSize(y, &Ny)); 8566 if (M == Ny) { 8567 PetscCall(MatMultAdd(A, x, y, w)); 8568 } else { 8569 PetscCall(MatMultTransposeAdd(A, x, y, w)); 8570 } 8571 PetscFunctionReturn(PETSC_SUCCESS); 8572 } 8573 8574 /*@ 8575 MatInterpolate - y = A*x or A'*x depending on the shape of 8576 the matrix 8577 8578 Neighbor-wise Collective 8579 8580 Input Parameters: 8581 + mat - the matrix 8582 - x - the vector to be interpolated 8583 8584 Output Parameter: 8585 . y - the resulting vector 8586 8587 Level: intermediate 8588 8589 Note: 8590 This allows one to use either the restriction or interpolation (its transpose) 8591 matrix to do the interpolation 8592 8593 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8594 @*/ 8595 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y) 8596 { 8597 PetscInt M, N, Ny; 8598 8599 PetscFunctionBegin; 8600 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8601 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8602 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8603 PetscCall(MatGetSize(A, &M, &N)); 8604 PetscCall(VecGetSize(y, &Ny)); 8605 if (M == Ny) { 8606 PetscCall(MatMult(A, x, y)); 8607 } else { 8608 PetscCall(MatMultTranspose(A, x, y)); 8609 } 8610 PetscFunctionReturn(PETSC_SUCCESS); 8611 } 8612 8613 /*@ 8614 MatRestrict - y = A*x or A'*x 8615 8616 Neighbor-wise Collective 8617 8618 Input Parameters: 8619 + mat - the matrix 8620 - x - the vector to be restricted 8621 8622 Output Parameter: 8623 . y - the resulting vector 8624 8625 Level: intermediate 8626 8627 Note: 8628 This allows one to use either the restriction or interpolation (its transpose) 8629 matrix to do the restriction 8630 8631 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG` 8632 @*/ 8633 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y) 8634 { 8635 PetscInt M, N, Ny; 8636 8637 PetscFunctionBegin; 8638 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8639 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8640 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8641 PetscCall(MatGetSize(A, &M, &N)); 8642 PetscCall(VecGetSize(y, &Ny)); 8643 if (M == Ny) { 8644 PetscCall(MatMult(A, x, y)); 8645 } else { 8646 PetscCall(MatMultTranspose(A, x, y)); 8647 } 8648 PetscFunctionReturn(PETSC_SUCCESS); 8649 } 8650 8651 /*@ 8652 MatMatInterpolateAdd - Y = W + A*X or W + A'*X 8653 8654 Neighbor-wise Collective 8655 8656 Input Parameters: 8657 + mat - the matrix 8658 . x - the input dense matrix to be multiplied 8659 - w - the input dense matrix to be added to the result 8660 8661 Output Parameter: 8662 . y - the output dense matrix 8663 8664 Level: intermediate 8665 8666 Note: 8667 This allows one to use either the restriction or interpolation (its transpose) 8668 matrix to do the interpolation. y matrix can be reused if already created with the proper sizes, 8669 otherwise it will be recreated. y must be initialized to `NULL` if not supplied. 8670 8671 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG` 8672 @*/ 8673 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y) 8674 { 8675 PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0; 8676 PetscBool trans = PETSC_TRUE; 8677 MatReuse reuse = MAT_INITIAL_MATRIX; 8678 8679 PetscFunctionBegin; 8680 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8681 PetscValidHeaderSpecific(x, MAT_CLASSID, 2); 8682 PetscValidType(x, 2); 8683 if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3); 8684 if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4); 8685 PetscCall(MatGetSize(A, &M, &N)); 8686 PetscCall(MatGetSize(x, &Mx, &Nx)); 8687 if (N == Mx) trans = PETSC_FALSE; 8688 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); 8689 Mo = trans ? N : M; 8690 if (*y) { 8691 PetscCall(MatGetSize(*y, &My, &Ny)); 8692 if (Mo == My && Nx == Ny) { 8693 reuse = MAT_REUSE_MATRIX; 8694 } else { 8695 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); 8696 PetscCall(MatDestroy(y)); 8697 } 8698 } 8699 8700 if (w && *y == w) { /* this is to minimize changes in PCMG */ 8701 PetscBool flg; 8702 8703 PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w)); 8704 if (w) { 8705 PetscInt My, Ny, Mw, Nw; 8706 8707 PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg)); 8708 PetscCall(MatGetSize(*y, &My, &Ny)); 8709 PetscCall(MatGetSize(w, &Mw, &Nw)); 8710 if (!flg || My != Mw || Ny != Nw) w = NULL; 8711 } 8712 if (!w) { 8713 PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w)); 8714 PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w)); 8715 PetscCall(PetscObjectDereference((PetscObject)w)); 8716 } else { 8717 PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN)); 8718 } 8719 } 8720 if (!trans) { 8721 PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8722 } else { 8723 PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8724 } 8725 if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN)); 8726 PetscFunctionReturn(PETSC_SUCCESS); 8727 } 8728 8729 /*@ 8730 MatMatInterpolate - Y = A*X or A'*X 8731 8732 Neighbor-wise Collective 8733 8734 Input Parameters: 8735 + mat - the matrix 8736 - x - the input dense matrix 8737 8738 Output Parameter: 8739 . y - the output dense matrix 8740 8741 Level: intermediate 8742 8743 Note: 8744 This allows one to use either the restriction or interpolation (its transpose) 8745 matrix to do the interpolation. y matrix can be reused if already created with the proper sizes, 8746 otherwise it will be recreated. y must be initialized to `NULL` if not supplied. 8747 8748 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG` 8749 @*/ 8750 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y) 8751 { 8752 PetscFunctionBegin; 8753 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8754 PetscFunctionReturn(PETSC_SUCCESS); 8755 } 8756 8757 /*@ 8758 MatMatRestrict - Y = A*X or A'*X 8759 8760 Neighbor-wise Collective 8761 8762 Input Parameters: 8763 + mat - the matrix 8764 - x - the input dense matrix 8765 8766 Output Parameter: 8767 . y - the output dense matrix 8768 8769 Level: intermediate 8770 8771 Note: 8772 This allows one to use either the restriction or interpolation (its transpose) 8773 matrix to do the restriction. y matrix can be reused if already created with the proper sizes, 8774 otherwise it will be recreated. y must be initialized to `NULL` if not supplied. 8775 8776 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG` 8777 @*/ 8778 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y) 8779 { 8780 PetscFunctionBegin; 8781 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8782 PetscFunctionReturn(PETSC_SUCCESS); 8783 } 8784 8785 /*@ 8786 MatGetNullSpace - retrieves the null space of a matrix. 8787 8788 Logically Collective 8789 8790 Input Parameters: 8791 + mat - the matrix 8792 - nullsp - the null space object 8793 8794 Level: developer 8795 8796 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace` 8797 @*/ 8798 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp) 8799 { 8800 PetscFunctionBegin; 8801 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8802 PetscValidPointer(nullsp, 2); 8803 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp; 8804 PetscFunctionReturn(PETSC_SUCCESS); 8805 } 8806 8807 /*@ 8808 MatSetNullSpace - attaches a null space to a matrix. 8809 8810 Logically Collective 8811 8812 Input Parameters: 8813 + mat - the matrix 8814 - nullsp - the null space object 8815 8816 Level: advanced 8817 8818 Notes: 8819 This null space is used by the `KSP` linear solvers to solve singular systems. 8820 8821 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` 8822 8823 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 8824 to zero but the linear system will still be solved in a least squares sense. 8825 8826 The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that 8827 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). 8828 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 8829 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 8830 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). 8831 This \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix. 8832 8833 If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called 8834 `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this 8835 routine also automatically calls `MatSetTransposeNullSpace()`. 8836 8837 The user should call `MatNullSpaceDestroy()`. 8838 8839 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, 8840 `KSPSetPCSide()` 8841 @*/ 8842 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp) 8843 { 8844 PetscFunctionBegin; 8845 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8846 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8847 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8848 PetscCall(MatNullSpaceDestroy(&mat->nullsp)); 8849 mat->nullsp = nullsp; 8850 if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp)); 8851 PetscFunctionReturn(PETSC_SUCCESS); 8852 } 8853 8854 /*@ 8855 MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix. 8856 8857 Logically Collective 8858 8859 Input Parameters: 8860 + mat - the matrix 8861 - nullsp - the null space object 8862 8863 Level: developer 8864 8865 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()` 8866 @*/ 8867 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp) 8868 { 8869 PetscFunctionBegin; 8870 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8871 PetscValidType(mat, 1); 8872 PetscValidPointer(nullsp, 2); 8873 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp; 8874 PetscFunctionReturn(PETSC_SUCCESS); 8875 } 8876 8877 /*@ 8878 MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix 8879 8880 Logically Collective 8881 8882 Input Parameters: 8883 + mat - the matrix 8884 - nullsp - the null space object 8885 8886 Level: advanced 8887 8888 Notes: 8889 This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning. 8890 8891 See `MatSetNullSpace()` 8892 8893 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()` 8894 @*/ 8895 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp) 8896 { 8897 PetscFunctionBegin; 8898 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8899 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8900 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8901 PetscCall(MatNullSpaceDestroy(&mat->transnullsp)); 8902 mat->transnullsp = nullsp; 8903 PetscFunctionReturn(PETSC_SUCCESS); 8904 } 8905 8906 /*@ 8907 MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions 8908 This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix. 8909 8910 Logically Collective 8911 8912 Input Parameters: 8913 + mat - the matrix 8914 - nullsp - the null space object 8915 8916 Level: advanced 8917 8918 Notes: 8919 Overwrites any previous near null space that may have been attached 8920 8921 You can remove the null space by calling this routine with an nullsp of `NULL` 8922 8923 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()` 8924 @*/ 8925 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp) 8926 { 8927 PetscFunctionBegin; 8928 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8929 PetscValidType(mat, 1); 8930 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8931 MatCheckPreallocated(mat, 1); 8932 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8933 PetscCall(MatNullSpaceDestroy(&mat->nearnullsp)); 8934 mat->nearnullsp = nullsp; 8935 PetscFunctionReturn(PETSC_SUCCESS); 8936 } 8937 8938 /*@ 8939 MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()` 8940 8941 Not Collective 8942 8943 Input Parameter: 8944 . mat - the matrix 8945 8946 Output Parameter: 8947 . nullsp - the null space object, `NULL` if not set 8948 8949 Level: advanced 8950 8951 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()` 8952 @*/ 8953 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp) 8954 { 8955 PetscFunctionBegin; 8956 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8957 PetscValidType(mat, 1); 8958 PetscValidPointer(nullsp, 2); 8959 MatCheckPreallocated(mat, 1); 8960 *nullsp = mat->nearnullsp; 8961 PetscFunctionReturn(PETSC_SUCCESS); 8962 } 8963 8964 /*@C 8965 MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix. 8966 8967 Collective 8968 8969 Input Parameters: 8970 + mat - the matrix 8971 . row - row/column permutation 8972 - info - information on desired factorization process 8973 8974 Level: developer 8975 8976 Notes: 8977 Probably really in-place only when level of fill is zero, otherwise allocates 8978 new space to store factored matrix and deletes previous memory. 8979 8980 Most users should employ the `KSP` interface for linear solvers 8981 instead of working directly with matrix algebra routines such as this. 8982 See, e.g., `KSPCreate()`. 8983 8984 Developer Note: 8985 The Fortran interface is not autogenerated as the 8986 interface definition cannot be generated correctly [due to `MatFactorInfo`] 8987 8988 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 8989 @*/ 8990 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info) 8991 { 8992 PetscFunctionBegin; 8993 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8994 PetscValidType(mat, 1); 8995 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 8996 PetscValidPointer(info, 3); 8997 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 8998 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 8999 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 9000 MatCheckPreallocated(mat, 1); 9001 PetscUseTypeMethod(mat, iccfactor, row, info); 9002 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9003 PetscFunctionReturn(PETSC_SUCCESS); 9004 } 9005 9006 /*@ 9007 MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the 9008 ghosted ones. 9009 9010 Not Collective 9011 9012 Input Parameters: 9013 + mat - the matrix 9014 - diag - the diagonal values, including ghost ones 9015 9016 Level: developer 9017 9018 Notes: 9019 Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices 9020 9021 This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()` 9022 9023 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 9024 @*/ 9025 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag) 9026 { 9027 PetscMPIInt size; 9028 9029 PetscFunctionBegin; 9030 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9031 PetscValidHeaderSpecific(diag, VEC_CLASSID, 2); 9032 PetscValidType(mat, 1); 9033 9034 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled"); 9035 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 9036 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 9037 if (size == 1) { 9038 PetscInt n, m; 9039 PetscCall(VecGetSize(diag, &n)); 9040 PetscCall(MatGetSize(mat, NULL, &m)); 9041 PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions"); 9042 PetscCall(MatDiagonalScale(mat, NULL, diag)); 9043 } else { 9044 PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag)); 9045 } 9046 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 9047 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9048 PetscFunctionReturn(PETSC_SUCCESS); 9049 } 9050 9051 /*@ 9052 MatGetInertia - Gets the inertia from a factored matrix 9053 9054 Collective 9055 9056 Input Parameter: 9057 . mat - the matrix 9058 9059 Output Parameters: 9060 + nneg - number of negative eigenvalues 9061 . nzero - number of zero eigenvalues 9062 - npos - number of positive eigenvalues 9063 9064 Level: advanced 9065 9066 Note: 9067 Matrix must have been factored by `MatCholeskyFactor()` 9068 9069 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()` 9070 @*/ 9071 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos) 9072 { 9073 PetscFunctionBegin; 9074 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9075 PetscValidType(mat, 1); 9076 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9077 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled"); 9078 PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos); 9079 PetscFunctionReturn(PETSC_SUCCESS); 9080 } 9081 9082 /*@C 9083 MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors 9084 9085 Neighbor-wise Collective 9086 9087 Input Parameters: 9088 + mat - the factored matrix obtained with `MatGetFactor()` 9089 - b - the right-hand-side vectors 9090 9091 Output Parameter: 9092 . x - the result vectors 9093 9094 Level: developer 9095 9096 Note: 9097 The vectors `b` and `x` cannot be the same. I.e., one cannot 9098 call `MatSolves`(A,x,x). 9099 9100 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()` 9101 @*/ 9102 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x) 9103 { 9104 PetscFunctionBegin; 9105 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9106 PetscValidType(mat, 1); 9107 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 9108 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9109 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 9110 9111 MatCheckPreallocated(mat, 1); 9112 PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0)); 9113 PetscUseTypeMethod(mat, solves, b, x); 9114 PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0)); 9115 PetscFunctionReturn(PETSC_SUCCESS); 9116 } 9117 9118 /*@ 9119 MatIsSymmetric - Test whether a matrix is symmetric 9120 9121 Collective 9122 9123 Input Parameters: 9124 + A - the matrix to test 9125 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose) 9126 9127 Output Parameter: 9128 . flg - the result 9129 9130 Level: intermediate 9131 9132 Notes: 9133 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9134 9135 If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()` 9136 9137 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9138 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9139 9140 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`, 9141 `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()` 9142 @*/ 9143 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg) 9144 { 9145 PetscFunctionBegin; 9146 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9147 PetscValidBoolPointer(flg, 3); 9148 9149 if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE; 9150 else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE; 9151 else { 9152 PetscUseTypeMethod(A, issymmetric, tol, flg); 9153 if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg)); 9154 } 9155 PetscFunctionReturn(PETSC_SUCCESS); 9156 } 9157 9158 /*@ 9159 MatIsHermitian - Test whether a matrix is Hermitian 9160 9161 Collective 9162 9163 Input Parameters: 9164 + A - the matrix to test 9165 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian) 9166 9167 Output Parameter: 9168 . flg - the result 9169 9170 Level: intermediate 9171 9172 Notes: 9173 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9174 9175 If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()` 9176 9177 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9178 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`) 9179 9180 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, 9181 `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()` 9182 @*/ 9183 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg) 9184 { 9185 PetscFunctionBegin; 9186 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9187 PetscValidBoolPointer(flg, 3); 9188 9189 if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE; 9190 else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE; 9191 else { 9192 PetscUseTypeMethod(A, ishermitian, tol, flg); 9193 if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg)); 9194 } 9195 PetscFunctionReturn(PETSC_SUCCESS); 9196 } 9197 9198 /*@ 9199 MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state 9200 9201 Not Collective 9202 9203 Input Parameter: 9204 . A - the matrix to check 9205 9206 Output Parameters: 9207 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid) 9208 - flg - the result (only valid if set is `PETSC_TRUE`) 9209 9210 Level: advanced 9211 9212 Notes: 9213 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()` 9214 if you want it explicitly checked 9215 9216 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9217 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9218 9219 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9220 @*/ 9221 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9222 { 9223 PetscFunctionBegin; 9224 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9225 PetscValidBoolPointer(set, 2); 9226 PetscValidBoolPointer(flg, 3); 9227 if (A->symmetric != PETSC_BOOL3_UNKNOWN) { 9228 *set = PETSC_TRUE; 9229 *flg = PetscBool3ToBool(A->symmetric); 9230 } else { 9231 *set = PETSC_FALSE; 9232 } 9233 PetscFunctionReturn(PETSC_SUCCESS); 9234 } 9235 9236 /*@ 9237 MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state 9238 9239 Not Collective 9240 9241 Input Parameter: 9242 . A - the matrix to check 9243 9244 Output Parameters: 9245 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid) 9246 - flg - the result (only valid if set is `PETSC_TRUE`) 9247 9248 Level: advanced 9249 9250 Notes: 9251 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). 9252 9253 One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD 9254 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`) 9255 9256 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9257 @*/ 9258 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg) 9259 { 9260 PetscFunctionBegin; 9261 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9262 PetscValidBoolPointer(set, 2); 9263 PetscValidBoolPointer(flg, 3); 9264 if (A->spd != PETSC_BOOL3_UNKNOWN) { 9265 *set = PETSC_TRUE; 9266 *flg = PetscBool3ToBool(A->spd); 9267 } else { 9268 *set = PETSC_FALSE; 9269 } 9270 PetscFunctionReturn(PETSC_SUCCESS); 9271 } 9272 9273 /*@ 9274 MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state 9275 9276 Not Collective 9277 9278 Input Parameter: 9279 . A - the matrix to check 9280 9281 Output Parameters: 9282 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid) 9283 - flg - the result (only valid if set is `PETSC_TRUE`) 9284 9285 Level: advanced 9286 9287 Notes: 9288 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()` 9289 if you want it explicitly checked 9290 9291 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9292 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9293 9294 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()` 9295 @*/ 9296 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg) 9297 { 9298 PetscFunctionBegin; 9299 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9300 PetscValidBoolPointer(set, 2); 9301 PetscValidBoolPointer(flg, 3); 9302 if (A->hermitian != PETSC_BOOL3_UNKNOWN) { 9303 *set = PETSC_TRUE; 9304 *flg = PetscBool3ToBool(A->hermitian); 9305 } else { 9306 *set = PETSC_FALSE; 9307 } 9308 PetscFunctionReturn(PETSC_SUCCESS); 9309 } 9310 9311 /*@ 9312 MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric 9313 9314 Collective 9315 9316 Input Parameter: 9317 . A - the matrix to test 9318 9319 Output Parameter: 9320 . flg - the result 9321 9322 Level: intermediate 9323 9324 Notes: 9325 If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()` 9326 9327 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 9328 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9329 9330 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()` 9331 @*/ 9332 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg) 9333 { 9334 PetscFunctionBegin; 9335 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9336 PetscValidBoolPointer(flg, 2); 9337 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9338 *flg = PetscBool3ToBool(A->structurally_symmetric); 9339 } else { 9340 PetscUseTypeMethod(A, isstructurallysymmetric, flg); 9341 PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg)); 9342 } 9343 PetscFunctionReturn(PETSC_SUCCESS); 9344 } 9345 9346 /*@ 9347 MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state 9348 9349 Not Collective 9350 9351 Input Parameter: 9352 . A - the matrix to check 9353 9354 Output Parameters: 9355 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid) 9356 - flg - the result (only valid if set is PETSC_TRUE) 9357 9358 Level: advanced 9359 9360 Notes: 9361 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 9362 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9363 9364 Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation) 9365 9366 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9367 @*/ 9368 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9369 { 9370 PetscFunctionBegin; 9371 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9372 PetscValidBoolPointer(set, 2); 9373 PetscValidBoolPointer(flg, 3); 9374 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9375 *set = PETSC_TRUE; 9376 *flg = PetscBool3ToBool(A->structurally_symmetric); 9377 } else { 9378 *set = PETSC_FALSE; 9379 } 9380 PetscFunctionReturn(PETSC_SUCCESS); 9381 } 9382 9383 /*@ 9384 MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need 9385 to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process 9386 9387 Not Collective 9388 9389 Input Parameter: 9390 . mat - the matrix 9391 9392 Output Parameters: 9393 + nstash - the size of the stash 9394 . reallocs - the number of additional mallocs incurred. 9395 . bnstash - the size of the block stash 9396 - breallocs - the number of additional mallocs incurred.in the block stash 9397 9398 Level: advanced 9399 9400 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()` 9401 @*/ 9402 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs) 9403 { 9404 PetscFunctionBegin; 9405 PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs)); 9406 PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs)); 9407 PetscFunctionReturn(PETSC_SUCCESS); 9408 } 9409 9410 /*@C 9411 MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same 9412 parallel layout, `PetscLayout` for rows and columns 9413 9414 Collective 9415 9416 Input Parameter: 9417 . mat - the matrix 9418 9419 Output Parameters: 9420 + right - (optional) vector that the matrix can be multiplied against 9421 - left - (optional) vector that the matrix vector product can be stored in 9422 9423 Level: advanced 9424 9425 Notes: 9426 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()`. 9427 9428 These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed 9429 9430 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()` 9431 @*/ 9432 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left) 9433 { 9434 PetscFunctionBegin; 9435 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9436 PetscValidType(mat, 1); 9437 if (mat->ops->getvecs) { 9438 PetscUseTypeMethod(mat, getvecs, right, left); 9439 } else { 9440 if (right) { 9441 PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup"); 9442 PetscCall(VecCreateWithLayout_Private(mat->cmap, right)); 9443 PetscCall(VecSetType(*right, mat->defaultvectype)); 9444 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9445 if (mat->boundtocpu && mat->bindingpropagates) { 9446 PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE)); 9447 PetscCall(VecBindToCPU(*right, PETSC_TRUE)); 9448 } 9449 #endif 9450 } 9451 if (left) { 9452 PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup"); 9453 PetscCall(VecCreateWithLayout_Private(mat->rmap, left)); 9454 PetscCall(VecSetType(*left, mat->defaultvectype)); 9455 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9456 if (mat->boundtocpu && mat->bindingpropagates) { 9457 PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE)); 9458 PetscCall(VecBindToCPU(*left, PETSC_TRUE)); 9459 } 9460 #endif 9461 } 9462 } 9463 PetscFunctionReturn(PETSC_SUCCESS); 9464 } 9465 9466 /*@C 9467 MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure 9468 with default values. 9469 9470 Not Collective 9471 9472 Input Parameter: 9473 . info - the `MatFactorInfo` data structure 9474 9475 Level: developer 9476 9477 Notes: 9478 The solvers are generally used through the `KSP` and `PC` objects, for example 9479 `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC` 9480 9481 Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed 9482 9483 Developer Note: 9484 The Fortran interface is not autogenerated as the 9485 interface definition cannot be generated correctly [due to `MatFactorInfo`] 9486 9487 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo` 9488 @*/ 9489 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info) 9490 { 9491 PetscFunctionBegin; 9492 PetscCall(PetscMemzero(info, sizeof(MatFactorInfo))); 9493 PetscFunctionReturn(PETSC_SUCCESS); 9494 } 9495 9496 /*@ 9497 MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed 9498 9499 Collective 9500 9501 Input Parameters: 9502 + mat - the factored matrix 9503 - is - the index set defining the Schur indices (0-based) 9504 9505 Level: advanced 9506 9507 Notes: 9508 Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system. 9509 9510 You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call. 9511 9512 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9513 9514 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`, 9515 `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9516 @*/ 9517 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is) 9518 { 9519 PetscErrorCode (*f)(Mat, IS); 9520 9521 PetscFunctionBegin; 9522 PetscValidType(mat, 1); 9523 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9524 PetscValidType(is, 2); 9525 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 9526 PetscCheckSameComm(mat, 1, is, 2); 9527 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 9528 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f)); 9529 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO"); 9530 PetscCall(MatDestroy(&mat->schur)); 9531 PetscCall((*f)(mat, is)); 9532 PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created"); 9533 PetscFunctionReturn(PETSC_SUCCESS); 9534 } 9535 9536 /*@ 9537 MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step 9538 9539 Logically Collective 9540 9541 Input Parameters: 9542 + F - the factored matrix obtained by calling `MatGetFactor()` 9543 . S - location where to return the Schur complement, can be `NULL` 9544 - status - the status of the Schur complement matrix, can be `NULL` 9545 9546 Level: advanced 9547 9548 Notes: 9549 You must call `MatFactorSetSchurIS()` before calling this routine. 9550 9551 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9552 9553 The routine provides a copy of the Schur matrix stored within the solver data structures. 9554 The caller must destroy the object when it is no longer needed. 9555 If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse. 9556 9557 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) 9558 9559 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9560 9561 Developer Note: 9562 The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc 9563 matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix. 9564 9565 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9566 @*/ 9567 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9568 { 9569 PetscFunctionBegin; 9570 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9571 if (S) PetscValidPointer(S, 2); 9572 if (status) PetscValidPointer(status, 3); 9573 if (S) { 9574 PetscErrorCode (*f)(Mat, Mat *); 9575 9576 PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f)); 9577 if (f) { 9578 PetscCall((*f)(F, S)); 9579 } else { 9580 PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S)); 9581 } 9582 } 9583 if (status) *status = F->schur_status; 9584 PetscFunctionReturn(PETSC_SUCCESS); 9585 } 9586 9587 /*@ 9588 MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix 9589 9590 Logically Collective 9591 9592 Input Parameters: 9593 + F - the factored matrix obtained by calling `MatGetFactor()` 9594 . *S - location where to return the Schur complement, can be `NULL` 9595 - status - the status of the Schur complement matrix, can be `NULL` 9596 9597 Level: advanced 9598 9599 Notes: 9600 You must call `MatFactorSetSchurIS()` before calling this routine. 9601 9602 Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS` 9603 9604 The routine returns a the Schur Complement stored within the data structures of the solver. 9605 9606 If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement. 9607 9608 The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed. 9609 9610 Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix 9611 9612 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9613 9614 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9615 @*/ 9616 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9617 { 9618 PetscFunctionBegin; 9619 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9620 if (S) PetscValidPointer(S, 2); 9621 if (status) PetscValidPointer(status, 3); 9622 if (S) *S = F->schur; 9623 if (status) *status = F->schur_status; 9624 PetscFunctionReturn(PETSC_SUCCESS); 9625 } 9626 9627 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F) 9628 { 9629 Mat S = F->schur; 9630 9631 PetscFunctionBegin; 9632 switch (F->schur_status) { 9633 case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through 9634 case MAT_FACTOR_SCHUR_INVERTED: 9635 if (S) { 9636 S->ops->solve = NULL; 9637 S->ops->matsolve = NULL; 9638 S->ops->solvetranspose = NULL; 9639 S->ops->matsolvetranspose = NULL; 9640 S->ops->solveadd = NULL; 9641 S->ops->solvetransposeadd = NULL; 9642 S->factortype = MAT_FACTOR_NONE; 9643 PetscCall(PetscFree(S->solvertype)); 9644 } 9645 case MAT_FACTOR_SCHUR_FACTORED: // fall-through 9646 break; 9647 default: 9648 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9649 } 9650 PetscFunctionReturn(PETSC_SUCCESS); 9651 } 9652 9653 /*@ 9654 MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()` 9655 9656 Logically Collective 9657 9658 Input Parameters: 9659 + F - the factored matrix obtained by calling `MatGetFactor()` 9660 . *S - location where the Schur complement is stored 9661 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`) 9662 9663 Level: advanced 9664 9665 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9666 @*/ 9667 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status) 9668 { 9669 PetscFunctionBegin; 9670 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9671 if (S) { 9672 PetscValidHeaderSpecific(*S, MAT_CLASSID, 2); 9673 *S = NULL; 9674 } 9675 F->schur_status = status; 9676 PetscCall(MatFactorUpdateSchurStatus_Private(F)); 9677 PetscFunctionReturn(PETSC_SUCCESS); 9678 } 9679 9680 /*@ 9681 MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step 9682 9683 Logically Collective 9684 9685 Input Parameters: 9686 + F - the factored matrix obtained by calling `MatGetFactor()` 9687 . rhs - location where the right hand side of the Schur complement system is stored 9688 - sol - location where the solution of the Schur complement system has to be returned 9689 9690 Level: advanced 9691 9692 Notes: 9693 The sizes of the vectors should match the size of the Schur complement 9694 9695 Must be called after `MatFactorSetSchurIS()` 9696 9697 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()` 9698 @*/ 9699 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol) 9700 { 9701 PetscFunctionBegin; 9702 PetscValidType(F, 1); 9703 PetscValidType(rhs, 2); 9704 PetscValidType(sol, 3); 9705 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9706 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9707 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9708 PetscCheckSameComm(F, 1, rhs, 2); 9709 PetscCheckSameComm(F, 1, sol, 3); 9710 PetscCall(MatFactorFactorizeSchurComplement(F)); 9711 switch (F->schur_status) { 9712 case MAT_FACTOR_SCHUR_FACTORED: 9713 PetscCall(MatSolveTranspose(F->schur, rhs, sol)); 9714 break; 9715 case MAT_FACTOR_SCHUR_INVERTED: 9716 PetscCall(MatMultTranspose(F->schur, rhs, sol)); 9717 break; 9718 default: 9719 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9720 } 9721 PetscFunctionReturn(PETSC_SUCCESS); 9722 } 9723 9724 /*@ 9725 MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step 9726 9727 Logically Collective 9728 9729 Input Parameters: 9730 + F - the factored matrix obtained by calling `MatGetFactor()` 9731 . rhs - location where the right hand side of the Schur complement system is stored 9732 - sol - location where the solution of the Schur complement system has to be returned 9733 9734 Level: advanced 9735 9736 Notes: 9737 The sizes of the vectors should match the size of the Schur complement 9738 9739 Must be called after `MatFactorSetSchurIS()` 9740 9741 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()` 9742 @*/ 9743 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol) 9744 { 9745 PetscFunctionBegin; 9746 PetscValidType(F, 1); 9747 PetscValidType(rhs, 2); 9748 PetscValidType(sol, 3); 9749 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9750 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9751 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9752 PetscCheckSameComm(F, 1, rhs, 2); 9753 PetscCheckSameComm(F, 1, sol, 3); 9754 PetscCall(MatFactorFactorizeSchurComplement(F)); 9755 switch (F->schur_status) { 9756 case MAT_FACTOR_SCHUR_FACTORED: 9757 PetscCall(MatSolve(F->schur, rhs, sol)); 9758 break; 9759 case MAT_FACTOR_SCHUR_INVERTED: 9760 PetscCall(MatMult(F->schur, rhs, sol)); 9761 break; 9762 default: 9763 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9764 } 9765 PetscFunctionReturn(PETSC_SUCCESS); 9766 } 9767 9768 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat); 9769 #if PetscDefined(HAVE_CUDA) 9770 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat); 9771 #endif 9772 9773 /* Schur status updated in the interface */ 9774 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F) 9775 { 9776 Mat S = F->schur; 9777 9778 PetscFunctionBegin; 9779 if (S) { 9780 PetscMPIInt size; 9781 PetscBool isdense, isdensecuda; 9782 9783 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size)); 9784 PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented"); 9785 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense)); 9786 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda)); 9787 PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name); 9788 PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0)); 9789 if (isdense) { 9790 PetscCall(MatSeqDenseInvertFactors_Private(S)); 9791 } else if (isdensecuda) { 9792 #if defined(PETSC_HAVE_CUDA) 9793 PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S)); 9794 #endif 9795 } 9796 // HIP?????????????? 9797 PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0)); 9798 } 9799 PetscFunctionReturn(PETSC_SUCCESS); 9800 } 9801 9802 /*@ 9803 MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step 9804 9805 Logically Collective 9806 9807 Input Parameter: 9808 . F - the factored matrix obtained by calling `MatGetFactor()` 9809 9810 Level: advanced 9811 9812 Notes: 9813 Must be called after `MatFactorSetSchurIS()`. 9814 9815 Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it. 9816 9817 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()` 9818 @*/ 9819 PetscErrorCode MatFactorInvertSchurComplement(Mat F) 9820 { 9821 PetscFunctionBegin; 9822 PetscValidType(F, 1); 9823 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9824 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS); 9825 PetscCall(MatFactorFactorizeSchurComplement(F)); 9826 PetscCall(MatFactorInvertSchurComplement_Private(F)); 9827 F->schur_status = MAT_FACTOR_SCHUR_INVERTED; 9828 PetscFunctionReturn(PETSC_SUCCESS); 9829 } 9830 9831 /*@ 9832 MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step 9833 9834 Logically Collective 9835 9836 Input Parameter: 9837 . F - the factored matrix obtained by calling `MatGetFactor()` 9838 9839 Level: advanced 9840 9841 Note: 9842 Must be called after `MatFactorSetSchurIS()` 9843 9844 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()` 9845 @*/ 9846 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F) 9847 { 9848 MatFactorInfo info; 9849 9850 PetscFunctionBegin; 9851 PetscValidType(F, 1); 9852 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9853 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS); 9854 PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0)); 9855 PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo))); 9856 if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */ 9857 PetscCall(MatCholeskyFactor(F->schur, NULL, &info)); 9858 } else { 9859 PetscCall(MatLUFactor(F->schur, NULL, NULL, &info)); 9860 } 9861 PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0)); 9862 F->schur_status = MAT_FACTOR_SCHUR_FACTORED; 9863 PetscFunctionReturn(PETSC_SUCCESS); 9864 } 9865 9866 /*@ 9867 MatPtAP - Creates the matrix product C = P^T * A * P 9868 9869 Neighbor-wise Collective 9870 9871 Input Parameters: 9872 + A - the matrix 9873 . P - the projection matrix 9874 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9875 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate 9876 if the result is a dense matrix this is irrelevant 9877 9878 Output Parameter: 9879 . C - the product matrix 9880 9881 Level: intermediate 9882 9883 Notes: 9884 C will be created and must be destroyed by the user with `MatDestroy()`. 9885 9886 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9887 9888 Developer Note: 9889 For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`. 9890 9891 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()` 9892 @*/ 9893 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C) 9894 { 9895 PetscFunctionBegin; 9896 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 9897 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9898 9899 if (scall == MAT_INITIAL_MATRIX) { 9900 PetscCall(MatProductCreate(A, P, NULL, C)); 9901 PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP)); 9902 PetscCall(MatProductSetAlgorithm(*C, "default")); 9903 PetscCall(MatProductSetFill(*C, fill)); 9904 9905 (*C)->product->api_user = PETSC_TRUE; 9906 PetscCall(MatProductSetFromOptions(*C)); 9907 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); 9908 PetscCall(MatProductSymbolic(*C)); 9909 } else { /* scall == MAT_REUSE_MATRIX */ 9910 PetscCall(MatProductReplaceMats(A, P, NULL, *C)); 9911 } 9912 9913 PetscCall(MatProductNumeric(*C)); 9914 (*C)->symmetric = A->symmetric; 9915 (*C)->spd = A->spd; 9916 PetscFunctionReturn(PETSC_SUCCESS); 9917 } 9918 9919 /*@ 9920 MatRARt - Creates the matrix product C = R * A * R^T 9921 9922 Neighbor-wise Collective 9923 9924 Input Parameters: 9925 + A - the matrix 9926 . R - the projection matrix 9927 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9928 - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate 9929 if the result is a dense matrix this is irrelevant 9930 9931 Output Parameter: 9932 . C - the product matrix 9933 9934 Level: intermediate 9935 9936 Notes: 9937 C will be created and must be destroyed by the user with `MatDestroy()`. 9938 9939 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9940 9941 This routine is currently only implemented for pairs of `MATAIJ` matrices and classes 9942 which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes, 9943 parallel MatRARt is implemented via explicit transpose of R, which could be very expensive. 9944 We recommend using MatPtAP(). 9945 9946 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()` 9947 @*/ 9948 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C) 9949 { 9950 PetscFunctionBegin; 9951 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 9952 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9953 9954 if (scall == MAT_INITIAL_MATRIX) { 9955 PetscCall(MatProductCreate(A, R, NULL, C)); 9956 PetscCall(MatProductSetType(*C, MATPRODUCT_RARt)); 9957 PetscCall(MatProductSetAlgorithm(*C, "default")); 9958 PetscCall(MatProductSetFill(*C, fill)); 9959 9960 (*C)->product->api_user = PETSC_TRUE; 9961 PetscCall(MatProductSetFromOptions(*C)); 9962 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); 9963 PetscCall(MatProductSymbolic(*C)); 9964 } else { /* scall == MAT_REUSE_MATRIX */ 9965 PetscCall(MatProductReplaceMats(A, R, NULL, *C)); 9966 } 9967 9968 PetscCall(MatProductNumeric(*C)); 9969 if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 9970 PetscFunctionReturn(PETSC_SUCCESS); 9971 } 9972 9973 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C) 9974 { 9975 PetscFunctionBegin; 9976 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9977 9978 if (scall == MAT_INITIAL_MATRIX) { 9979 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype])); 9980 PetscCall(MatProductCreate(A, B, NULL, C)); 9981 PetscCall(MatProductSetType(*C, ptype)); 9982 PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT)); 9983 PetscCall(MatProductSetFill(*C, fill)); 9984 9985 (*C)->product->api_user = PETSC_TRUE; 9986 PetscCall(MatProductSetFromOptions(*C)); 9987 PetscCall(MatProductSymbolic(*C)); 9988 } else { /* scall == MAT_REUSE_MATRIX */ 9989 Mat_Product *product = (*C)->product; 9990 PetscBool isdense; 9991 9992 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, "")); 9993 if (isdense && product && product->type != ptype) { 9994 PetscCall(MatProductClear(*C)); 9995 product = NULL; 9996 } 9997 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype])); 9998 if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */ 9999 PetscCheck(isdense, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first"); 10000 PetscCall(MatProductCreate_Private(A, B, NULL, *C)); 10001 product = (*C)->product; 10002 product->fill = fill; 10003 product->api_user = PETSC_TRUE; 10004 product->clear = PETSC_TRUE; 10005 10006 PetscCall(MatProductSetType(*C, ptype)); 10007 PetscCall(MatProductSetFromOptions(*C)); 10008 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); 10009 PetscCall(MatProductSymbolic(*C)); 10010 } else { /* user may change input matrices A or B when REUSE */ 10011 PetscCall(MatProductReplaceMats(A, B, NULL, *C)); 10012 } 10013 } 10014 PetscCall(MatProductNumeric(*C)); 10015 PetscFunctionReturn(PETSC_SUCCESS); 10016 } 10017 10018 /*@ 10019 MatMatMult - Performs matrix-matrix multiplication C=A*B. 10020 10021 Neighbor-wise Collective 10022 10023 Input Parameters: 10024 + A - the left matrix 10025 . B - the right matrix 10026 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10027 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate 10028 if the result is a dense matrix this is irrelevant 10029 10030 Output Parameter: 10031 . C - the product matrix 10032 10033 Notes: 10034 Unless scall is `MAT_REUSE_MATRIX` C will be created. 10035 10036 `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 10037 call to this function with `MAT_INITIAL_MATRIX`. 10038 10039 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed. 10040 10041 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`, 10042 rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse. 10043 10044 Example of Usage: 10045 .vb 10046 MatProductCreate(A,B,NULL,&C); 10047 MatProductSetType(C,MATPRODUCT_AB); 10048 MatProductSymbolic(C); 10049 MatProductNumeric(C); // compute C=A * B 10050 MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1 10051 MatProductNumeric(C); 10052 MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1 10053 MatProductNumeric(C); 10054 .ve 10055 10056 Level: intermediate 10057 10058 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()` 10059 @*/ 10060 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10061 { 10062 PetscFunctionBegin; 10063 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C)); 10064 PetscFunctionReturn(PETSC_SUCCESS); 10065 } 10066 10067 /*@ 10068 MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T. 10069 10070 Neighbor-wise Collective 10071 10072 Input Parameters: 10073 + A - the left matrix 10074 . B - the right matrix 10075 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10076 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 10077 10078 Output Parameter: 10079 . C - the product matrix 10080 10081 Level: intermediate 10082 10083 Notes: 10084 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10085 10086 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call 10087 10088 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10089 actually needed. 10090 10091 This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class, 10092 and for pairs of `MATMPIDENSE` matrices. 10093 10094 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt` 10095 10096 Options Database Keys: 10097 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the 10098 first redundantly copies the transposed B matrix on each process and requires O(log P) communication complexity; 10099 the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity. 10100 10101 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductCreate()`, `MatProductAlgorithm`, `MatProductType`, `MATPRODUCT_ABt` 10102 @*/ 10103 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10104 { 10105 PetscFunctionBegin; 10106 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C)); 10107 if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10108 PetscFunctionReturn(PETSC_SUCCESS); 10109 } 10110 10111 /*@ 10112 MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B. 10113 10114 Neighbor-wise Collective 10115 10116 Input Parameters: 10117 + A - the left matrix 10118 . B - the right matrix 10119 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10120 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 10121 10122 Output Parameter: 10123 . C - the product matrix 10124 10125 Level: intermediate 10126 10127 Notes: 10128 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10129 10130 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call. 10131 10132 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB` 10133 10134 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10135 actually needed. 10136 10137 This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes 10138 which inherit from `MATSEQAIJ`. C will be of the same type as the input matrices. 10139 10140 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()` 10141 @*/ 10142 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10143 { 10144 PetscFunctionBegin; 10145 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C)); 10146 PetscFunctionReturn(PETSC_SUCCESS); 10147 } 10148 10149 /*@ 10150 MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C. 10151 10152 Neighbor-wise Collective 10153 10154 Input Parameters: 10155 + A - the left matrix 10156 . B - the middle matrix 10157 . C - the right matrix 10158 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10159 - 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 10160 if the result is a dense matrix this is irrelevant 10161 10162 Output Parameter: 10163 . D - the product matrix 10164 10165 Level: intermediate 10166 10167 Notes: 10168 Unless scall is `MAT_REUSE_MATRIX` D will be created. 10169 10170 `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call 10171 10172 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC` 10173 10174 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10175 actually needed. 10176 10177 If you have many matrices with the same non-zero structure to multiply, you 10178 should use `MAT_REUSE_MATRIX` in all calls but the first 10179 10180 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()` 10181 @*/ 10182 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D) 10183 { 10184 PetscFunctionBegin; 10185 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6); 10186 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10187 10188 if (scall == MAT_INITIAL_MATRIX) { 10189 PetscCall(MatProductCreate(A, B, C, D)); 10190 PetscCall(MatProductSetType(*D, MATPRODUCT_ABC)); 10191 PetscCall(MatProductSetAlgorithm(*D, "default")); 10192 PetscCall(MatProductSetFill(*D, fill)); 10193 10194 (*D)->product->api_user = PETSC_TRUE; 10195 PetscCall(MatProductSetFromOptions(*D)); 10196 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, 10197 ((PetscObject)C)->type_name); 10198 PetscCall(MatProductSymbolic(*D)); 10199 } else { /* user may change input matrices when REUSE */ 10200 PetscCall(MatProductReplaceMats(A, B, C, *D)); 10201 } 10202 PetscCall(MatProductNumeric(*D)); 10203 PetscFunctionReturn(PETSC_SUCCESS); 10204 } 10205 10206 /*@ 10207 MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators. 10208 10209 Collective 10210 10211 Input Parameters: 10212 + mat - the matrix 10213 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices) 10214 . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used) 10215 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10216 10217 Output Parameter: 10218 . matredundant - redundant matrix 10219 10220 Level: advanced 10221 10222 Notes: 10223 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 10224 original matrix has not changed from that last call to MatCreateRedundantMatrix(). 10225 10226 This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before 10227 calling it. 10228 10229 `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be. 10230 10231 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubComm` 10232 @*/ 10233 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant) 10234 { 10235 MPI_Comm comm; 10236 PetscMPIInt size; 10237 PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs; 10238 Mat_Redundant *redund = NULL; 10239 PetscSubcomm psubcomm = NULL; 10240 MPI_Comm subcomm_in = subcomm; 10241 Mat *matseq; 10242 IS isrow, iscol; 10243 PetscBool newsubcomm = PETSC_FALSE; 10244 10245 PetscFunctionBegin; 10246 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10247 if (nsubcomm && reuse == MAT_REUSE_MATRIX) { 10248 PetscValidPointer(*matredundant, 5); 10249 PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5); 10250 } 10251 10252 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10253 if (size == 1 || nsubcomm == 1) { 10254 if (reuse == MAT_INITIAL_MATRIX) { 10255 PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant)); 10256 } else { 10257 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"); 10258 PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN)); 10259 } 10260 PetscFunctionReturn(PETSC_SUCCESS); 10261 } 10262 10263 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10264 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10265 MatCheckPreallocated(mat, 1); 10266 10267 PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0)); 10268 if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */ 10269 /* create psubcomm, then get subcomm */ 10270 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10271 PetscCallMPI(MPI_Comm_size(comm, &size)); 10272 PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size); 10273 10274 PetscCall(PetscSubcommCreate(comm, &psubcomm)); 10275 PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm)); 10276 PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS)); 10277 PetscCall(PetscSubcommSetFromOptions(psubcomm)); 10278 PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL)); 10279 newsubcomm = PETSC_TRUE; 10280 PetscCall(PetscSubcommDestroy(&psubcomm)); 10281 } 10282 10283 /* get isrow, iscol and a local sequential matrix matseq[0] */ 10284 if (reuse == MAT_INITIAL_MATRIX) { 10285 mloc_sub = PETSC_DECIDE; 10286 nloc_sub = PETSC_DECIDE; 10287 if (bs < 1) { 10288 PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M)); 10289 PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N)); 10290 } else { 10291 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M)); 10292 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N)); 10293 } 10294 PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm)); 10295 rstart = rend - mloc_sub; 10296 PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow)); 10297 PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol)); 10298 } else { /* reuse == MAT_REUSE_MATRIX */ 10299 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"); 10300 /* retrieve subcomm */ 10301 PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm)); 10302 redund = (*matredundant)->redundant; 10303 isrow = redund->isrow; 10304 iscol = redund->iscol; 10305 matseq = redund->matseq; 10306 } 10307 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq)); 10308 10309 /* get matredundant over subcomm */ 10310 if (reuse == MAT_INITIAL_MATRIX) { 10311 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant)); 10312 10313 /* create a supporting struct and attach it to C for reuse */ 10314 PetscCall(PetscNew(&redund)); 10315 (*matredundant)->redundant = redund; 10316 redund->isrow = isrow; 10317 redund->iscol = iscol; 10318 redund->matseq = matseq; 10319 if (newsubcomm) { 10320 redund->subcomm = subcomm; 10321 } else { 10322 redund->subcomm = MPI_COMM_NULL; 10323 } 10324 } else { 10325 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant)); 10326 } 10327 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 10328 if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) { 10329 PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE)); 10330 PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE)); 10331 } 10332 #endif 10333 PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0)); 10334 PetscFunctionReturn(PETSC_SUCCESS); 10335 } 10336 10337 /*@C 10338 MatGetMultiProcBlock - Create multiple 'parallel submatrices' from 10339 a given `Mat`. Each submatrix can span multiple procs. 10340 10341 Collective 10342 10343 Input Parameters: 10344 + mat - the matrix 10345 . subcomm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))` 10346 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10347 10348 Output Parameter: 10349 . subMat - parallel sub-matrices each spanning a given `subcomm` 10350 10351 Level: advanced 10352 10353 Notes: 10354 The submatrix partition across processors is dictated by `subComm` a 10355 communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm` 10356 is not restricted to be grouped with consecutive original ranks. 10357 10358 Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices 10359 map directly to the layout of the original matrix [wrt the local 10360 row,col partitioning]. So the original 'DiagonalMat' naturally maps 10361 into the 'DiagonalMat' of the `subMat`, hence it is used directly from 10362 the `subMat`. However the offDiagMat looses some columns - and this is 10363 reconstructed with `MatSetValues()` 10364 10365 This is used by `PCBJACOBI` when a single block spans multiple MPI processes. 10366 10367 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI` 10368 @*/ 10369 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) 10370 { 10371 PetscMPIInt commsize, subCommSize; 10372 10373 PetscFunctionBegin; 10374 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize)); 10375 PetscCallMPI(MPI_Comm_size(subComm, &subCommSize)); 10376 PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize); 10377 10378 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"); 10379 PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10380 PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat); 10381 PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10382 PetscFunctionReturn(PETSC_SUCCESS); 10383 } 10384 10385 /*@ 10386 MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering 10387 10388 Not Collective 10389 10390 Input Parameters: 10391 + mat - matrix to extract local submatrix from 10392 . isrow - local row indices for submatrix 10393 - iscol - local column indices for submatrix 10394 10395 Output Parameter: 10396 . submat - the submatrix 10397 10398 Level: intermediate 10399 10400 Notes: 10401 `submat` should be disposed of with `MatRestoreLocalSubMatrix()`. 10402 10403 Depending on the format of `mat`, the returned submat may not implement `MatMult()`. Its communicator may be 10404 the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of `mat`'s. 10405 10406 `submat` always implements `MatSetValuesLocal()`. If `isrow` and `iscol` have the same block size, then 10407 `MatSetValuesBlockedLocal()` will also be implemented. 10408 10409 `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`. 10410 Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided. 10411 10412 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()` 10413 @*/ 10414 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10415 { 10416 PetscFunctionBegin; 10417 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10418 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10419 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10420 PetscCheckSameComm(isrow, 2, iscol, 3); 10421 PetscValidPointer(submat, 4); 10422 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call"); 10423 10424 if (mat->ops->getlocalsubmatrix) { 10425 PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat); 10426 } else { 10427 PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat)); 10428 } 10429 PetscFunctionReturn(PETSC_SUCCESS); 10430 } 10431 10432 /*@ 10433 MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()` 10434 10435 Not Collective 10436 10437 Input Parameters: 10438 + mat - matrix to extract local submatrix from 10439 . isrow - local row indices for submatrix 10440 . iscol - local column indices for submatrix 10441 - submat - the submatrix 10442 10443 Level: intermediate 10444 10445 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()` 10446 @*/ 10447 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10448 { 10449 PetscFunctionBegin; 10450 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10451 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10452 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10453 PetscCheckSameComm(isrow, 2, iscol, 3); 10454 PetscValidPointer(submat, 4); 10455 if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4); 10456 10457 if (mat->ops->restorelocalsubmatrix) { 10458 PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat); 10459 } else { 10460 PetscCall(MatDestroy(submat)); 10461 } 10462 *submat = NULL; 10463 PetscFunctionReturn(PETSC_SUCCESS); 10464 } 10465 10466 /*@ 10467 MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix 10468 10469 Collective 10470 10471 Input Parameter: 10472 . mat - the matrix 10473 10474 Output Parameter: 10475 . is - if any rows have zero diagonals this contains the list of them 10476 10477 Level: developer 10478 10479 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10480 @*/ 10481 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is) 10482 { 10483 PetscFunctionBegin; 10484 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10485 PetscValidType(mat, 1); 10486 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10487 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10488 10489 if (!mat->ops->findzerodiagonals) { 10490 Vec diag; 10491 const PetscScalar *a; 10492 PetscInt *rows; 10493 PetscInt rStart, rEnd, r, nrow = 0; 10494 10495 PetscCall(MatCreateVecs(mat, &diag, NULL)); 10496 PetscCall(MatGetDiagonal(mat, diag)); 10497 PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd)); 10498 PetscCall(VecGetArrayRead(diag, &a)); 10499 for (r = 0; r < rEnd - rStart; ++r) 10500 if (a[r] == 0.0) ++nrow; 10501 PetscCall(PetscMalloc1(nrow, &rows)); 10502 nrow = 0; 10503 for (r = 0; r < rEnd - rStart; ++r) 10504 if (a[r] == 0.0) rows[nrow++] = r + rStart; 10505 PetscCall(VecRestoreArrayRead(diag, &a)); 10506 PetscCall(VecDestroy(&diag)); 10507 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is)); 10508 } else { 10509 PetscUseTypeMethod(mat, findzerodiagonals, is); 10510 } 10511 PetscFunctionReturn(PETSC_SUCCESS); 10512 } 10513 10514 /*@ 10515 MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size) 10516 10517 Collective 10518 10519 Input Parameter: 10520 . mat - the matrix 10521 10522 Output Parameter: 10523 . is - contains the list of rows with off block diagonal entries 10524 10525 Level: developer 10526 10527 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10528 @*/ 10529 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is) 10530 { 10531 PetscFunctionBegin; 10532 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10533 PetscValidType(mat, 1); 10534 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10535 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10536 10537 PetscUseTypeMethod(mat, findoffblockdiagonalentries, is); 10538 PetscFunctionReturn(PETSC_SUCCESS); 10539 } 10540 10541 /*@C 10542 MatInvertBlockDiagonal - Inverts the block diagonal entries. 10543 10544 Collective; No Fortran Support 10545 10546 Input Parameter: 10547 . mat - the matrix 10548 10549 Output Parameter: 10550 . values - the block inverses in column major order (FORTRAN-like) 10551 10552 Level: advanced 10553 10554 Notes: 10555 The size of the blocks is determined by the block size of the matrix. 10556 10557 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10558 10559 The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size 10560 10561 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()` 10562 @*/ 10563 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values) 10564 { 10565 PetscFunctionBegin; 10566 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10567 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10568 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10569 PetscUseTypeMethod(mat, invertblockdiagonal, values); 10570 PetscFunctionReturn(PETSC_SUCCESS); 10571 } 10572 10573 /*@C 10574 MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries. 10575 10576 Collective; No Fortran Support 10577 10578 Input Parameters: 10579 + mat - the matrix 10580 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()` 10581 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()` 10582 10583 Output Parameter: 10584 . values - the block inverses in column major order (FORTRAN-like) 10585 10586 Level: advanced 10587 10588 Notes: 10589 Use `MatInvertBlockDiagonal()` if all blocks have the same size 10590 10591 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10592 10593 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()` 10594 @*/ 10595 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values) 10596 { 10597 PetscFunctionBegin; 10598 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10599 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10600 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10601 PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values); 10602 PetscFunctionReturn(PETSC_SUCCESS); 10603 } 10604 10605 /*@ 10606 MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A 10607 10608 Collective 10609 10610 Input Parameters: 10611 + A - the matrix 10612 - C - matrix with inverted block diagonal of `A`. This matrix should be created and may have its type set. 10613 10614 Level: advanced 10615 10616 Note: 10617 The blocksize of the matrix is used to determine the blocks on the diagonal of `C` 10618 10619 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()` 10620 @*/ 10621 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C) 10622 { 10623 const PetscScalar *vals; 10624 PetscInt *dnnz; 10625 PetscInt m, rstart, rend, bs, i, j; 10626 10627 PetscFunctionBegin; 10628 PetscCall(MatInvertBlockDiagonal(A, &vals)); 10629 PetscCall(MatGetBlockSize(A, &bs)); 10630 PetscCall(MatGetLocalSize(A, &m, NULL)); 10631 PetscCall(MatSetLayouts(C, A->rmap, A->cmap)); 10632 PetscCall(PetscMalloc1(m / bs, &dnnz)); 10633 for (j = 0; j < m / bs; j++) dnnz[j] = 1; 10634 PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL)); 10635 PetscCall(PetscFree(dnnz)); 10636 PetscCall(MatGetOwnershipRange(C, &rstart, &rend)); 10637 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE)); 10638 for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES)); 10639 PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 10640 PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 10641 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE)); 10642 PetscFunctionReturn(PETSC_SUCCESS); 10643 } 10644 10645 /*@C 10646 MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created 10647 via `MatTransposeColoringCreate()`. 10648 10649 Collective 10650 10651 Input Parameter: 10652 . c - coloring context 10653 10654 Level: intermediate 10655 10656 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()` 10657 @*/ 10658 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c) 10659 { 10660 MatTransposeColoring matcolor = *c; 10661 10662 PetscFunctionBegin; 10663 if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS); 10664 if (--((PetscObject)matcolor)->refct > 0) { 10665 matcolor = NULL; 10666 PetscFunctionReturn(PETSC_SUCCESS); 10667 } 10668 10669 PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow)); 10670 PetscCall(PetscFree(matcolor->rows)); 10671 PetscCall(PetscFree(matcolor->den2sp)); 10672 PetscCall(PetscFree(matcolor->colorforcol)); 10673 PetscCall(PetscFree(matcolor->columns)); 10674 if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart)); 10675 PetscCall(PetscHeaderDestroy(c)); 10676 PetscFunctionReturn(PETSC_SUCCESS); 10677 } 10678 10679 /*@C 10680 MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which 10681 a `MatTransposeColoring` context has been created, computes a dense B^T by applying 10682 `MatTransposeColoring` to sparse B. 10683 10684 Collective 10685 10686 Input Parameters: 10687 + coloring - coloring context created with `MatTransposeColoringCreate()` 10688 - B - sparse matrix 10689 10690 Output Parameter: 10691 . Btdense - dense matrix B^T 10692 10693 Level: developer 10694 10695 Note: 10696 These are used internally for some implementations of `MatRARt()` 10697 10698 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()` 10699 @*/ 10700 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense) 10701 { 10702 PetscFunctionBegin; 10703 PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10704 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 10705 PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3); 10706 10707 PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense)); 10708 PetscFunctionReturn(PETSC_SUCCESS); 10709 } 10710 10711 /*@C 10712 MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which 10713 a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense 10714 in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix 10715 `Csp` from `Cden`. 10716 10717 Collective 10718 10719 Input Parameters: 10720 + matcoloring - coloring context created with `MatTransposeColoringCreate()` 10721 - Cden - matrix product of a sparse matrix and a dense matrix Btdense 10722 10723 Output Parameter: 10724 . Csp - sparse matrix 10725 10726 Level: developer 10727 10728 Note: 10729 These are used internally for some implementations of `MatRARt()` 10730 10731 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()` 10732 @*/ 10733 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp) 10734 { 10735 PetscFunctionBegin; 10736 PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10737 PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2); 10738 PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3); 10739 10740 PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp)); 10741 PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY)); 10742 PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY)); 10743 PetscFunctionReturn(PETSC_SUCCESS); 10744 } 10745 10746 /*@C 10747 MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T. 10748 10749 Collective 10750 10751 Input Parameters: 10752 + mat - the matrix product C 10753 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()` 10754 10755 Output Parameter: 10756 . color - the new coloring context 10757 10758 Level: intermediate 10759 10760 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`, 10761 `MatTransColoringApplyDenToSp()` 10762 @*/ 10763 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color) 10764 { 10765 MatTransposeColoring c; 10766 MPI_Comm comm; 10767 10768 PetscFunctionBegin; 10769 PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10770 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10771 PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL)); 10772 10773 c->ctype = iscoloring->ctype; 10774 PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c); 10775 10776 *color = c; 10777 PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10778 PetscFunctionReturn(PETSC_SUCCESS); 10779 } 10780 10781 /*@ 10782 MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the 10783 matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the 10784 same, otherwise it will be larger 10785 10786 Not Collective 10787 10788 Input Parameter: 10789 . A - the matrix 10790 10791 Output Parameter: 10792 . state - the current state 10793 10794 Level: intermediate 10795 10796 Notes: 10797 You can only compare states from two different calls to the SAME matrix, you cannot compare calls between 10798 different matrices 10799 10800 Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix 10801 10802 Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers. 10803 10804 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()` 10805 @*/ 10806 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state) 10807 { 10808 PetscFunctionBegin; 10809 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10810 *state = mat->nonzerostate; 10811 PetscFunctionReturn(PETSC_SUCCESS); 10812 } 10813 10814 /*@ 10815 MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential 10816 matrices from each processor 10817 10818 Collective 10819 10820 Input Parameters: 10821 + comm - the communicators the parallel matrix will live on 10822 . seqmat - the input sequential matrices 10823 . n - number of local columns (or `PETSC_DECIDE`) 10824 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10825 10826 Output Parameter: 10827 . mpimat - the parallel matrix generated 10828 10829 Level: developer 10830 10831 Note: 10832 The number of columns of the matrix in EACH processor MUST be the same. 10833 10834 .seealso: [](ch_matrices), `Mat` 10835 @*/ 10836 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat) 10837 { 10838 PetscMPIInt size; 10839 10840 PetscFunctionBegin; 10841 PetscCallMPI(MPI_Comm_size(comm, &size)); 10842 if (size == 1) { 10843 if (reuse == MAT_INITIAL_MATRIX) { 10844 PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat)); 10845 } else { 10846 PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN)); 10847 } 10848 PetscFunctionReturn(PETSC_SUCCESS); 10849 } 10850 10851 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"); 10852 10853 PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0)); 10854 PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat)); 10855 PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0)); 10856 PetscFunctionReturn(PETSC_SUCCESS); 10857 } 10858 10859 /*@ 10860 MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI ranks' ownership ranges. 10861 10862 Collective 10863 10864 Input Parameters: 10865 + A - the matrix to create subdomains from 10866 - N - requested number of subdomains 10867 10868 Output Parameters: 10869 + n - number of subdomains resulting on this MPI process 10870 - iss - `IS` list with indices of subdomains on this MPI process 10871 10872 Level: advanced 10873 10874 Note: 10875 The number of subdomains must be smaller than the communicator size 10876 10877 .seealso: [](ch_matrices), `Mat`, `IS` 10878 @*/ 10879 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[]) 10880 { 10881 MPI_Comm comm, subcomm; 10882 PetscMPIInt size, rank, color; 10883 PetscInt rstart, rend, k; 10884 10885 PetscFunctionBegin; 10886 PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 10887 PetscCallMPI(MPI_Comm_size(comm, &size)); 10888 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 10889 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); 10890 *n = 1; 10891 k = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */ 10892 color = rank / k; 10893 PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm)); 10894 PetscCall(PetscMalloc1(1, iss)); 10895 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 10896 PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0])); 10897 PetscCallMPI(MPI_Comm_free(&subcomm)); 10898 PetscFunctionReturn(PETSC_SUCCESS); 10899 } 10900 10901 /*@ 10902 MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection. 10903 10904 If the interpolation and restriction operators are the same, uses `MatPtAP()`. 10905 If they are not the same, uses `MatMatMatMult()`. 10906 10907 Once the coarse grid problem is constructed, correct for interpolation operators 10908 that are not of full rank, which can legitimately happen in the case of non-nested 10909 geometric multigrid. 10910 10911 Input Parameters: 10912 + restrct - restriction operator 10913 . dA - fine grid matrix 10914 . interpolate - interpolation operator 10915 . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10916 - fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate 10917 10918 Output Parameter: 10919 . A - the Galerkin coarse matrix 10920 10921 Options Database Key: 10922 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used 10923 10924 Level: developer 10925 10926 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()` 10927 @*/ 10928 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A) 10929 { 10930 IS zerorows; 10931 Vec diag; 10932 10933 PetscFunctionBegin; 10934 PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10935 /* Construct the coarse grid matrix */ 10936 if (interpolate == restrct) { 10937 PetscCall(MatPtAP(dA, interpolate, reuse, fill, A)); 10938 } else { 10939 PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A)); 10940 } 10941 10942 /* If the interpolation matrix is not of full rank, A will have zero rows. 10943 This can legitimately happen in the case of non-nested geometric multigrid. 10944 In that event, we set the rows of the matrix to the rows of the identity, 10945 ignoring the equations (as the RHS will also be zero). */ 10946 10947 PetscCall(MatFindZeroRows(*A, &zerorows)); 10948 10949 if (zerorows != NULL) { /* if there are any zero rows */ 10950 PetscCall(MatCreateVecs(*A, &diag, NULL)); 10951 PetscCall(MatGetDiagonal(*A, diag)); 10952 PetscCall(VecISSet(diag, zerorows, 1.0)); 10953 PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES)); 10954 PetscCall(VecDestroy(&diag)); 10955 PetscCall(ISDestroy(&zerorows)); 10956 } 10957 PetscFunctionReturn(PETSC_SUCCESS); 10958 } 10959 10960 /*@C 10961 MatSetOperation - Allows user to set a matrix operation for any matrix type 10962 10963 Logically Collective 10964 10965 Input Parameters: 10966 + mat - the matrix 10967 . op - the name of the operation 10968 - f - the function that provides the operation 10969 10970 Level: developer 10971 10972 Usage: 10973 .vb 10974 extern PetscErrorCode usermult(Mat, Vec, Vec); 10975 10976 PetscCall(MatCreateXXX(comm, ..., &A)); 10977 PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFunction)usermult)); 10978 .ve 10979 10980 Notes: 10981 See the file `include/petscmat.h` for a complete list of matrix 10982 operations, which all have the form MATOP_<OPERATION>, where 10983 <OPERATION> is the name (in all capital letters) of the 10984 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 10985 10986 All user-provided functions (except for `MATOP_DESTROY`) should have the same calling 10987 sequence as the usual matrix interface routines, since they 10988 are intended to be accessed via the usual matrix interface 10989 routines, e.g., 10990 .vb 10991 MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec) 10992 .ve 10993 10994 In particular each function MUST return `PETSC_SUCCESS` on success and 10995 nonzero on failure. 10996 10997 This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type. 10998 10999 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()` 11000 @*/ 11001 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void)) 11002 { 11003 PetscFunctionBegin; 11004 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11005 if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view; 11006 (((void (**)(void))mat->ops)[op]) = f; 11007 PetscFunctionReturn(PETSC_SUCCESS); 11008 } 11009 11010 /*@C 11011 MatGetOperation - Gets a matrix operation for any matrix type. 11012 11013 Not Collective 11014 11015 Input Parameters: 11016 + mat - the matrix 11017 - op - the name of the operation 11018 11019 Output Parameter: 11020 . f - the function that provides the operation 11021 11022 Level: developer 11023 11024 Usage: 11025 .vb 11026 PetscErrorCode (*usermult)(Mat, Vec, Vec); 11027 MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult); 11028 .ve 11029 11030 Notes: 11031 See the file include/petscmat.h for a complete list of matrix 11032 operations, which all have the form MATOP_<OPERATION>, where 11033 <OPERATION> is the name (in all capital letters) of the 11034 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11035 11036 This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type. 11037 11038 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()` 11039 @*/ 11040 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void)) 11041 { 11042 PetscFunctionBegin; 11043 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11044 *f = (((void (**)(void))mat->ops)[op]); 11045 PetscFunctionReturn(PETSC_SUCCESS); 11046 } 11047 11048 /*@ 11049 MatHasOperation - Determines whether the given matrix supports the particular operation. 11050 11051 Not Collective 11052 11053 Input Parameters: 11054 + mat - the matrix 11055 - op - the operation, for example, `MATOP_GET_DIAGONAL` 11056 11057 Output Parameter: 11058 . has - either `PETSC_TRUE` or `PETSC_FALSE` 11059 11060 Level: advanced 11061 11062 Note: 11063 See `MatSetOperation()` for additional discussion on naming convention and usage of `op`. 11064 11065 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()` 11066 @*/ 11067 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has) 11068 { 11069 PetscFunctionBegin; 11070 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11071 PetscValidBoolPointer(has, 3); 11072 if (mat->ops->hasoperation) { 11073 PetscUseTypeMethod(mat, hasoperation, op, has); 11074 } else { 11075 if (((void **)mat->ops)[op]) *has = PETSC_TRUE; 11076 else { 11077 *has = PETSC_FALSE; 11078 if (op == MATOP_CREATE_SUBMATRIX) { 11079 PetscMPIInt size; 11080 11081 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 11082 if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has)); 11083 } 11084 } 11085 } 11086 PetscFunctionReturn(PETSC_SUCCESS); 11087 } 11088 11089 /*@ 11090 MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent 11091 11092 Collective 11093 11094 Input Parameter: 11095 . mat - the matrix 11096 11097 Output Parameter: 11098 . cong - either `PETSC_TRUE` or `PETSC_FALSE` 11099 11100 Level: beginner 11101 11102 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout` 11103 @*/ 11104 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong) 11105 { 11106 PetscFunctionBegin; 11107 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11108 PetscValidType(mat, 1); 11109 PetscValidBoolPointer(cong, 2); 11110 if (!mat->rmap || !mat->cmap) { 11111 *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE; 11112 PetscFunctionReturn(PETSC_SUCCESS); 11113 } 11114 if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */ 11115 PetscCall(PetscLayoutSetUp(mat->rmap)); 11116 PetscCall(PetscLayoutSetUp(mat->cmap)); 11117 PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong)); 11118 if (*cong) mat->congruentlayouts = 1; 11119 else mat->congruentlayouts = 0; 11120 } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE; 11121 PetscFunctionReturn(PETSC_SUCCESS); 11122 } 11123 11124 PetscErrorCode MatSetInf(Mat A) 11125 { 11126 PetscFunctionBegin; 11127 PetscUseTypeMethod(A, setinf); 11128 PetscFunctionReturn(PETSC_SUCCESS); 11129 } 11130 11131 /*@C 11132 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 11133 and possibly removes small values from the graph structure. 11134 11135 Collective 11136 11137 Input Parameters: 11138 + A - the matrix 11139 . sym - `PETSC_TRUE` indicates that the graph should be symmetrized 11140 . scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry 11141 - filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value 11142 11143 Output Parameter: 11144 . graph - the resulting graph 11145 11146 Level: advanced 11147 11148 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG` 11149 @*/ 11150 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph) 11151 { 11152 PetscFunctionBegin; 11153 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11154 PetscValidType(A, 1); 11155 PetscValidLogicalCollectiveBool(A, scale, 3); 11156 PetscValidPointer(graph, 5); 11157 PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph); 11158 PetscFunctionReturn(PETSC_SUCCESS); 11159 } 11160 11161 /*@ 11162 MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place, 11163 meaning the same memory is used for the matrix, and no new memory is allocated. 11164 11165 Collective 11166 11167 Input Parameter: 11168 . A - the matrix 11169 11170 Level: intermediate 11171 11172 Developer Note: 11173 The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end 11174 of the arrays in the data structure are unneeded. 11175 11176 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatChop()` 11177 @*/ 11178 PetscErrorCode MatEliminateZeros(Mat A) 11179 { 11180 PetscFunctionBegin; 11181 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11182 PetscUseTypeMethod(A, eliminatezeros); 11183 PetscFunctionReturn(PETSC_SUCCESS); 11184 } 11185