1 /* 2 This is where the abstract matrix operations are defined 3 Portions of this code are under: 4 Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved. 5 */ 6 7 #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/ 8 #include <petsc/private/isimpl.h> 9 #include <petsc/private/vecimpl.h> 10 11 /* Logging support */ 12 PetscClassId MAT_CLASSID; 13 PetscClassId MAT_COLORING_CLASSID; 14 PetscClassId MAT_FDCOLORING_CLASSID; 15 PetscClassId MAT_TRANSPOSECOLORING_CLASSID; 16 17 PetscLogEvent MAT_Mult, MAT_MultAdd, MAT_MultTranspose; 18 PetscLogEvent MAT_MultTransposeAdd, MAT_Solve, MAT_Solves, MAT_SolveAdd, MAT_SolveTranspose, MAT_MatSolve, MAT_MatTrSolve; 19 PetscLogEvent MAT_SolveTransposeAdd, MAT_SOR, MAT_ForwardSolve, MAT_BackwardSolve, MAT_LUFactor, MAT_LUFactorSymbolic; 20 PetscLogEvent MAT_LUFactorNumeric, MAT_CholeskyFactor, MAT_CholeskyFactorSymbolic, MAT_CholeskyFactorNumeric, MAT_ILUFactor; 21 PetscLogEvent MAT_ILUFactorSymbolic, MAT_ICCFactorSymbolic, MAT_Copy, MAT_Convert, MAT_Scale, MAT_AssemblyBegin; 22 PetscLogEvent MAT_QRFactorNumeric, MAT_QRFactorSymbolic, MAT_QRFactor; 23 PetscLogEvent MAT_AssemblyEnd, MAT_SetValues, MAT_GetValues, MAT_GetRow, MAT_GetRowIJ, MAT_CreateSubMats, MAT_GetOrdering, MAT_RedundantMat, MAT_GetSeqNonzeroStructure; 24 PetscLogEvent MAT_IncreaseOverlap, MAT_Partitioning, MAT_PartitioningND, MAT_Coarsen, MAT_ZeroEntries, MAT_Load, MAT_View, MAT_AXPY, MAT_FDColoringCreate; 25 PetscLogEvent MAT_FDColoringSetUp, MAT_FDColoringApply, MAT_Transpose, MAT_FDColoringFunction, MAT_CreateSubMat; 26 PetscLogEvent MAT_TransposeColoringCreate; 27 PetscLogEvent MAT_MatMult, MAT_MatMultSymbolic, MAT_MatMultNumeric; 28 PetscLogEvent MAT_PtAP, MAT_PtAPSymbolic, MAT_PtAPNumeric, MAT_RARt, MAT_RARtSymbolic, MAT_RARtNumeric; 29 PetscLogEvent MAT_MatTransposeMult, MAT_MatTransposeMultSymbolic, MAT_MatTransposeMultNumeric; 30 PetscLogEvent MAT_TransposeMatMult, MAT_TransposeMatMultSymbolic, MAT_TransposeMatMultNumeric; 31 PetscLogEvent MAT_MatMatMult, MAT_MatMatMultSymbolic, MAT_MatMatMultNumeric; 32 PetscLogEvent MAT_MultHermitianTranspose, MAT_MultHermitianTransposeAdd; 33 PetscLogEvent MAT_Getsymtransreduced, MAT_GetBrowsOfAcols; 34 PetscLogEvent MAT_GetBrowsOfAocols, MAT_Getlocalmat, MAT_Getlocalmatcondensed, MAT_Seqstompi, MAT_Seqstompinum, MAT_Seqstompisym; 35 PetscLogEvent MAT_GetMultiProcBlock; 36 PetscLogEvent MAT_CUSPARSECopyToGPU, MAT_CUSPARSECopyFromGPU, MAT_CUSPARSEGenerateTranspose, MAT_CUSPARSESolveAnalysis; 37 PetscLogEvent MAT_HIPSPARSECopyToGPU, MAT_HIPSPARSECopyFromGPU, MAT_HIPSPARSEGenerateTranspose, MAT_HIPSPARSESolveAnalysis; 38 PetscLogEvent MAT_PreallCOO, MAT_SetVCOO; 39 PetscLogEvent MAT_SetValuesBatch; 40 PetscLogEvent MAT_ViennaCLCopyToGPU; 41 PetscLogEvent MAT_CUDACopyToGPU; 42 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU; 43 PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom; 44 PetscLogEvent MAT_FactorFactS, MAT_FactorInvS; 45 PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights; 46 PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR; 47 48 const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL}; 49 50 /*@ 51 MatSetRandom - Sets all components of a matrix to random numbers. 52 53 Logically Collective 54 55 Input Parameters: 56 + x - the matrix 57 - rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or `NULL` and 58 it will create one internally. 59 60 Example: 61 .vb 62 PetscRandomCreate(PETSC_COMM_WORLD,&rctx); 63 MatSetRandom(x,rctx); 64 PetscRandomDestroy(rctx); 65 .ve 66 67 Level: intermediate 68 69 Notes: 70 For sparse matrices that have been preallocated but not been assembled it randomly selects appropriate locations, 71 72 for sparse matrices that already have locations it fills the locations with random numbers. 73 74 It generates an error if used on sparse matrices that have not been preallocated. 75 76 .seealso: [](chapter_matrices), `Mat`, `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomCreate()`, `PetscRandomDestroy()` 77 @*/ 78 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx) 79 { 80 PetscRandom randObj = NULL; 81 82 PetscFunctionBegin; 83 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 84 if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2); 85 PetscValidType(x, 1); 86 MatCheckPreallocated(x, 1); 87 88 if (!rctx) { 89 MPI_Comm comm; 90 PetscCall(PetscObjectGetComm((PetscObject)x, &comm)); 91 PetscCall(PetscRandomCreate(comm, &randObj)); 92 PetscCall(PetscRandomSetType(randObj, x->defaultrandtype)); 93 PetscCall(PetscRandomSetFromOptions(randObj)); 94 rctx = randObj; 95 } 96 PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0)); 97 PetscUseTypeMethod(x, setrandom, rctx); 98 PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0)); 99 100 PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY)); 101 PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY)); 102 PetscCall(PetscRandomDestroy(&randObj)); 103 PetscFunctionReturn(PETSC_SUCCESS); 104 } 105 106 /*@ 107 MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in 108 109 Logically Collective 110 111 Input Parameter: 112 . mat - the factored matrix 113 114 Output Parameters: 115 + pivot - the pivot value computed 116 - row - the row that the zero pivot occurred. This row value must be interpreted carefully due to row reorderings and which processes 117 the share the matrix 118 119 Level: advanced 120 121 Notes: 122 This routine does not work for factorizations done with external packages. 123 124 This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT` 125 126 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 127 128 .seealso: [](chapter_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, 129 `MAT_FACTOR_NUMERIC_ZEROPIVOT` 130 @*/ 131 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row) 132 { 133 PetscFunctionBegin; 134 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 135 PetscValidRealPointer(pivot, 2); 136 PetscValidIntPointer(row, 3); 137 *pivot = mat->factorerror_zeropivot_value; 138 *row = mat->factorerror_zeropivot_row; 139 PetscFunctionReturn(PETSC_SUCCESS); 140 } 141 142 /*@ 143 MatFactorGetError - gets the error code from a factorization 144 145 Logically Collective 146 147 Input Parameter: 148 . mat - the factored matrix 149 150 Output Parameter: 151 . err - the error code 152 153 Level: advanced 154 155 Note: 156 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 157 158 .seealso: [](chapter_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, 159 `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, `MatFactorError` 160 @*/ 161 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err) 162 { 163 PetscFunctionBegin; 164 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 165 PetscValidPointer(err, 2); 166 *err = mat->factorerrortype; 167 PetscFunctionReturn(PETSC_SUCCESS); 168 } 169 170 /*@ 171 MatFactorClearError - clears the error code in a factorization 172 173 Logically Collective 174 175 Input Parameter: 176 . mat - the factored matrix 177 178 Level: developer 179 180 Note: 181 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 182 183 .seealso: [](chapter_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`, 184 `MatGetErrorCode()`, `MatFactorError` 185 @*/ 186 PetscErrorCode MatFactorClearError(Mat mat) 187 { 188 PetscFunctionBegin; 189 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 190 mat->factorerrortype = MAT_FACTOR_NOERROR; 191 mat->factorerror_zeropivot_value = 0.0; 192 mat->factorerror_zeropivot_row = 0; 193 PetscFunctionReturn(PETSC_SUCCESS); 194 } 195 196 PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero) 197 { 198 Vec r, l; 199 const PetscScalar *al; 200 PetscInt i, nz, gnz, N, n; 201 202 PetscFunctionBegin; 203 PetscCall(MatCreateVecs(mat, &r, &l)); 204 if (!cols) { /* nonzero rows */ 205 PetscCall(MatGetSize(mat, &N, NULL)); 206 PetscCall(MatGetLocalSize(mat, &n, NULL)); 207 PetscCall(VecSet(l, 0.0)); 208 PetscCall(VecSetRandom(r, NULL)); 209 PetscCall(MatMult(mat, r, l)); 210 PetscCall(VecGetArrayRead(l, &al)); 211 } else { /* nonzero columns */ 212 PetscCall(MatGetSize(mat, NULL, &N)); 213 PetscCall(MatGetLocalSize(mat, NULL, &n)); 214 PetscCall(VecSet(r, 0.0)); 215 PetscCall(VecSetRandom(l, NULL)); 216 PetscCall(MatMultTranspose(mat, l, r)); 217 PetscCall(VecGetArrayRead(r, &al)); 218 } 219 if (tol <= 0.0) { 220 for (i = 0, nz = 0; i < n; i++) 221 if (al[i] != 0.0) nz++; 222 } else { 223 for (i = 0, nz = 0; i < n; i++) 224 if (PetscAbsScalar(al[i]) > tol) nz++; 225 } 226 PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 227 if (gnz != N) { 228 PetscInt *nzr; 229 PetscCall(PetscMalloc1(nz, &nzr)); 230 if (nz) { 231 if (tol < 0) { 232 for (i = 0, nz = 0; i < n; i++) 233 if (al[i] != 0.0) nzr[nz++] = i; 234 } else { 235 for (i = 0, nz = 0; i < n; i++) 236 if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i; 237 } 238 } 239 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero)); 240 } else *nonzero = NULL; 241 if (!cols) { /* nonzero rows */ 242 PetscCall(VecRestoreArrayRead(l, &al)); 243 } else { 244 PetscCall(VecRestoreArrayRead(r, &al)); 245 } 246 PetscCall(VecDestroy(&l)); 247 PetscCall(VecDestroy(&r)); 248 PetscFunctionReturn(PETSC_SUCCESS); 249 } 250 251 /*@ 252 MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix 253 254 Input Parameter: 255 . A - the matrix 256 257 Output Parameter: 258 . keptrows - the rows that are not completely zero 259 260 Level: intermediate 261 262 Note: 263 `keptrows` is set to `NULL` if all rows are nonzero. 264 265 .seealso: [](chapter_matrices), `Mat`, `MatFindZeroRows()` 266 @*/ 267 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows) 268 { 269 PetscFunctionBegin; 270 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 271 PetscValidType(mat, 1); 272 PetscValidPointer(keptrows, 2); 273 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 274 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 275 if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows); 276 else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows)); 277 PetscFunctionReturn(PETSC_SUCCESS); 278 } 279 280 /*@ 281 MatFindZeroRows - Locate all rows that are completely zero in the matrix 282 283 Input Parameter: 284 . A - the matrix 285 286 Output Parameter: 287 . zerorows - the rows that are completely zero 288 289 Level: intermediate 290 291 Note: 292 `zerorows` is set to `NULL` if no rows are zero. 293 294 .seealso: [](chapter_matrices), `Mat`, `MatFindNonzeroRows()` 295 @*/ 296 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows) 297 { 298 IS keptrows; 299 PetscInt m, n; 300 301 PetscFunctionBegin; 302 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 303 PetscValidType(mat, 1); 304 PetscValidPointer(zerorows, 2); 305 PetscCall(MatFindNonzeroRows(mat, &keptrows)); 306 /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows. 307 In keeping with this convention, we set zerorows to NULL if there are no zero 308 rows. */ 309 if (keptrows == NULL) { 310 *zerorows = NULL; 311 } else { 312 PetscCall(MatGetOwnershipRange(mat, &m, &n)); 313 PetscCall(ISComplement(keptrows, m, n, zerorows)); 314 PetscCall(ISDestroy(&keptrows)); 315 } 316 PetscFunctionReturn(PETSC_SUCCESS); 317 } 318 319 /*@ 320 MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling 321 322 Not Collective 323 324 Input Parameter: 325 . A - the matrix 326 327 Output Parameter: 328 . a - the diagonal part (which is a SEQUENTIAL matrix) 329 330 Level: advanced 331 332 Notes: 333 See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix. 334 335 Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation. 336 337 .seealso: [](chapter_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ` 338 @*/ 339 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a) 340 { 341 PetscFunctionBegin; 342 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 343 PetscValidType(A, 1); 344 PetscValidPointer(a, 2); 345 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 346 if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a); 347 else { 348 PetscMPIInt size; 349 350 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 351 PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name); 352 *a = A; 353 } 354 PetscFunctionReturn(PETSC_SUCCESS); 355 } 356 357 /*@ 358 MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries. 359 360 Collective 361 362 Input Parameter: 363 . mat - the matrix 364 365 Output Parameter: 366 . trace - the sum of the diagonal entries 367 368 Level: advanced 369 370 .seealso: [](chapter_matrices), `Mat` 371 @*/ 372 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace) 373 { 374 Vec diag; 375 376 PetscFunctionBegin; 377 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 378 PetscValidScalarPointer(trace, 2); 379 PetscCall(MatCreateVecs(mat, &diag, NULL)); 380 PetscCall(MatGetDiagonal(mat, diag)); 381 PetscCall(VecSum(diag, trace)); 382 PetscCall(VecDestroy(&diag)); 383 PetscFunctionReturn(PETSC_SUCCESS); 384 } 385 386 /*@ 387 MatRealPart - Zeros out the imaginary part of the matrix 388 389 Logically Collective 390 391 Input Parameter: 392 . mat - the matrix 393 394 Level: advanced 395 396 .seealso: [](chapter_matrices), `Mat`, `MatImaginaryPart()` 397 @*/ 398 PetscErrorCode MatRealPart(Mat mat) 399 { 400 PetscFunctionBegin; 401 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 402 PetscValidType(mat, 1); 403 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 404 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 405 MatCheckPreallocated(mat, 1); 406 PetscUseTypeMethod(mat, realpart); 407 PetscFunctionReturn(PETSC_SUCCESS); 408 } 409 410 /*@C 411 MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix 412 413 Collective 414 415 Input Parameter: 416 . mat - the matrix 417 418 Output Parameters: 419 + nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each block) 420 - ghosts - the global indices of the ghost points 421 422 Level: advanced 423 424 Note: 425 `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()` 426 427 .seealso: [](chapter_matrices), `Mat`, `VecCreateGhost()` 428 @*/ 429 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[]) 430 { 431 PetscFunctionBegin; 432 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 433 PetscValidType(mat, 1); 434 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 435 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 436 if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts); 437 else { 438 if (nghosts) *nghosts = 0; 439 if (ghosts) *ghosts = NULL; 440 } 441 PetscFunctionReturn(PETSC_SUCCESS); 442 } 443 444 /*@ 445 MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part 446 447 Logically Collective 448 449 Input Parameter: 450 . mat - the matrix 451 452 Level: advanced 453 454 .seealso: [](chapter_matrices), `Mat`, `MatRealPart()` 455 @*/ 456 PetscErrorCode MatImaginaryPart(Mat mat) 457 { 458 PetscFunctionBegin; 459 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 460 PetscValidType(mat, 1); 461 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 462 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 463 MatCheckPreallocated(mat, 1); 464 PetscUseTypeMethod(mat, imaginarypart); 465 PetscFunctionReturn(PETSC_SUCCESS); 466 } 467 468 /*@ 469 MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices) 470 471 Not Collective 472 473 Input Parameter: 474 . mat - the matrix 475 476 Output Parameters: 477 + missing - is any diagonal missing 478 - dd - first diagonal entry that is missing (optional) on this process 479 480 Level: advanced 481 482 .seealso: [](chapter_matrices), `Mat` 483 @*/ 484 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd) 485 { 486 PetscFunctionBegin; 487 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 488 PetscValidType(mat, 1); 489 PetscValidBoolPointer(missing, 2); 490 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name); 491 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 492 PetscUseTypeMethod(mat, missingdiagonal, missing, dd); 493 PetscFunctionReturn(PETSC_SUCCESS); 494 } 495 496 /*@C 497 MatGetRow - Gets a row of a matrix. You MUST call `MatRestoreRow()` 498 for each row that you get to ensure that your application does 499 not bleed memory. 500 501 Not Collective 502 503 Input Parameters: 504 + mat - the matrix 505 - row - the row to get 506 507 Output Parameters: 508 + ncols - if not `NULL`, the number of nonzeros in the row 509 . cols - if not `NULL`, the column numbers 510 - vals - if not `NULL`, the values 511 512 Level: advanced 513 514 Notes: 515 This routine is provided for people who need to have direct access 516 to the structure of a matrix. We hope that we provide enough 517 high-level matrix routines that few users will need it. 518 519 `MatGetRow()` always returns 0-based column indices, regardless of 520 whether the internal representation is 0-based (default) or 1-based. 521 522 For better efficiency, set cols and/or vals to `NULL` if you do 523 not wish to extract these quantities. 524 525 The user can only examine the values extracted with `MatGetRow()`; 526 the values cannot be altered. To change the matrix entries, one 527 must use `MatSetValues()`. 528 529 You can only have one call to `MatGetRow()` outstanding for a particular 530 matrix at a time, per processor. `MatGetRow()` can only obtain rows 531 associated with the given processor, it cannot get rows from the 532 other processors; for that we suggest using `MatCreateSubMatrices()`, then 533 MatGetRow() on the submatrix. The row index passed to `MatGetRow()` 534 is in the global number of rows. 535 536 Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix. 537 538 Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly. 539 540 Fortran Note: 541 The calling sequence is 542 .vb 543 MatGetRow(matrix,row,ncols,cols,values,ierr) 544 Mat matrix (input) 545 integer row (input) 546 integer ncols (output) 547 integer cols(maxcols) (output) 548 double precision (or double complex) values(maxcols) output 549 .ve 550 where maxcols >= maximum nonzeros in any row of the matrix. 551 552 Caution: 553 Do not try to change the contents of the output arrays (`cols` and `vals`). 554 In some cases, this may corrupt the matrix. 555 556 .seealso: [](chapter_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()` 557 @*/ 558 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 559 { 560 PetscInt incols; 561 562 PetscFunctionBegin; 563 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 564 PetscValidType(mat, 1); 565 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 566 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 567 MatCheckPreallocated(mat, 1); 568 PetscCheck(row >= mat->rmap->rstart && row < mat->rmap->rend, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Only for local rows, %" PetscInt_FMT " not in [%" PetscInt_FMT ",%" PetscInt_FMT ")", row, mat->rmap->rstart, mat->rmap->rend); 569 PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0)); 570 PetscUseTypeMethod(mat, getrow, row, &incols, (PetscInt **)cols, (PetscScalar **)vals); 571 if (ncols) *ncols = incols; 572 PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0)); 573 PetscFunctionReturn(PETSC_SUCCESS); 574 } 575 576 /*@ 577 MatConjugate - replaces the matrix values with their complex conjugates 578 579 Logically Collective 580 581 Input Parameter: 582 . mat - the matrix 583 584 Level: advanced 585 586 .seealso: [](chapter_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()` 587 @*/ 588 PetscErrorCode MatConjugate(Mat mat) 589 { 590 PetscFunctionBegin; 591 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 592 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 593 if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) { 594 PetscUseTypeMethod(mat, conjugate); 595 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 596 } 597 PetscFunctionReturn(PETSC_SUCCESS); 598 } 599 600 /*@C 601 MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`. 602 603 Not Collective 604 605 Input Parameters: 606 + mat - the matrix 607 . row - the row to get 608 . ncols - the number of nonzeros 609 . cols - the columns of the nonzeros 610 - vals - if nonzero the column values 611 612 Level: advanced 613 614 Notes: 615 This routine should be called after you have finished examining the entries. 616 617 This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental 618 us of the array after it has been restored. If you pass `NULL`, it will 619 not zero the pointers. Use of `cols` or `vals` after `MatRestoreRow()` is invalid. 620 621 Fortran Notes: 622 The calling sequence is 623 .vb 624 MatRestoreRow(matrix,row,ncols,cols,values,ierr) 625 Mat matrix (input) 626 integer row (input) 627 integer ncols (output) 628 integer cols(maxcols) (output) 629 double precision (or double complex) values(maxcols) output 630 .ve 631 Where maxcols >= maximum nonzeros in any row of the matrix. 632 633 In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()` 634 before another call to `MatGetRow()` can be made. 635 636 .seealso: [](chapter_matrices), `Mat`, `MatGetRow()` 637 @*/ 638 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 639 { 640 PetscFunctionBegin; 641 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 642 if (ncols) PetscValidIntPointer(ncols, 3); 643 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 644 if (!mat->ops->restorerow) PetscFunctionReturn(PETSC_SUCCESS); 645 PetscUseTypeMethod(mat, restorerow, row, ncols, (PetscInt **)cols, (PetscScalar **)vals); 646 if (ncols) *ncols = 0; 647 if (cols) *cols = NULL; 648 if (vals) *vals = NULL; 649 PetscFunctionReturn(PETSC_SUCCESS); 650 } 651 652 /*@ 653 MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 654 You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag. 655 656 Not Collective 657 658 Input Parameter: 659 . mat - the matrix 660 661 Level: advanced 662 663 Note: 664 The flag is to ensure that users are aware that `MatGetRow()` only provides the upper triangular part of the row for the matrices in `MATSBAIJ` format. 665 666 .seealso: [](chapter_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()` 667 @*/ 668 PetscErrorCode MatGetRowUpperTriangular(Mat mat) 669 { 670 PetscFunctionBegin; 671 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 672 PetscValidType(mat, 1); 673 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 674 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 675 MatCheckPreallocated(mat, 1); 676 if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS); 677 PetscUseTypeMethod(mat, getrowuppertriangular); 678 PetscFunctionReturn(PETSC_SUCCESS); 679 } 680 681 /*@ 682 MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 683 684 Not Collective 685 686 Input Parameter: 687 . mat - the matrix 688 689 Level: advanced 690 691 Note: 692 This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`. 693 694 .seealso: [](chapter_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()` 695 @*/ 696 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat) 697 { 698 PetscFunctionBegin; 699 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 700 PetscValidType(mat, 1); 701 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 702 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 703 MatCheckPreallocated(mat, 1); 704 if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS); 705 PetscUseTypeMethod(mat, restorerowuppertriangular); 706 PetscFunctionReturn(PETSC_SUCCESS); 707 } 708 709 /*@C 710 MatSetOptionsPrefix - Sets the prefix used for searching for all 711 `Mat` options in the database. 712 713 Logically Collective 714 715 Input Parameters: 716 + A - the matrix 717 - prefix - the prefix to prepend to all option names 718 719 Level: advanced 720 721 Notes: 722 A hyphen (-) must NOT be given at the beginning of the prefix name. 723 The first character of all runtime options is AUTOMATICALLY the hyphen. 724 725 This is NOT used for options for the factorization of the matrix. Normally the 726 prefix is automatically passed in from the PC calling the factorization. To set 727 it directly use `MatSetOptionsPrefixFactor()` 728 729 .seealso: [](chapter_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()` 730 @*/ 731 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[]) 732 { 733 PetscFunctionBegin; 734 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 735 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix)); 736 PetscFunctionReturn(PETSC_SUCCESS); 737 } 738 739 /*@C 740 MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for 741 for matrices created with `MatGetFactor()` 742 743 Logically Collective 744 745 Input Parameters: 746 + A - the matrix 747 - prefix - the prefix to prepend to all option names for the factored matrix 748 749 Level: developer 750 751 Notes: 752 A hyphen (-) must NOT be given at the beginning of the prefix name. 753 The first character of all runtime options is AUTOMATICALLY the hyphen. 754 755 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 756 it directly when not using `KSP`/`PC` use `MatSetOptionsPrefixFactor()` 757 758 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()` 759 @*/ 760 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[]) 761 { 762 PetscFunctionBegin; 763 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 764 if (prefix) { 765 PetscValidCharPointer(prefix, 2); 766 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 767 if (prefix != A->factorprefix) { 768 PetscCall(PetscFree(A->factorprefix)); 769 PetscCall(PetscStrallocpy(prefix, &A->factorprefix)); 770 } 771 } else PetscCall(PetscFree(A->factorprefix)); 772 PetscFunctionReturn(PETSC_SUCCESS); 773 } 774 775 /*@C 776 MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for 777 for matrices created with `MatGetFactor()` 778 779 Logically Collective 780 781 Input Parameters: 782 + A - the matrix 783 - prefix - the prefix to prepend to all option names for the factored matrix 784 785 Level: developer 786 787 Notes: 788 A hyphen (-) must NOT be given at the beginning of the prefix name. 789 The first character of all runtime options is AUTOMATICALLY the hyphen. 790 791 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 792 it directly when not using `KSP`/`PC` use `MatAppendOptionsPrefixFactor()` 793 794 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`, 795 `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`, 796 `MatSetOptionsPrefix()` 797 @*/ 798 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[]) 799 { 800 size_t len1, len2, new_len; 801 802 PetscFunctionBegin; 803 PetscValidHeader(A, 1); 804 if (!prefix) PetscFunctionReturn(PETSC_SUCCESS); 805 if (!A->factorprefix) { 806 PetscCall(MatSetOptionsPrefixFactor(A, prefix)); 807 PetscFunctionReturn(PETSC_SUCCESS); 808 } 809 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 810 811 PetscCall(PetscStrlen(A->factorprefix, &len1)); 812 PetscCall(PetscStrlen(prefix, &len2)); 813 new_len = len1 + len2 + 1; 814 PetscCall(PetscRealloc(new_len * sizeof(*(A->factorprefix)), &A->factorprefix)); 815 PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1)); 816 PetscFunctionReturn(PETSC_SUCCESS); 817 } 818 819 /*@C 820 MatAppendOptionsPrefix - Appends to the prefix used for searching for all 821 matrix options in the database. 822 823 Logically Collective 824 825 Input Parameters: 826 + A - the matrix 827 - prefix - the prefix to prepend to all option names 828 829 Level: advanced 830 831 Note: 832 A hyphen (-) must NOT be given at the beginning of the prefix name. 833 The first character of all runtime options is AUTOMATICALLY the hyphen. 834 835 .seealso: [](chapter_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()` 836 @*/ 837 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[]) 838 { 839 PetscFunctionBegin; 840 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 841 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix)); 842 PetscFunctionReturn(PETSC_SUCCESS); 843 } 844 845 /*@C 846 MatGetOptionsPrefix - Gets the prefix used for searching for all 847 matrix options in the database. 848 849 Not Collective 850 851 Input Parameter: 852 . A - the matrix 853 854 Output Parameter: 855 . prefix - pointer to the prefix string used 856 857 Level: advanced 858 859 Fortran Note: 860 The user should pass in a string `prefix` of 861 sufficient length to hold the prefix. 862 863 .seealso: [](chapter_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()` 864 @*/ 865 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[]) 866 { 867 PetscFunctionBegin; 868 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 869 PetscValidPointer(prefix, 2); 870 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix)); 871 PetscFunctionReturn(PETSC_SUCCESS); 872 } 873 874 /*@ 875 MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by users. 876 877 Collective 878 879 Input Parameter: 880 . A - the matrix 881 882 Level: beginner 883 884 Notes: 885 The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`. 886 887 Users can reset the preallocation to access the original memory. 888 889 Currently only supported for `MATAIJ` matrices. 890 891 .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()` 892 @*/ 893 PetscErrorCode MatResetPreallocation(Mat A) 894 { 895 PetscFunctionBegin; 896 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 897 PetscValidType(A, 1); 898 PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A)); 899 PetscFunctionReturn(PETSC_SUCCESS); 900 } 901 902 /*@ 903 MatSetUp - Sets up the internal matrix data structures for later use. 904 905 Collective 906 907 Input Parameter: 908 . A - the matrix 909 910 Level: intermediate 911 912 Notes: 913 If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of 914 setting values in the matrix. 915 916 If a suitable preallocation routine is used, this function does not need to be called. 917 918 This routine is called internally by other matrix functions when needed so rarely needs to be called by users 919 920 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()` 921 @*/ 922 PetscErrorCode MatSetUp(Mat A) 923 { 924 PetscFunctionBegin; 925 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 926 if (!((PetscObject)A)->type_name) { 927 PetscMPIInt size; 928 929 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 930 PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ)); 931 } 932 if (!A->preallocated) PetscTryTypeMethod(A, setup); 933 PetscCall(PetscLayoutSetUp(A->rmap)); 934 PetscCall(PetscLayoutSetUp(A->cmap)); 935 A->preallocated = PETSC_TRUE; 936 PetscFunctionReturn(PETSC_SUCCESS); 937 } 938 939 #if defined(PETSC_HAVE_SAWS) 940 #include <petscviewersaws.h> 941 #endif 942 943 /*@C 944 MatViewFromOptions - View properties of the matrix based on options set in the options database 945 946 Collective 947 948 Input Parameters: 949 + A - the matrix 950 . obj - optional additional object that provides the options prefix to use 951 - name - command line option 952 953 Options Database Key: 954 . -mat_view [viewertype]:... - the viewer and its options 955 956 Level: intermediate 957 958 Notes: 959 .vb 960 If no value is provided ascii:stdout is used 961 ascii[:[filename][:[format][:append]]] defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab, 962 for example ascii::ascii_info prints just the information about the object not all details 963 unless :append is given filename opens in write mode, overwriting what was already there 964 binary[:[filename][:[format][:append]]] defaults to the file binaryoutput 965 draw[:drawtype[:filename]] for example, draw:tikz, draw:tikz:figure.tex or draw:x 966 socket[:port] defaults to the standard output port 967 saws[:communicatorname] publishes object to the Scientific Application Webserver (SAWs) 968 .ve 969 970 .seealso: [](chapter_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()` 971 @*/ 972 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[]) 973 { 974 PetscFunctionBegin; 975 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 976 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 977 PetscFunctionReturn(PETSC_SUCCESS); 978 } 979 980 /*@C 981 MatView - display information about a matrix in a variety ways 982 983 Collective 984 985 Input Parameters: 986 + mat - the matrix 987 - viewer - visualization context 988 989 Options Database Keys: 990 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 991 . -mat_view ::ascii_info_detail - Prints more detailed info 992 . -mat_view - Prints matrix in ASCII format 993 . -mat_view ::ascii_matlab - Prints matrix in Matlab format 994 . -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 995 . -display <name> - Sets display name (default is host) 996 . -draw_pause <sec> - Sets number of seconds to pause after display 997 . -mat_view socket - Sends matrix to socket, can be accessed from Matlab (see Users-Manual: ch_matlab for details) 998 . -viewer_socket_machine <machine> - 999 . -viewer_socket_port <port> - 1000 . -mat_view binary - save matrix to file in binary format 1001 - -viewer_binary_filename <name> - 1002 1003 Level: beginner 1004 1005 Notes: 1006 The available visualization contexts include 1007 + `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices 1008 . `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD` 1009 . `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm 1010 - `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure 1011 1012 The user can open alternative visualization contexts with 1013 + `PetscViewerASCIIOpen()` - Outputs matrix to a specified file 1014 . `PetscViewerBinaryOpen()` - Outputs matrix in binary to a 1015 specified file; corresponding input uses MatLoad() 1016 . `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to 1017 an X window display 1018 - `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer. 1019 Currently only the sequential dense and AIJ 1020 matrix types support the Socket viewer. 1021 1022 The user can call `PetscViewerPushFormat()` to specify the output 1023 format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`, 1024 `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`). Available formats include 1025 + `PETSC_VIEWER_DEFAULT` - default, prints matrix contents 1026 . `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in Matlab format 1027 . `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros 1028 . `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse 1029 format common among all matrix types 1030 . `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific 1031 format (which is in many cases the same as the default) 1032 . `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix 1033 size and structure (not the matrix entries) 1034 - `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about 1035 the matrix structure 1036 1037 The ASCII viewers are only recommended for small matrices on at most a moderate number of processes, 1038 the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format. 1039 1040 In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer). 1041 1042 See the manual page for `MatLoad()` for the exact format of the binary file when the binary 1043 viewer is used. 1044 1045 See share/petsc/matlab/PetscBinaryRead.m for a Matlab code that can read in the binary file when the binary 1046 viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python. 1047 1048 One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure, 1049 and then use the following mouse functions. 1050 .vb 1051 left mouse: zoom in 1052 middle mouse: zoom out 1053 right mouse: continue with the simulation 1054 .ve 1055 1056 .seealso: [](chapter_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`, 1057 `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()` 1058 @*/ 1059 PetscErrorCode MatView(Mat mat, PetscViewer viewer) 1060 { 1061 PetscInt rows, cols, rbs, cbs; 1062 PetscBool isascii, isstring, issaws; 1063 PetscViewerFormat format; 1064 PetscMPIInt size; 1065 1066 PetscFunctionBegin; 1067 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1068 PetscValidType(mat, 1); 1069 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer)); 1070 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1071 PetscCheckSameComm(mat, 1, viewer, 2); 1072 1073 PetscCall(PetscViewerGetFormat(viewer, &format)); 1074 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 1075 if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS); 1076 1077 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 1078 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 1079 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws)); 1080 PetscCheck((isascii && (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL)) || !mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "No viewers for factored matrix except ASCII, info, or info_detail"); 1081 1082 PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0)); 1083 if (isascii) { 1084 if (!mat->preallocated) { 1085 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n")); 1086 PetscFunctionReturn(PETSC_SUCCESS); 1087 } 1088 if (!mat->assembled) { 1089 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n")); 1090 PetscFunctionReturn(PETSC_SUCCESS); 1091 } 1092 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer)); 1093 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1094 MatNullSpace nullsp, transnullsp; 1095 1096 PetscCall(PetscViewerASCIIPushTab(viewer)); 1097 PetscCall(MatGetSize(mat, &rows, &cols)); 1098 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1099 if (rbs != 1 || cbs != 1) { 1100 if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs)); 1101 else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs)); 1102 } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols)); 1103 if (mat->factortype) { 1104 MatSolverType solver; 1105 PetscCall(MatFactorGetSolverType(mat, &solver)); 1106 PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver)); 1107 } 1108 if (mat->ops->getinfo) { 1109 MatInfo info; 1110 PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info)); 1111 PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated)); 1112 if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs)); 1113 } 1114 PetscCall(MatGetNullSpace(mat, &nullsp)); 1115 PetscCall(MatGetTransposeNullSpace(mat, &transnullsp)); 1116 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached null space\n")); 1117 if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached transposed null space\n")); 1118 PetscCall(MatGetNearNullSpace(mat, &nullsp)); 1119 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached near null space\n")); 1120 PetscCall(PetscViewerASCIIPushTab(viewer)); 1121 PetscCall(MatProductView(mat, viewer)); 1122 PetscCall(PetscViewerASCIIPopTab(viewer)); 1123 } 1124 } else if (issaws) { 1125 #if defined(PETSC_HAVE_SAWS) 1126 PetscMPIInt rank; 1127 1128 PetscCall(PetscObjectName((PetscObject)mat)); 1129 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 1130 if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer)); 1131 #endif 1132 } else if (isstring) { 1133 const char *type; 1134 PetscCall(MatGetType(mat, &type)); 1135 PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type)); 1136 PetscTryTypeMethod(mat, view, viewer); 1137 } 1138 if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) { 1139 PetscCall(PetscViewerASCIIPushTab(viewer)); 1140 PetscUseTypeMethod(mat, viewnative, viewer); 1141 PetscCall(PetscViewerASCIIPopTab(viewer)); 1142 } else if (mat->ops->view) { 1143 PetscCall(PetscViewerASCIIPushTab(viewer)); 1144 PetscUseTypeMethod(mat, view, viewer); 1145 PetscCall(PetscViewerASCIIPopTab(viewer)); 1146 } 1147 if (isascii) { 1148 PetscCall(PetscViewerGetFormat(viewer, &format)); 1149 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer)); 1150 } 1151 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1152 PetscFunctionReturn(PETSC_SUCCESS); 1153 } 1154 1155 #if defined(PETSC_USE_DEBUG) 1156 #include <../src/sys/totalview/tv_data_display.h> 1157 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat) 1158 { 1159 TV_add_row("Local rows", "int", &mat->rmap->n); 1160 TV_add_row("Local columns", "int", &mat->cmap->n); 1161 TV_add_row("Global rows", "int", &mat->rmap->N); 1162 TV_add_row("Global columns", "int", &mat->cmap->N); 1163 TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name); 1164 return TV_format_OK; 1165 } 1166 #endif 1167 1168 /*@C 1169 MatLoad - Loads a matrix that has been stored in binary/HDF5 format 1170 with `MatView()`. The matrix format is determined from the options database. 1171 Generates a parallel MPI matrix if the communicator has more than one 1172 processor. The default matrix type is `MATAIJ`. 1173 1174 Collective 1175 1176 Input Parameters: 1177 + mat - the newly loaded matrix, this needs to have been created with `MatCreate()` 1178 or some related function before a call to `MatLoad()` 1179 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer 1180 1181 Options Database Keys: 1182 Used with block matrix formats (`MATSEQBAIJ`, ...) to specify 1183 block size 1184 . -matload_block_size <bs> - set block size 1185 1186 Level: beginner 1187 1188 Notes: 1189 If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the 1190 `Mat` before calling this routine if you wish to set it from the options database. 1191 1192 `MatLoad()` automatically loads into the options database any options 1193 given in the file filename.info where filename is the name of the file 1194 that was passed to the `PetscViewerBinaryOpen()`. The options in the info 1195 file will be ignored if you use the -viewer_binary_skip_info option. 1196 1197 If the type or size of mat is not set before a call to `MatLoad()`, PETSc 1198 sets the default matrix type AIJ and sets the local and global sizes. 1199 If type and/or size is already set, then the same are used. 1200 1201 In parallel, each processor can load a subset of rows (or the 1202 entire matrix). This routine is especially useful when a large 1203 matrix is stored on disk and only part of it is desired on each 1204 processor. For example, a parallel solver may access only some of 1205 the rows from each processor. The algorithm used here reads 1206 relatively small blocks of data rather than reading the entire 1207 matrix and then subsetting it. 1208 1209 Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`. 1210 Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`, 1211 or the sequence like 1212 .vb 1213 `PetscViewer` v; 1214 `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v); 1215 `PetscViewerSetType`(v,`PETSCVIEWERBINARY`); 1216 `PetscViewerSetFromOptions`(v); 1217 `PetscViewerFileSetMode`(v,`FILE_MODE_READ`); 1218 `PetscViewerFileSetName`(v,"datafile"); 1219 .ve 1220 The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option 1221 $ -viewer_type {binary,hdf5} 1222 1223 See the example src/ksp/ksp/tutorials/ex27.c with the first approach, 1224 and src/mat/tutorials/ex10.c with the second approach. 1225 1226 In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks 1227 is read onto rank 0 and then shipped to its destination rank, one after another. 1228 Multiple objects, both matrices and vectors, can be stored within the same file. 1229 Their PetscObject name is ignored; they are loaded in the order of their storage. 1230 1231 Most users should not need to know the details of the binary storage 1232 format, since `MatLoad()` and `MatView()` completely hide these details. 1233 But for anyone who's interested, the standard binary matrix storage 1234 format is 1235 1236 .vb 1237 PetscInt MAT_FILE_CLASSID 1238 PetscInt number of rows 1239 PetscInt number of columns 1240 PetscInt total number of nonzeros 1241 PetscInt *number nonzeros in each row 1242 PetscInt *column indices of all nonzeros (starting index is zero) 1243 PetscScalar *values of all nonzeros 1244 .ve 1245 1246 PETSc automatically does the byte swapping for 1247 machines that store the bytes reversed. Thus if you write your own binary 1248 read/write routines you have to swap the bytes; see `PetscBinaryRead()` 1249 and `PetscBinaryWrite()` to see how this may be done. 1250 1251 In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used. 1252 Each processor's chunk is loaded independently by its owning rank. 1253 Multiple objects, both matrices and vectors, can be stored within the same file. 1254 They are looked up by their PetscObject name. 1255 1256 As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use 1257 by default the same structure and naming of the AIJ arrays and column count 1258 within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g. 1259 $ save example.mat A b -v7.3 1260 can be directly read by this routine (see Reference 1 for details). 1261 1262 Depending on your MATLAB version, this format might be a default, 1263 otherwise you can set it as default in Preferences. 1264 1265 Unless -nocompression flag is used to save the file in MATLAB, 1266 PETSc must be configured with ZLIB package. 1267 1268 See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c 1269 1270 This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5` 1271 1272 Corresponding `MatView()` is not yet implemented. 1273 1274 The loaded matrix is actually a transpose of the original one in MATLAB, 1275 unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above). 1276 With this format, matrix is automatically transposed by PETSc, 1277 unless the matrix is marked as SPD or symmetric 1278 (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`). 1279 1280 References: 1281 . * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version 1282 1283 .seealso: [](chapter_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()` 1284 @*/ 1285 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer) 1286 { 1287 PetscBool flg; 1288 1289 PetscFunctionBegin; 1290 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1291 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1292 1293 if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ)); 1294 1295 flg = PETSC_FALSE; 1296 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL)); 1297 if (flg) { 1298 PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE)); 1299 PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE)); 1300 } 1301 flg = PETSC_FALSE; 1302 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL)); 1303 if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE)); 1304 1305 PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0)); 1306 PetscUseTypeMethod(mat, load, viewer); 1307 PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0)); 1308 PetscFunctionReturn(PETSC_SUCCESS); 1309 } 1310 1311 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant) 1312 { 1313 Mat_Redundant *redund = *redundant; 1314 1315 PetscFunctionBegin; 1316 if (redund) { 1317 if (redund->matseq) { /* via MatCreateSubMatrices() */ 1318 PetscCall(ISDestroy(&redund->isrow)); 1319 PetscCall(ISDestroy(&redund->iscol)); 1320 PetscCall(MatDestroySubMatrices(1, &redund->matseq)); 1321 } else { 1322 PetscCall(PetscFree2(redund->send_rank, redund->recv_rank)); 1323 PetscCall(PetscFree(redund->sbuf_j)); 1324 PetscCall(PetscFree(redund->sbuf_a)); 1325 for (PetscInt i = 0; i < redund->nrecvs; i++) { 1326 PetscCall(PetscFree(redund->rbuf_j[i])); 1327 PetscCall(PetscFree(redund->rbuf_a[i])); 1328 } 1329 PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a)); 1330 } 1331 1332 if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm)); 1333 PetscCall(PetscFree(redund)); 1334 } 1335 PetscFunctionReturn(PETSC_SUCCESS); 1336 } 1337 1338 /*@C 1339 MatDestroy - Frees space taken by a matrix. 1340 1341 Collective 1342 1343 Input Parameter: 1344 . A - the matrix 1345 1346 Level: beginner 1347 1348 Developer Note: 1349 Some special arrays of matrices are not destroyed in this routine but instead by the routines called by 1350 `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines. 1351 `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes 1352 if changes are needed here. 1353 1354 .seealso: [](chapter_matrices), `Mat`, `MatCreate()` 1355 @*/ 1356 PetscErrorCode MatDestroy(Mat *A) 1357 { 1358 PetscFunctionBegin; 1359 if (!*A) PetscFunctionReturn(PETSC_SUCCESS); 1360 PetscValidHeaderSpecific(*A, MAT_CLASSID, 1); 1361 if (--((PetscObject)(*A))->refct > 0) { 1362 *A = NULL; 1363 PetscFunctionReturn(PETSC_SUCCESS); 1364 } 1365 1366 /* if memory was published with SAWs then destroy it */ 1367 PetscCall(PetscObjectSAWsViewOff((PetscObject)*A)); 1368 PetscTryTypeMethod((*A), destroy); 1369 1370 PetscCall(PetscFree((*A)->factorprefix)); 1371 PetscCall(PetscFree((*A)->defaultvectype)); 1372 PetscCall(PetscFree((*A)->defaultrandtype)); 1373 PetscCall(PetscFree((*A)->bsizes)); 1374 PetscCall(PetscFree((*A)->solvertype)); 1375 for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i])); 1376 if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL; 1377 PetscCall(MatDestroy_Redundant(&(*A)->redundant)); 1378 PetscCall(MatProductClear(*A)); 1379 PetscCall(MatNullSpaceDestroy(&(*A)->nullsp)); 1380 PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp)); 1381 PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp)); 1382 PetscCall(MatDestroy(&(*A)->schur)); 1383 PetscCall(PetscLayoutDestroy(&(*A)->rmap)); 1384 PetscCall(PetscLayoutDestroy(&(*A)->cmap)); 1385 PetscCall(PetscHeaderDestroy(A)); 1386 PetscFunctionReturn(PETSC_SUCCESS); 1387 } 1388 1389 /*@C 1390 MatSetValues - Inserts or adds a block of values into a matrix. 1391 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1392 MUST be called after all calls to `MatSetValues()` have been completed. 1393 1394 Not Collective 1395 1396 Input Parameters: 1397 + mat - the matrix 1398 . v - a logically two-dimensional array of values 1399 . m - the number of rows 1400 . idxm - the global indices of the rows 1401 . n - the number of columns 1402 . idxn - the global indices of the columns 1403 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1404 1405 Level: beginner 1406 1407 Notes: 1408 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1409 1410 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1411 options cannot be mixed without intervening calls to the assembly 1412 routines. 1413 1414 `MatSetValues()` uses 0-based row and column numbers in Fortran 1415 as well as in C. 1416 1417 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1418 simply ignored. This allows easily inserting element stiffness matrices 1419 with homogeneous Dirchlet boundary conditions that you don't want represented 1420 in the matrix. 1421 1422 Efficiency Alert: 1423 The routine `MatSetValuesBlocked()` may offer much better efficiency 1424 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1425 1426 Developer Note: 1427 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1428 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1429 1430 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1431 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1432 @*/ 1433 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1434 { 1435 PetscFunctionBeginHot; 1436 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1437 PetscValidType(mat, 1); 1438 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1439 PetscValidIntPointer(idxm, 3); 1440 PetscValidIntPointer(idxn, 5); 1441 MatCheckPreallocated(mat, 1); 1442 1443 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1444 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1445 1446 if (PetscDefined(USE_DEBUG)) { 1447 PetscInt i, j; 1448 1449 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1450 for (i = 0; i < m; i++) { 1451 for (j = 0; j < n; j++) { 1452 if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j])) 1453 #if defined(PETSC_USE_COMPLEX) 1454 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Inserting %g+i%g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")", (double)PetscRealPart(v[i * n + j]), (double)PetscImaginaryPart(v[i * n + j]), idxm[i], idxn[j]); 1455 #else 1456 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Inserting %g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")", (double)v[i * n + j], idxm[i], idxn[j]); 1457 #endif 1458 } 1459 } 1460 for (i = 0; i < m; i++) PetscCheck(idxm[i] < mat->rmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot insert in row %" PetscInt_FMT ", maximum is %" PetscInt_FMT, idxm[i], mat->rmap->N - 1); 1461 for (i = 0; i < n; i++) PetscCheck(idxn[i] < mat->cmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot insert in column %" PetscInt_FMT ", maximum is %" PetscInt_FMT, idxn[i], mat->cmap->N - 1); 1462 } 1463 1464 if (mat->assembled) { 1465 mat->was_assembled = PETSC_TRUE; 1466 mat->assembled = PETSC_FALSE; 1467 } 1468 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1469 PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv); 1470 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1471 PetscFunctionReturn(PETSC_SUCCESS); 1472 } 1473 1474 /*@C 1475 MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns 1476 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1477 MUST be called after all calls to `MatSetValues()` have been completed. 1478 1479 Not Collective 1480 1481 Input Parameters: 1482 + mat - the matrix 1483 . v - a logically two-dimensional array of values 1484 . ism - the rows to provide 1485 . isn - the columns to provide 1486 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1487 1488 Level: beginner 1489 1490 Notes: 1491 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1492 1493 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1494 options cannot be mixed without intervening calls to the assembly 1495 routines. 1496 1497 `MatSetValues()` uses 0-based row and column numbers in Fortran 1498 as well as in C. 1499 1500 Negative indices may be passed in `ism` and `isn`, these rows and columns are 1501 simply ignored. This allows easily inserting element stiffness matrices 1502 with homogeneous Dirchlet boundary conditions that you don't want represented 1503 in the matrix. 1504 1505 Efficiency Alert: 1506 The routine `MatSetValuesBlocked()` may offer much better efficiency 1507 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1508 1509 This is currently not optimized for any particular `ISType` 1510 1511 Developer Notes: 1512 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1513 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1514 1515 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1516 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()` 1517 @*/ 1518 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv) 1519 { 1520 PetscInt m, n; 1521 const PetscInt *rows, *cols; 1522 1523 PetscFunctionBeginHot; 1524 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1525 PetscCall(ISGetIndices(ism, &rows)); 1526 PetscCall(ISGetIndices(isn, &cols)); 1527 PetscCall(ISGetLocalSize(ism, &m)); 1528 PetscCall(ISGetLocalSize(isn, &n)); 1529 PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv)); 1530 PetscCall(ISRestoreIndices(ism, &rows)); 1531 PetscCall(ISRestoreIndices(isn, &cols)); 1532 PetscFunctionReturn(PETSC_SUCCESS); 1533 } 1534 1535 /*@ 1536 MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1537 values into a matrix 1538 1539 Not Collective 1540 1541 Input Parameters: 1542 + mat - the matrix 1543 . row - the (block) row to set 1544 - v - a logically two-dimensional array of values 1545 1546 Level: intermediate 1547 1548 Notes: 1549 The values, `v`, are column-oriented (for the block version) and sorted 1550 1551 All the nonzeros in the row must be provided 1552 1553 The matrix must have previously had its column indices set, likely by having been assembled. 1554 1555 The row must belong to this process 1556 1557 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1558 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()` 1559 @*/ 1560 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[]) 1561 { 1562 PetscInt globalrow; 1563 1564 PetscFunctionBegin; 1565 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1566 PetscValidType(mat, 1); 1567 PetscValidScalarPointer(v, 3); 1568 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow)); 1569 PetscCall(MatSetValuesRow(mat, globalrow, v)); 1570 PetscFunctionReturn(PETSC_SUCCESS); 1571 } 1572 1573 /*@ 1574 MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1575 values into a matrix 1576 1577 Not Collective 1578 1579 Input Parameters: 1580 + mat - the matrix 1581 . row - the (block) row to set 1582 - v - a logically two-dimensional (column major) array of values for block matrices with blocksize larger than one, otherwise a one dimensional array of values 1583 1584 Level: advanced 1585 1586 Notes: 1587 The values, `v`, are column-oriented for the block version. 1588 1589 All the nonzeros in the row must be provided 1590 1591 THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used. 1592 1593 The row must belong to this process 1594 1595 .seealso: [](chapter_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1596 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()` 1597 @*/ 1598 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[]) 1599 { 1600 PetscFunctionBeginHot; 1601 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1602 PetscValidType(mat, 1); 1603 MatCheckPreallocated(mat, 1); 1604 PetscValidScalarPointer(v, 3); 1605 PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values"); 1606 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1607 mat->insertmode = INSERT_VALUES; 1608 1609 if (mat->assembled) { 1610 mat->was_assembled = PETSC_TRUE; 1611 mat->assembled = PETSC_FALSE; 1612 } 1613 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1614 PetscUseTypeMethod(mat, setvaluesrow, row, v); 1615 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1616 PetscFunctionReturn(PETSC_SUCCESS); 1617 } 1618 1619 /*@ 1620 MatSetValuesStencil - Inserts or adds a block of values into a matrix. 1621 Using structured grid indexing 1622 1623 Not Collective 1624 1625 Input Parameters: 1626 + mat - the matrix 1627 . m - number of rows being entered 1628 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered 1629 . n - number of columns being entered 1630 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered 1631 . v - a logically two-dimensional array of values 1632 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values 1633 1634 Level: beginner 1635 1636 Notes: 1637 By default the values, `v`, are row-oriented. See `MatSetOption()` for other options. 1638 1639 Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1640 options cannot be mixed without intervening calls to the assembly 1641 routines. 1642 1643 The grid coordinates are across the entire grid, not just the local portion 1644 1645 `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran 1646 as well as in C. 1647 1648 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1649 1650 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1651 or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1652 1653 The columns and rows in the stencil passed in MUST be contained within the 1654 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1655 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1656 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1657 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1658 1659 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 1660 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 1661 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 1662 `DM_BOUNDARY_PERIODIC` boundary type. 1663 1664 For indices that don't mean anything for your case (like the k index when working in 2d) or the c index when you have 1665 a single value per point) you can skip filling those indices. 1666 1667 Inspired by the structured grid interface to the HYPRE package 1668 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1669 1670 Efficiency Alert: 1671 The routine `MatSetValuesBlockedStencil()` may offer much better efficiency 1672 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1673 1674 Fortran Note: 1675 `idxm` and `idxn` should be declared as 1676 $ MatStencil idxm(4,m),idxn(4,n) 1677 and the values inserted using 1678 .vb 1679 idxm(MatStencil_i,1) = i 1680 idxm(MatStencil_j,1) = j 1681 idxm(MatStencil_k,1) = k 1682 idxm(MatStencil_c,1) = c 1683 etc 1684 .ve 1685 1686 .seealso: [](chapter_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1687 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil` 1688 @*/ 1689 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1690 { 1691 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1692 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1693 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1694 1695 PetscFunctionBegin; 1696 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1697 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1698 PetscValidType(mat, 1); 1699 PetscValidPointer(idxm, 3); 1700 PetscValidPointer(idxn, 5); 1701 1702 if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 1703 jdxm = buf; 1704 jdxn = buf + m; 1705 } else { 1706 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1707 jdxm = bufm; 1708 jdxn = bufn; 1709 } 1710 for (i = 0; i < m; i++) { 1711 for (j = 0; j < 3 - sdim; j++) dxm++; 1712 tmp = *dxm++ - starts[0]; 1713 for (j = 0; j < dim - 1; j++) { 1714 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1715 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1716 } 1717 if (mat->stencil.noc) dxm++; 1718 jdxm[i] = tmp; 1719 } 1720 for (i = 0; i < n; i++) { 1721 for (j = 0; j < 3 - sdim; j++) dxn++; 1722 tmp = *dxn++ - starts[0]; 1723 for (j = 0; j < dim - 1; j++) { 1724 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1725 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1726 } 1727 if (mat->stencil.noc) dxn++; 1728 jdxn[i] = tmp; 1729 } 1730 PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv)); 1731 PetscCall(PetscFree2(bufm, bufn)); 1732 PetscFunctionReturn(PETSC_SUCCESS); 1733 } 1734 1735 /*@ 1736 MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix. 1737 Using structured grid indexing 1738 1739 Not Collective 1740 1741 Input Parameters: 1742 + mat - the matrix 1743 . m - number of rows being entered 1744 . idxm - grid coordinates for matrix rows being entered 1745 . n - number of columns being entered 1746 . idxn - grid coordinates for matrix columns being entered 1747 . v - a logically two-dimensional array of values 1748 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values 1749 1750 Level: beginner 1751 1752 Notes: 1753 By default the values, `v`, are row-oriented and unsorted. 1754 See `MatSetOption()` for other options. 1755 1756 Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1757 options cannot be mixed without intervening calls to the assembly 1758 routines. 1759 1760 The grid coordinates are across the entire grid, not just the local portion 1761 1762 `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran 1763 as well as in C. 1764 1765 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1766 1767 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1768 or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1769 1770 The columns and rows in the stencil passed in MUST be contained within the 1771 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1772 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1773 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1774 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1775 1776 Negative indices may be passed in idxm and idxn, these rows and columns are 1777 simply ignored. This allows easily inserting element stiffness matrices 1778 with homogeneous Dirchlet boundary conditions that you don't want represented 1779 in the matrix. 1780 1781 Inspired by the structured grid interface to the HYPRE package 1782 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1783 1784 Fortran Note: 1785 `idxm` and `idxn` should be declared as 1786 $ MatStencil idxm(4,m),idxn(4,n) 1787 and the values inserted using 1788 .vb 1789 idxm(MatStencil_i,1) = i 1790 idxm(MatStencil_j,1) = j 1791 idxm(MatStencil_k,1) = k 1792 etc 1793 .ve 1794 1795 .seealso: [](chapter_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1796 `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`, 1797 `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` 1798 @*/ 1799 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1800 { 1801 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1802 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1803 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1804 1805 PetscFunctionBegin; 1806 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1807 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1808 PetscValidType(mat, 1); 1809 PetscValidPointer(idxm, 3); 1810 PetscValidPointer(idxn, 5); 1811 PetscValidScalarPointer(v, 6); 1812 1813 if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 1814 jdxm = buf; 1815 jdxn = buf + m; 1816 } else { 1817 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1818 jdxm = bufm; 1819 jdxn = bufn; 1820 } 1821 for (i = 0; i < m; i++) { 1822 for (j = 0; j < 3 - sdim; j++) dxm++; 1823 tmp = *dxm++ - starts[0]; 1824 for (j = 0; j < sdim - 1; j++) { 1825 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1826 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1827 } 1828 dxm++; 1829 jdxm[i] = tmp; 1830 } 1831 for (i = 0; i < n; i++) { 1832 for (j = 0; j < 3 - sdim; j++) dxn++; 1833 tmp = *dxn++ - starts[0]; 1834 for (j = 0; j < sdim - 1; j++) { 1835 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1836 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1837 } 1838 dxn++; 1839 jdxn[i] = tmp; 1840 } 1841 PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv)); 1842 PetscCall(PetscFree2(bufm, bufn)); 1843 PetscFunctionReturn(PETSC_SUCCESS); 1844 } 1845 1846 /*@ 1847 MatSetStencil - Sets the grid information for setting values into a matrix via 1848 `MatSetValuesStencil()` 1849 1850 Not Collective 1851 1852 Input Parameters: 1853 + mat - the matrix 1854 . dim - dimension of the grid 1, 2, or 3 1855 . dims - number of grid points in x, y, and z direction, including ghost points on your processor 1856 . starts - starting point of ghost nodes on your processor in x, y, and z direction 1857 - dof - number of degrees of freedom per node 1858 1859 Level: beginner 1860 1861 Notes: 1862 Inspired by the structured grid interface to the HYPRE package 1863 (www.llnl.gov/CASC/hyper) 1864 1865 For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the 1866 user. 1867 1868 .seealso: [](chapter_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1869 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()` 1870 @*/ 1871 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof) 1872 { 1873 PetscFunctionBegin; 1874 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1875 PetscValidIntPointer(dims, 3); 1876 PetscValidIntPointer(starts, 4); 1877 1878 mat->stencil.dim = dim + (dof > 1); 1879 for (PetscInt i = 0; i < dim; i++) { 1880 mat->stencil.dims[i] = dims[dim - i - 1]; /* copy the values in backwards */ 1881 mat->stencil.starts[i] = starts[dim - i - 1]; 1882 } 1883 mat->stencil.dims[dim] = dof; 1884 mat->stencil.starts[dim] = 0; 1885 mat->stencil.noc = (PetscBool)(dof == 1); 1886 PetscFunctionReturn(PETSC_SUCCESS); 1887 } 1888 1889 /*@C 1890 MatSetValuesBlocked - Inserts or adds a block of values into a matrix. 1891 1892 Not Collective 1893 1894 Input Parameters: 1895 + mat - the matrix 1896 . v - a logically two-dimensional array of values 1897 . m - the number of block rows 1898 . idxm - the global block indices 1899 . n - the number of block columns 1900 . idxn - the global block indices 1901 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values 1902 1903 Level: intermediate 1904 1905 Notes: 1906 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call 1907 MatXXXXSetPreallocation() or `MatSetUp()` before using this routine. 1908 1909 The `m` and `n` count the NUMBER of blocks in the row direction and column direction, 1910 NOT the total number of rows/columns; for example, if the block size is 2 and 1911 you are passing in values for rows 2,3,4,5 then m would be 2 (not 4). 1912 The values in idxm would be 1 2; that is the first index for each block divided by 1913 the block size. 1914 1915 You must call `MatSetBlockSize()` when constructing this matrix (before 1916 preallocating it). 1917 1918 By default the values, `v`, are row-oriented, so the layout of 1919 `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options. 1920 1921 Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES` 1922 options cannot be mixed without intervening calls to the assembly 1923 routines. 1924 1925 `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran 1926 as well as in C. 1927 1928 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1929 simply ignored. This allows easily inserting element stiffness matrices 1930 with homogeneous Dirchlet boundary conditions that you don't want represented 1931 in the matrix. 1932 1933 Each time an entry is set within a sparse matrix via `MatSetValues()`, 1934 internal searching must be done to determine where to place the 1935 data in the matrix storage space. By instead inserting blocks of 1936 entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is 1937 reduced. 1938 1939 Example: 1940 .vb 1941 Suppose m=n=2 and block size(bs) = 2 The array is 1942 1943 1 2 | 3 4 1944 5 6 | 7 8 1945 - - - | - - - 1946 9 10 | 11 12 1947 13 14 | 15 16 1948 1949 v[] should be passed in like 1950 v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] 1951 1952 If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then 1953 v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16] 1954 .ve 1955 1956 .seealso: [](chapter_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()` 1957 @*/ 1958 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1959 { 1960 PetscFunctionBeginHot; 1961 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1962 PetscValidType(mat, 1); 1963 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1964 PetscValidIntPointer(idxm, 3); 1965 PetscValidIntPointer(idxn, 5); 1966 MatCheckPreallocated(mat, 1); 1967 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1968 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1969 if (PetscDefined(USE_DEBUG)) { 1970 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1971 PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 1972 } 1973 if (PetscDefined(USE_DEBUG)) { 1974 PetscInt rbs, cbs, M, N, i; 1975 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1976 PetscCall(MatGetSize(mat, &M, &N)); 1977 for (i = 0; i < m; i++) PetscCheck(idxm[i] * rbs < M, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row block index %" PetscInt_FMT " (index %" PetscInt_FMT ") greater than row length %" PetscInt_FMT, i, idxm[i], M); 1978 for (i = 0; i < n; i++) PetscCheck(idxn[i] * cbs < N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column block index %" PetscInt_FMT " (index %" PetscInt_FMT ") great than column length %" PetscInt_FMT, i, idxn[i], N); 1979 } 1980 if (mat->assembled) { 1981 mat->was_assembled = PETSC_TRUE; 1982 mat->assembled = PETSC_FALSE; 1983 } 1984 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1985 if (mat->ops->setvaluesblocked) { 1986 PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv); 1987 } else { 1988 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn; 1989 PetscInt i, j, bs, cbs; 1990 1991 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 1992 if (m * bs + n * cbs <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 1993 iidxm = buf; 1994 iidxn = buf + m * bs; 1995 } else { 1996 PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc)); 1997 iidxm = bufr; 1998 iidxn = bufc; 1999 } 2000 for (i = 0; i < m; i++) { 2001 for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j; 2002 } 2003 if (m != n || bs != cbs || idxm != idxn) { 2004 for (i = 0; i < n; i++) { 2005 for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j; 2006 } 2007 } else iidxn = iidxm; 2008 PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv)); 2009 PetscCall(PetscFree2(bufr, bufc)); 2010 } 2011 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2012 PetscFunctionReturn(PETSC_SUCCESS); 2013 } 2014 2015 /*@C 2016 MatGetValues - Gets a block of local values from a matrix. 2017 2018 Not Collective; can only return values that are owned by the give process 2019 2020 Input Parameters: 2021 + mat - the matrix 2022 . v - a logically two-dimensional array for storing the values 2023 . m - the number of rows 2024 . idxm - the global indices of the rows 2025 . n - the number of columns 2026 - idxn - the global indices of the columns 2027 2028 Level: advanced 2029 2030 Notes: 2031 The user must allocate space (m*n `PetscScalar`s) for the values, `v`. 2032 The values, `v`, are then returned in a row-oriented format, 2033 analogous to that used by default in `MatSetValues()`. 2034 2035 `MatGetValues()` uses 0-based row and column numbers in 2036 Fortran as well as in C. 2037 2038 `MatGetValues()` requires that the matrix has been assembled 2039 with `MatAssemblyBegin()`/`MatAssemblyEnd()`. Thus, calls to 2040 `MatSetValues()` and `MatGetValues()` CANNOT be made in succession 2041 without intermediate matrix assembly. 2042 2043 Negative row or column indices will be ignored and those locations in `v` will be 2044 left unchanged. 2045 2046 For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI rank. 2047 That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable 2048 from `MatGetOwnershipRange`(mat,&rstart,&rend). 2049 2050 .seealso: [](chapter_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()` 2051 @*/ 2052 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) 2053 { 2054 PetscFunctionBegin; 2055 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2056 PetscValidType(mat, 1); 2057 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); 2058 PetscValidIntPointer(idxm, 3); 2059 PetscValidIntPointer(idxn, 5); 2060 PetscValidScalarPointer(v, 6); 2061 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2062 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2063 MatCheckPreallocated(mat, 1); 2064 2065 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2066 PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v); 2067 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2068 PetscFunctionReturn(PETSC_SUCCESS); 2069 } 2070 2071 /*@C 2072 MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices 2073 defined previously by `MatSetLocalToGlobalMapping()` 2074 2075 Not Collective 2076 2077 Input Parameters: 2078 + mat - the matrix 2079 . nrow - number of rows 2080 . irow - the row local indices 2081 . ncol - number of columns 2082 - icol - the column local indices 2083 2084 Output Parameter: 2085 . y - a logically two-dimensional array of values 2086 2087 Level: advanced 2088 2089 Notes: 2090 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine. 2091 2092 This routine can only return values that are owned by the requesting MPI rank. That is, for standard matrix formats, rows that, in the global numbering, 2093 are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can 2094 determine if the resulting global row associated with the local row r is owned by the requesting MPI rank by applying the `ISLocalToGlobalMapping` set 2095 with `MatSetLocalToGlobalMapping()`. 2096 2097 Developer Note: 2098 This is labelled with C so does not automatically generate Fortran stubs and interfaces 2099 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2100 2101 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2102 `MatSetValuesLocal()`, `MatGetValues()` 2103 @*/ 2104 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[]) 2105 { 2106 PetscFunctionBeginHot; 2107 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2108 PetscValidType(mat, 1); 2109 MatCheckPreallocated(mat, 1); 2110 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */ 2111 PetscValidIntPointer(irow, 3); 2112 PetscValidIntPointer(icol, 5); 2113 if (PetscDefined(USE_DEBUG)) { 2114 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2115 PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2116 } 2117 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2118 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2119 if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y); 2120 else { 2121 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm; 2122 if ((nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2123 irowm = buf; 2124 icolm = buf + nrow; 2125 } else { 2126 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2127 irowm = bufr; 2128 icolm = bufc; 2129 } 2130 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping())."); 2131 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping())."); 2132 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm)); 2133 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm)); 2134 PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y)); 2135 PetscCall(PetscFree2(bufr, bufc)); 2136 } 2137 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2138 PetscFunctionReturn(PETSC_SUCCESS); 2139 } 2140 2141 /*@ 2142 MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and 2143 the same size. Currently, this can only be called once and creates the given matrix. 2144 2145 Not Collective 2146 2147 Input Parameters: 2148 + mat - the matrix 2149 . nb - the number of blocks 2150 . bs - the number of rows (and columns) in each block 2151 . rows - a concatenation of the rows for each block 2152 - v - a concatenation of logically two-dimensional arrays of values 2153 2154 Level: advanced 2155 2156 Note: 2157 `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values 2158 2159 In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix. 2160 2161 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 2162 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()` 2163 @*/ 2164 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[]) 2165 { 2166 PetscFunctionBegin; 2167 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2168 PetscValidType(mat, 1); 2169 PetscValidIntPointer(rows, 4); 2170 PetscValidScalarPointer(v, 5); 2171 PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2172 2173 PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0)); 2174 if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v); 2175 else { 2176 for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES)); 2177 } 2178 PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0)); 2179 PetscFunctionReturn(PETSC_SUCCESS); 2180 } 2181 2182 /*@ 2183 MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by 2184 the routine `MatSetValuesLocal()` to allow users to insert matrix entries 2185 using a local (per-processor) numbering. 2186 2187 Not Collective 2188 2189 Input Parameters: 2190 + x - the matrix 2191 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()` 2192 - cmapping - column mapping 2193 2194 Level: intermediate 2195 2196 Note: 2197 If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix 2198 2199 .seealso: [](chapter_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()` 2200 @*/ 2201 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping) 2202 { 2203 PetscFunctionBegin; 2204 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 2205 PetscValidType(x, 1); 2206 if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2); 2207 if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3); 2208 if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping); 2209 else { 2210 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping)); 2211 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping)); 2212 } 2213 PetscFunctionReturn(PETSC_SUCCESS); 2214 } 2215 2216 /*@ 2217 MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()` 2218 2219 Not Collective 2220 2221 Input Parameter: 2222 . A - the matrix 2223 2224 Output Parameters: 2225 + rmapping - row mapping 2226 - cmapping - column mapping 2227 2228 Level: advanced 2229 2230 .seealso: [](chapter_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()` 2231 @*/ 2232 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping) 2233 { 2234 PetscFunctionBegin; 2235 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2236 PetscValidType(A, 1); 2237 if (rmapping) { 2238 PetscValidPointer(rmapping, 2); 2239 *rmapping = A->rmap->mapping; 2240 } 2241 if (cmapping) { 2242 PetscValidPointer(cmapping, 3); 2243 *cmapping = A->cmap->mapping; 2244 } 2245 PetscFunctionReturn(PETSC_SUCCESS); 2246 } 2247 2248 /*@ 2249 MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix 2250 2251 Logically Collective 2252 2253 Input Parameters: 2254 + A - the matrix 2255 . rmap - row layout 2256 - cmap - column layout 2257 2258 Level: advanced 2259 2260 Note: 2261 The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called. 2262 2263 .seealso: [](chapter_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()` 2264 @*/ 2265 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap) 2266 { 2267 PetscFunctionBegin; 2268 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2269 PetscCall(PetscLayoutReference(rmap, &A->rmap)); 2270 PetscCall(PetscLayoutReference(cmap, &A->cmap)); 2271 PetscFunctionReturn(PETSC_SUCCESS); 2272 } 2273 2274 /*@ 2275 MatGetLayouts - Gets the `PetscLayout` objects for rows and columns 2276 2277 Not Collective 2278 2279 Input Parameter: 2280 . A - the matrix 2281 2282 Output Parameters: 2283 + rmap - row layout 2284 - cmap - column layout 2285 2286 Level: advanced 2287 2288 .seealso: [](chapter_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()` 2289 @*/ 2290 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap) 2291 { 2292 PetscFunctionBegin; 2293 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2294 PetscValidType(A, 1); 2295 if (rmap) { 2296 PetscValidPointer(rmap, 2); 2297 *rmap = A->rmap; 2298 } 2299 if (cmap) { 2300 PetscValidPointer(cmap, 3); 2301 *cmap = A->cmap; 2302 } 2303 PetscFunctionReturn(PETSC_SUCCESS); 2304 } 2305 2306 /*@C 2307 MatSetValuesLocal - Inserts or adds values into certain locations of a matrix, 2308 using a local numbering of the nodes. 2309 2310 Not Collective 2311 2312 Input Parameters: 2313 + mat - the matrix 2314 . nrow - number of rows 2315 . irow - the row local indices 2316 . ncol - number of columns 2317 . icol - the column local indices 2318 . y - a logically two-dimensional array of values 2319 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2320 2321 Level: intermediate 2322 2323 Notes: 2324 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 2325 `MatSetUp()` before using this routine 2326 2327 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine 2328 2329 Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2330 options cannot be mixed without intervening calls to the assembly 2331 routines. 2332 2333 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2334 MUST be called after all calls to `MatSetValuesLocal()` have been completed. 2335 2336 Developer Note: 2337 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2338 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2339 2340 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2341 `MatGetValuesLocal()` 2342 @*/ 2343 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2344 { 2345 PetscFunctionBeginHot; 2346 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2347 PetscValidType(mat, 1); 2348 MatCheckPreallocated(mat, 1); 2349 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2350 PetscValidIntPointer(irow, 3); 2351 PetscValidIntPointer(icol, 5); 2352 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2353 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2354 if (PetscDefined(USE_DEBUG)) { 2355 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2356 PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2357 } 2358 2359 if (mat->assembled) { 2360 mat->was_assembled = PETSC_TRUE; 2361 mat->assembled = PETSC_FALSE; 2362 } 2363 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2364 if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv); 2365 else { 2366 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2367 const PetscInt *irowm, *icolm; 2368 2369 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2370 bufr = buf; 2371 bufc = buf + nrow; 2372 irowm = bufr; 2373 icolm = bufc; 2374 } else { 2375 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2376 irowm = bufr; 2377 icolm = bufc; 2378 } 2379 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr)); 2380 else irowm = irow; 2381 if (mat->cmap->mapping) { 2382 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2383 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc)); 2384 } else icolm = irowm; 2385 } else icolm = icol; 2386 PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv)); 2387 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2388 } 2389 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2390 PetscFunctionReturn(PETSC_SUCCESS); 2391 } 2392 2393 /*@C 2394 MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix, 2395 using a local ordering of the nodes a block at a time. 2396 2397 Not Collective 2398 2399 Input Parameters: 2400 + x - the matrix 2401 . nrow - number of rows 2402 . irow - the row local indices 2403 . ncol - number of columns 2404 . icol - the column local indices 2405 . y - a logically two-dimensional array of values 2406 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2407 2408 Level: intermediate 2409 2410 Notes: 2411 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 2412 `MatSetUp()` before using this routine 2413 2414 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()` 2415 before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the 2416 2417 Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2418 options cannot be mixed without intervening calls to the assembly 2419 routines. 2420 2421 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2422 MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed. 2423 2424 Developer Note: 2425 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2426 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2427 2428 .seealso: [](chapter_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, 2429 `MatSetValuesLocal()`, `MatSetValuesBlocked()` 2430 @*/ 2431 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2432 { 2433 PetscFunctionBeginHot; 2434 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2435 PetscValidType(mat, 1); 2436 MatCheckPreallocated(mat, 1); 2437 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2438 PetscValidIntPointer(irow, 3); 2439 PetscValidIntPointer(icol, 5); 2440 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2441 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2442 if (PetscDefined(USE_DEBUG)) { 2443 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2444 PetscCheck(mat->ops->setvaluesblockedlocal || mat->ops->setvaluesblocked || mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2445 } 2446 2447 if (mat->assembled) { 2448 mat->was_assembled = PETSC_TRUE; 2449 mat->assembled = PETSC_FALSE; 2450 } 2451 if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */ 2452 PetscInt irbs, rbs; 2453 PetscCall(MatGetBlockSizes(mat, &rbs, NULL)); 2454 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs)); 2455 PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs); 2456 } 2457 if (PetscUnlikelyDebug(mat->cmap->mapping)) { 2458 PetscInt icbs, cbs; 2459 PetscCall(MatGetBlockSizes(mat, NULL, &cbs)); 2460 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs)); 2461 PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs); 2462 } 2463 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2464 if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv); 2465 else { 2466 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2467 const PetscInt *irowm, *icolm; 2468 2469 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2470 bufr = buf; 2471 bufc = buf + nrow; 2472 irowm = bufr; 2473 icolm = bufc; 2474 } else { 2475 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2476 irowm = bufr; 2477 icolm = bufc; 2478 } 2479 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr)); 2480 else irowm = irow; 2481 if (mat->cmap->mapping) { 2482 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2483 PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc)); 2484 } else icolm = irowm; 2485 } else icolm = icol; 2486 PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv)); 2487 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2488 } 2489 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2490 PetscFunctionReturn(PETSC_SUCCESS); 2491 } 2492 2493 /*@ 2494 MatMultDiagonalBlock - Computes the matrix-vector product, y = Dx. Where D is defined by the inode or block structure of the diagonal 2495 2496 Collective 2497 2498 Input Parameters: 2499 + mat - the matrix 2500 - x - the vector to be multiplied 2501 2502 Output Parameter: 2503 . y - the result 2504 2505 Level: developer 2506 2507 Note: 2508 The vectors `x` and `y` cannot be the same. I.e., one cannot 2509 call `MatMultDiagonalBlock`(A,y,y). 2510 2511 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2512 @*/ 2513 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y) 2514 { 2515 PetscFunctionBegin; 2516 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2517 PetscValidType(mat, 1); 2518 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2519 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2520 2521 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2522 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2523 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2524 MatCheckPreallocated(mat, 1); 2525 2526 PetscUseTypeMethod(mat, multdiagonalblock, x, y); 2527 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2528 PetscFunctionReturn(PETSC_SUCCESS); 2529 } 2530 2531 /*@ 2532 MatMult - Computes the matrix-vector product, y = Ax. 2533 2534 Neighbor-wise Collective 2535 2536 Input Parameters: 2537 + mat - the matrix 2538 - x - the vector to be multiplied 2539 2540 Output Parameter: 2541 . y - the result 2542 2543 Level: beginner 2544 2545 Note: 2546 The vectors `x` and `y` cannot be the same. I.e., one cannot 2547 call `MatMult`(A,y,y). 2548 2549 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2550 @*/ 2551 PetscErrorCode MatMult(Mat mat, Vec x, Vec y) 2552 { 2553 PetscFunctionBegin; 2554 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2555 PetscValidType(mat, 1); 2556 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2557 VecCheckAssembled(x); 2558 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2559 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2560 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2561 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2562 PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N); 2563 PetscCheck(mat->rmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, y->map->N); 2564 PetscCheck(mat->cmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, x->map->n); 2565 PetscCheck(mat->rmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, y->map->n); 2566 PetscCall(VecSetErrorIfLocked(y, 3)); 2567 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2568 MatCheckPreallocated(mat, 1); 2569 2570 PetscCall(VecLockReadPush(x)); 2571 PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0)); 2572 PetscUseTypeMethod(mat, mult, x, y); 2573 PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0)); 2574 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2575 PetscCall(VecLockReadPop(x)); 2576 PetscFunctionReturn(PETSC_SUCCESS); 2577 } 2578 2579 /*@ 2580 MatMultTranspose - Computes matrix transpose times a vector y = A^T * x. 2581 2582 Neighbor-wise Collective 2583 2584 Input Parameters: 2585 + mat - the matrix 2586 - x - the vector to be multiplied 2587 2588 Output Parameter: 2589 . y - the result 2590 2591 Level: beginner 2592 2593 Notes: 2594 The vectors `x` and `y` cannot be the same. I.e., one cannot 2595 call `MatMultTranspose`(A,y,y). 2596 2597 For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple, 2598 use `MatMultHermitianTranspose()` 2599 2600 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()` 2601 @*/ 2602 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y) 2603 { 2604 PetscErrorCode (*op)(Mat, Vec, Vec) = NULL; 2605 2606 PetscFunctionBegin; 2607 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2608 PetscValidType(mat, 1); 2609 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2610 VecCheckAssembled(x); 2611 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2612 2613 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2614 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2615 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2616 PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N); 2617 PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N); 2618 PetscCheck(mat->cmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, y->map->n); 2619 PetscCheck(mat->rmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, x->map->n); 2620 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2621 MatCheckPreallocated(mat, 1); 2622 2623 if (!mat->ops->multtranspose) { 2624 if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult; 2625 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s does not have a multiply transpose defined or is symmetric and does not have a multiply defined", ((PetscObject)mat)->type_name); 2626 } else op = mat->ops->multtranspose; 2627 PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0)); 2628 PetscCall(VecLockReadPush(x)); 2629 PetscCall((*op)(mat, x, y)); 2630 PetscCall(VecLockReadPop(x)); 2631 PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0)); 2632 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2633 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2634 PetscFunctionReturn(PETSC_SUCCESS); 2635 } 2636 2637 /*@ 2638 MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector. 2639 2640 Neighbor-wise Collective 2641 2642 Input Parameters: 2643 + mat - the matrix 2644 - x - the vector to be multilplied 2645 2646 Output Parameter: 2647 . y - the result 2648 2649 Level: beginner 2650 2651 Notes: 2652 The vectors `x` and `y` cannot be the same. I.e., one cannot 2653 call `MatMultHermitianTranspose`(A,y,y). 2654 2655 Also called the conjugate transpose, complex conjugate transpose, or adjoint. 2656 2657 For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical. 2658 2659 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()` 2660 @*/ 2661 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y) 2662 { 2663 PetscFunctionBegin; 2664 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2665 PetscValidType(mat, 1); 2666 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2667 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2668 2669 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2670 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2671 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2672 PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N); 2673 PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N); 2674 PetscCheck(mat->cmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, y->map->n); 2675 PetscCheck(mat->rmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, x->map->n); 2676 MatCheckPreallocated(mat, 1); 2677 2678 PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0)); 2679 #if defined(PETSC_USE_COMPLEX) 2680 if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) { 2681 PetscCall(VecLockReadPush(x)); 2682 if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y); 2683 else PetscUseTypeMethod(mat, mult, x, y); 2684 PetscCall(VecLockReadPop(x)); 2685 } else { 2686 Vec w; 2687 PetscCall(VecDuplicate(x, &w)); 2688 PetscCall(VecCopy(x, w)); 2689 PetscCall(VecConjugate(w)); 2690 PetscCall(MatMultTranspose(mat, w, y)); 2691 PetscCall(VecDestroy(&w)); 2692 PetscCall(VecConjugate(y)); 2693 } 2694 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2695 #else 2696 PetscCall(MatMultTranspose(mat, x, y)); 2697 #endif 2698 PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0)); 2699 PetscFunctionReturn(PETSC_SUCCESS); 2700 } 2701 2702 /*@ 2703 MatMultAdd - Computes v3 = v2 + A * v1. 2704 2705 Neighbor-wise Collective 2706 2707 Input Parameters: 2708 + mat - the matrix 2709 . v1 - the vector to be multiplied by `mat` 2710 - v2 - the vector to be added to the result 2711 2712 Output Parameter: 2713 . v3 - the result 2714 2715 Level: beginner 2716 2717 Note: 2718 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2719 call `MatMultAdd`(A,v1,v2,v1). 2720 2721 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()` 2722 @*/ 2723 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2724 { 2725 PetscFunctionBegin; 2726 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2727 PetscValidType(mat, 1); 2728 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2729 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2730 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2731 2732 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2733 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2734 PetscCheck(mat->cmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v1->map->N); 2735 /* PetscCheck(mat->rmap->N == v2->map->N,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v2->map->N); 2736 PetscCheck(mat->rmap->N == v3->map->N,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v3->map->N); */ 2737 PetscCheck(mat->rmap->n == v3->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, v3->map->n); 2738 PetscCheck(mat->rmap->n == v2->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, v2->map->n); 2739 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2740 MatCheckPreallocated(mat, 1); 2741 2742 PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3)); 2743 PetscCall(VecLockReadPush(v1)); 2744 PetscUseTypeMethod(mat, multadd, v1, v2, v3); 2745 PetscCall(VecLockReadPop(v1)); 2746 PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3)); 2747 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2748 PetscFunctionReturn(PETSC_SUCCESS); 2749 } 2750 2751 /*@ 2752 MatMultTransposeAdd - Computes v3 = v2 + A' * v1. 2753 2754 Neighbor-wise Collective 2755 2756 Input Parameters: 2757 + mat - the matrix 2758 . v1 - the vector to be multiplied by the transpose of the matrix 2759 - v2 - the vector to be added to the result 2760 2761 Output Parameter: 2762 . v3 - the result 2763 2764 Level: beginner 2765 2766 Note: 2767 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2768 call `MatMultTransposeAdd`(A,v1,v2,v1). 2769 2770 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2771 @*/ 2772 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2773 { 2774 PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd; 2775 2776 PetscFunctionBegin; 2777 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2778 PetscValidType(mat, 1); 2779 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2780 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2781 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2782 2783 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2784 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2785 PetscCheck(mat->rmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, v1->map->N); 2786 PetscCheck(mat->cmap->N == v2->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v2->map->N); 2787 PetscCheck(mat->cmap->N == v3->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v3->map->N); 2788 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2789 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2790 MatCheckPreallocated(mat, 1); 2791 2792 PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2793 PetscCall(VecLockReadPush(v1)); 2794 PetscCall((*op)(mat, v1, v2, v3)); 2795 PetscCall(VecLockReadPop(v1)); 2796 PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2797 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2798 PetscFunctionReturn(PETSC_SUCCESS); 2799 } 2800 2801 /*@ 2802 MatMultHermitianTransposeAdd - Computes v3 = v2 + A^H * v1. 2803 2804 Neighbor-wise Collective 2805 2806 Input Parameters: 2807 + mat - the matrix 2808 . v1 - the vector to be multiplied by the Hermitian transpose 2809 - v2 - the vector to be added to the result 2810 2811 Output Parameter: 2812 . v3 - the result 2813 2814 Level: beginner 2815 2816 Note: 2817 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2818 call `MatMultHermitianTransposeAdd`(A,v1,v2,v1). 2819 2820 .seealso: [](chapter_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2821 @*/ 2822 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2823 { 2824 PetscFunctionBegin; 2825 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2826 PetscValidType(mat, 1); 2827 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2828 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2829 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2830 2831 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2832 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2833 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2834 PetscCheck(mat->rmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, v1->map->N); 2835 PetscCheck(mat->cmap->N == v2->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v2->map->N); 2836 PetscCheck(mat->cmap->N == v3->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v3->map->N); 2837 MatCheckPreallocated(mat, 1); 2838 2839 PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2840 PetscCall(VecLockReadPush(v1)); 2841 if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3); 2842 else { 2843 Vec w, z; 2844 PetscCall(VecDuplicate(v1, &w)); 2845 PetscCall(VecCopy(v1, w)); 2846 PetscCall(VecConjugate(w)); 2847 PetscCall(VecDuplicate(v3, &z)); 2848 PetscCall(MatMultTranspose(mat, w, z)); 2849 PetscCall(VecDestroy(&w)); 2850 PetscCall(VecConjugate(z)); 2851 if (v2 != v3) { 2852 PetscCall(VecWAXPY(v3, 1.0, v2, z)); 2853 } else { 2854 PetscCall(VecAXPY(v3, 1.0, z)); 2855 } 2856 PetscCall(VecDestroy(&z)); 2857 } 2858 PetscCall(VecLockReadPop(v1)); 2859 PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2860 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2861 PetscFunctionReturn(PETSC_SUCCESS); 2862 } 2863 2864 /*@C 2865 MatGetFactorType - gets the type of factorization it is 2866 2867 Not Collective 2868 2869 Input Parameter: 2870 . mat - the matrix 2871 2872 Output Parameter: 2873 . t - the type, one of `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2874 2875 Level: intermediate 2876 2877 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2878 `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2879 @*/ 2880 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t) 2881 { 2882 PetscFunctionBegin; 2883 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2884 PetscValidType(mat, 1); 2885 PetscValidPointer(t, 2); 2886 *t = mat->factortype; 2887 PetscFunctionReturn(PETSC_SUCCESS); 2888 } 2889 2890 /*@C 2891 MatSetFactorType - sets the type of factorization it is 2892 2893 Logically Collective 2894 2895 Input Parameters: 2896 + mat - the matrix 2897 - t - the type, one of `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2898 2899 Level: intermediate 2900 2901 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2902 `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2903 @*/ 2904 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t) 2905 { 2906 PetscFunctionBegin; 2907 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2908 PetscValidType(mat, 1); 2909 mat->factortype = t; 2910 PetscFunctionReturn(PETSC_SUCCESS); 2911 } 2912 2913 /*@C 2914 MatGetInfo - Returns information about matrix storage (number of 2915 nonzeros, memory, etc.). 2916 2917 Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag 2918 2919 Input Parameters: 2920 + mat - the matrix 2921 - flag - flag indicating the type of parameters to be returned (`MAT_LOCAL` - local matrix, `MAT_GLOBAL_MAX` - maximum over all processors, `MAT_GLOBAL_SUM` - sum over all processors) 2922 2923 Output Parameter: 2924 . info - matrix information context 2925 2926 Notes: 2927 The `MatInfo` context contains a variety of matrix data, including 2928 number of nonzeros allocated and used, number of mallocs during 2929 matrix assembly, etc. Additional information for factored matrices 2930 is provided (such as the fill ratio, number of mallocs during 2931 factorization, etc.). Much of this info is printed to `PETSC_STDOUT` 2932 when using the runtime options 2933 $ -info -mat_view ::ascii_info 2934 2935 Example: 2936 See the file ${PETSC_DIR}/include/petscmat.h for a complete list of 2937 data within the MatInfo context. For example, 2938 .vb 2939 MatInfo info; 2940 Mat A; 2941 double mal, nz_a, nz_u; 2942 2943 MatGetInfo(A,MAT_LOCAL,&info); 2944 mal = info.mallocs; 2945 nz_a = info.nz_allocated; 2946 .ve 2947 2948 Fortran users should declare info as a double precision 2949 array of dimension `MAT_INFO_SIZE`, and then extract the parameters 2950 of interest. See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h 2951 a complete list of parameter names. 2952 .vb 2953 double precision info(MAT_INFO_SIZE) 2954 double precision mal, nz_a 2955 Mat A 2956 integer ierr 2957 2958 call MatGetInfo(A,MAT_LOCAL,info,ierr) 2959 mal = info(MAT_INFO_MALLOCS) 2960 nz_a = info(MAT_INFO_NZ_ALLOCATED) 2961 .ve 2962 2963 Level: intermediate 2964 2965 Developer Note: 2966 The Fortran interface is not autogenerated as the 2967 interface definition cannot be generated correctly [due to `MatInfo` argument] 2968 2969 .seealso: [](chapter_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()` 2970 @*/ 2971 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info) 2972 { 2973 PetscFunctionBegin; 2974 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2975 PetscValidType(mat, 1); 2976 PetscValidPointer(info, 3); 2977 MatCheckPreallocated(mat, 1); 2978 PetscUseTypeMethod(mat, getinfo, flag, info); 2979 PetscFunctionReturn(PETSC_SUCCESS); 2980 } 2981 2982 /* 2983 This is used by external packages where it is not easy to get the info from the actual 2984 matrix factorization. 2985 */ 2986 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info) 2987 { 2988 PetscFunctionBegin; 2989 PetscCall(PetscMemzero(info, sizeof(MatInfo))); 2990 PetscFunctionReturn(PETSC_SUCCESS); 2991 } 2992 2993 /*@C 2994 MatLUFactor - Performs in-place LU factorization of matrix. 2995 2996 Collective 2997 2998 Input Parameters: 2999 + mat - the matrix 3000 . row - row permutation 3001 . col - column permutation 3002 - info - options for factorization, includes 3003 .vb 3004 fill - expected fill as ratio of original fill. 3005 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3006 Run with the option -info to determine an optimal value to use 3007 .ve 3008 Level: developer 3009 3010 Notes: 3011 Most users should employ the `KSP` interface for linear solvers 3012 instead of working directly with matrix algebra routines such as this. 3013 See, e.g., `KSPCreate()`. 3014 3015 This changes the state of the matrix to a factored matrix; it cannot be used 3016 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3017 3018 This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()` 3019 when not using `KSP`. 3020 3021 Developer Note: 3022 The Fortran interface is not autogenerated as the 3023 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3024 3025 .seealso: [](chapter_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, 3026 `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3027 @*/ 3028 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3029 { 3030 MatFactorInfo tinfo; 3031 3032 PetscFunctionBegin; 3033 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3034 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3035 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3036 if (info) PetscValidPointer(info, 4); 3037 PetscValidType(mat, 1); 3038 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3039 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3040 MatCheckPreallocated(mat, 1); 3041 if (!info) { 3042 PetscCall(MatFactorInfoInitialize(&tinfo)); 3043 info = &tinfo; 3044 } 3045 3046 PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0)); 3047 PetscUseTypeMethod(mat, lufactor, row, col, info); 3048 PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0)); 3049 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3050 PetscFunctionReturn(PETSC_SUCCESS); 3051 } 3052 3053 /*@C 3054 MatILUFactor - Performs in-place ILU factorization of matrix. 3055 3056 Collective 3057 3058 Input Parameters: 3059 + mat - the matrix 3060 . row - row permutation 3061 . col - column permutation 3062 - info - structure containing 3063 .vb 3064 levels - number of levels of fill. 3065 expected fill - as ratio of original fill. 3066 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 3067 missing diagonal entries) 3068 .ve 3069 3070 Level: developer 3071 3072 Notes: 3073 Most users should employ the `KSP` interface for linear solvers 3074 instead of working directly with matrix algebra routines such as this. 3075 See, e.g., `KSPCreate()`. 3076 3077 Probably really in-place only when level of fill is zero, otherwise allocates 3078 new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()` 3079 when not using `KSP`. 3080 3081 Developer Note: 3082 The Fortran interface is not autogenerated as the 3083 interface definition cannot be generated correctly [due to MatFactorInfo] 3084 3085 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 3086 @*/ 3087 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3088 { 3089 PetscFunctionBegin; 3090 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3091 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3092 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3093 PetscValidPointer(info, 4); 3094 PetscValidType(mat, 1); 3095 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 3096 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3097 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3098 MatCheckPreallocated(mat, 1); 3099 3100 PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0)); 3101 PetscUseTypeMethod(mat, ilufactor, row, col, info); 3102 PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0)); 3103 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3104 PetscFunctionReturn(PETSC_SUCCESS); 3105 } 3106 3107 /*@C 3108 MatLUFactorSymbolic - Performs symbolic LU factorization of matrix. 3109 Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`. 3110 3111 Collective 3112 3113 Input Parameters: 3114 + fact - the factor matrix obtained with `MatGetFactor()` 3115 . mat - the matrix 3116 . row - the row permutation 3117 . col - the column permutation 3118 - info - options for factorization, includes 3119 .vb 3120 fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use 3121 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3122 .ve 3123 3124 Level: developer 3125 3126 Notes: 3127 See [Matrix Factorization](sec_matfactor) for additional information about factorizations 3128 3129 Most users should employ the simplified `KSP` interface for linear solvers 3130 instead of working directly with matrix algebra routines such as this. 3131 See, e.g., `KSPCreate()`. 3132 3133 Developer Note: 3134 The Fortran interface is not autogenerated as the 3135 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3136 3137 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3138 @*/ 3139 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 3140 { 3141 MatFactorInfo tinfo; 3142 3143 PetscFunctionBegin; 3144 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3145 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3146 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 3147 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 3148 if (info) PetscValidPointer(info, 5); 3149 PetscValidType(fact, 1); 3150 PetscValidType(mat, 2); 3151 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3152 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3153 MatCheckPreallocated(mat, 2); 3154 if (!info) { 3155 PetscCall(MatFactorInfoInitialize(&tinfo)); 3156 info = &tinfo; 3157 } 3158 3159 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0)); 3160 PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info); 3161 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0)); 3162 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3163 PetscFunctionReturn(PETSC_SUCCESS); 3164 } 3165 3166 /*@C 3167 MatLUFactorNumeric - Performs numeric LU factorization of a matrix. 3168 Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`. 3169 3170 Collective 3171 3172 Input Parameters: 3173 + fact - the factor matrix obtained with `MatGetFactor()` 3174 . mat - the matrix 3175 - info - options for factorization 3176 3177 Level: developer 3178 3179 Notes: 3180 See `MatLUFactor()` for in-place factorization. See 3181 `MatCholeskyFactorNumeric()` for the symmetric, positive definite case. 3182 3183 Most users should employ the `KSP` interface for linear solvers 3184 instead of working directly with matrix algebra routines such as this. 3185 See, e.g., `KSPCreate()`. 3186 3187 Developer Note: 3188 The Fortran interface is not autogenerated as the 3189 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3190 3191 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()` 3192 @*/ 3193 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3194 { 3195 MatFactorInfo tinfo; 3196 3197 PetscFunctionBegin; 3198 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3199 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3200 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3201 PetscValidType(fact, 1); 3202 PetscValidType(mat, 2); 3203 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3204 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, 3205 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3206 3207 MatCheckPreallocated(mat, 2); 3208 if (!info) { 3209 PetscCall(MatFactorInfoInitialize(&tinfo)); 3210 info = &tinfo; 3211 } 3212 3213 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3214 else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0)); 3215 PetscUseTypeMethod(fact, lufactornumeric, mat, info); 3216 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3217 else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0)); 3218 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3219 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3220 PetscFunctionReturn(PETSC_SUCCESS); 3221 } 3222 3223 /*@C 3224 MatCholeskyFactor - Performs in-place Cholesky factorization of a 3225 symmetric matrix. 3226 3227 Collective 3228 3229 Input Parameters: 3230 + mat - the matrix 3231 . perm - row and column permutations 3232 - f - expected fill as ratio of original fill 3233 3234 Level: developer 3235 3236 Notes: 3237 See `MatLUFactor()` for the nonsymmetric case. See also `MatGetFactor()`, 3238 `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`. 3239 3240 Most users should employ the `KSP` interface for linear solvers 3241 instead of working directly with matrix algebra routines such as this. 3242 See, e.g., `KSPCreate()`. 3243 3244 Developer Note: 3245 The Fortran interface is not autogenerated as the 3246 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3247 3248 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()` 3249 `MatGetOrdering()` 3250 @*/ 3251 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info) 3252 { 3253 MatFactorInfo tinfo; 3254 3255 PetscFunctionBegin; 3256 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3257 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2); 3258 if (info) PetscValidPointer(info, 3); 3259 PetscValidType(mat, 1); 3260 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3261 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3262 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3263 MatCheckPreallocated(mat, 1); 3264 if (!info) { 3265 PetscCall(MatFactorInfoInitialize(&tinfo)); 3266 info = &tinfo; 3267 } 3268 3269 PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0)); 3270 PetscUseTypeMethod(mat, choleskyfactor, perm, info); 3271 PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0)); 3272 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3273 PetscFunctionReturn(PETSC_SUCCESS); 3274 } 3275 3276 /*@C 3277 MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization 3278 of a symmetric matrix. 3279 3280 Collective 3281 3282 Input Parameters: 3283 + fact - the factor matrix obtained with `MatGetFactor()` 3284 . mat - the matrix 3285 . perm - row and column permutations 3286 - info - options for factorization, includes 3287 .vb 3288 fill - expected fill as ratio of original fill. 3289 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3290 Run with the option -info to determine an optimal value to use 3291 .ve 3292 3293 Level: developer 3294 3295 Notes: 3296 See `MatLUFactorSymbolic()` for the nonsymmetric case. See also 3297 `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`. 3298 3299 Most users should employ the `KSP` interface for linear solvers 3300 instead of working directly with matrix algebra routines such as this. 3301 See, e.g., `KSPCreate()`. 3302 3303 Developer Note: 3304 The Fortran interface is not autogenerated as the 3305 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3306 3307 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()` 3308 `MatGetOrdering()` 3309 @*/ 3310 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 3311 { 3312 MatFactorInfo tinfo; 3313 3314 PetscFunctionBegin; 3315 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3316 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3317 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 3318 if (info) PetscValidPointer(info, 4); 3319 PetscValidType(fact, 1); 3320 PetscValidType(mat, 2); 3321 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3322 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3323 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3324 MatCheckPreallocated(mat, 2); 3325 if (!info) { 3326 PetscCall(MatFactorInfoInitialize(&tinfo)); 3327 info = &tinfo; 3328 } 3329 3330 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3331 PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info); 3332 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3333 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3334 PetscFunctionReturn(PETSC_SUCCESS); 3335 } 3336 3337 /*@C 3338 MatCholeskyFactorNumeric - Performs numeric Cholesky factorization 3339 of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and 3340 `MatCholeskyFactorSymbolic()`. 3341 3342 Collective 3343 3344 Input Parameters: 3345 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored 3346 . mat - the initial matrix that is to be factored 3347 - info - options for factorization 3348 3349 Level: developer 3350 3351 Note: 3352 Most users should employ the `KSP` interface for linear solvers 3353 instead of working directly with matrix algebra routines such as this. 3354 See, e.g., `KSPCreate()`. 3355 3356 Developer Note: 3357 The Fortran interface is not autogenerated as the 3358 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3359 3360 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()` 3361 @*/ 3362 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3363 { 3364 MatFactorInfo tinfo; 3365 3366 PetscFunctionBegin; 3367 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3368 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3369 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3370 PetscValidType(fact, 1); 3371 PetscValidType(mat, 2); 3372 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3373 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, 3374 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3375 MatCheckPreallocated(mat, 2); 3376 if (!info) { 3377 PetscCall(MatFactorInfoInitialize(&tinfo)); 3378 info = &tinfo; 3379 } 3380 3381 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3382 else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0)); 3383 PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info); 3384 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3385 else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0)); 3386 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3387 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3388 PetscFunctionReturn(PETSC_SUCCESS); 3389 } 3390 3391 /*@ 3392 MatQRFactor - Performs in-place QR factorization of matrix. 3393 3394 Collective 3395 3396 Input Parameters: 3397 + mat - the matrix 3398 . col - column permutation 3399 - info - options for factorization, includes 3400 .vb 3401 fill - expected fill as ratio of original fill. 3402 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3403 Run with the option -info to determine an optimal value to use 3404 .ve 3405 3406 Level: developer 3407 3408 Notes: 3409 Most users should employ the `KSP` interface for linear solvers 3410 instead of working directly with matrix algebra routines such as this. 3411 See, e.g., `KSPCreate()`. 3412 3413 This changes the state of the matrix to a factored matrix; it cannot be used 3414 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3415 3416 Developer Note: 3417 The Fortran interface is not autogenerated as the 3418 interface definition cannot be generated correctly [due to MatFactorInfo] 3419 3420 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`, 3421 `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3422 @*/ 3423 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info) 3424 { 3425 PetscFunctionBegin; 3426 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3427 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2); 3428 if (info) PetscValidPointer(info, 3); 3429 PetscValidType(mat, 1); 3430 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3431 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3432 MatCheckPreallocated(mat, 1); 3433 PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0)); 3434 PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info)); 3435 PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0)); 3436 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3437 PetscFunctionReturn(PETSC_SUCCESS); 3438 } 3439 3440 /*@ 3441 MatQRFactorSymbolic - Performs symbolic QR factorization of matrix. 3442 Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`. 3443 3444 Collective 3445 3446 Input Parameters: 3447 + fact - the factor matrix obtained with `MatGetFactor()` 3448 . mat - the matrix 3449 . col - column permutation 3450 - info - options for factorization, includes 3451 .vb 3452 fill - expected fill as ratio of original fill. 3453 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3454 Run with the option -info to determine an optimal value to use 3455 .ve 3456 3457 Level: developer 3458 3459 Note: 3460 Most users should employ the `KSP` interface for linear solvers 3461 instead of working directly with matrix algebra routines such as this. 3462 See, e.g., `KSPCreate()`. 3463 3464 Developer Note: 3465 The Fortran interface is not autogenerated as the 3466 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3467 3468 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3469 @*/ 3470 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info) 3471 { 3472 MatFactorInfo tinfo; 3473 3474 PetscFunctionBegin; 3475 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3476 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3477 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3478 if (info) PetscValidPointer(info, 4); 3479 PetscValidType(fact, 1); 3480 PetscValidType(mat, 2); 3481 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3482 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3483 MatCheckPreallocated(mat, 2); 3484 if (!info) { 3485 PetscCall(MatFactorInfoInitialize(&tinfo)); 3486 info = &tinfo; 3487 } 3488 3489 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3490 PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info)); 3491 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3492 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3493 PetscFunctionReturn(PETSC_SUCCESS); 3494 } 3495 3496 /*@ 3497 MatQRFactorNumeric - Performs numeric QR factorization of a matrix. 3498 Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`. 3499 3500 Collective 3501 3502 Input Parameters: 3503 + fact - the factor matrix obtained with `MatGetFactor()` 3504 . mat - the matrix 3505 - info - options for factorization 3506 3507 Level: developer 3508 3509 Notes: 3510 See `MatQRFactor()` for in-place factorization. 3511 3512 Most users should employ the `KSP` interface for linear solvers 3513 instead of working directly with matrix algebra routines such as this. 3514 See, e.g., `KSPCreate()`. 3515 3516 Developer Note: 3517 The Fortran interface is not autogenerated as the 3518 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3519 3520 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()` 3521 @*/ 3522 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3523 { 3524 MatFactorInfo tinfo; 3525 3526 PetscFunctionBegin; 3527 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3528 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3529 PetscValidType(fact, 1); 3530 PetscValidType(mat, 2); 3531 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3532 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, 3533 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3534 3535 MatCheckPreallocated(mat, 2); 3536 if (!info) { 3537 PetscCall(MatFactorInfoInitialize(&tinfo)); 3538 info = &tinfo; 3539 } 3540 3541 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3542 else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0)); 3543 PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info)); 3544 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3545 else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0)); 3546 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3547 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3548 PetscFunctionReturn(PETSC_SUCCESS); 3549 } 3550 3551 /*@ 3552 MatSolve - Solves A x = b, given a factored matrix. 3553 3554 Neighbor-wise Collective 3555 3556 Input Parameters: 3557 + mat - the factored matrix 3558 - b - the right-hand-side vector 3559 3560 Output Parameter: 3561 . x - the result vector 3562 3563 Level: developer 3564 3565 Notes: 3566 The vectors `b` and `x` cannot be the same. I.e., one cannot 3567 call `MatSolve`(A,x,x). 3568 3569 Most users should employ the `KSP` interface for linear solvers 3570 instead of working directly with matrix algebra routines such as this. 3571 See, e.g., `KSPCreate()`. 3572 3573 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3574 @*/ 3575 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x) 3576 { 3577 PetscFunctionBegin; 3578 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3579 PetscValidType(mat, 1); 3580 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3581 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3582 PetscCheckSameComm(mat, 1, b, 2); 3583 PetscCheckSameComm(mat, 1, x, 3); 3584 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3585 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); 3586 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); 3587 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); 3588 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3589 MatCheckPreallocated(mat, 1); 3590 3591 PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0)); 3592 if (mat->factorerrortype) { 3593 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3594 PetscCall(VecSetInf(x)); 3595 } else PetscUseTypeMethod(mat, solve, b, x); 3596 PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0)); 3597 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3598 PetscFunctionReturn(PETSC_SUCCESS); 3599 } 3600 3601 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans) 3602 { 3603 Vec b, x; 3604 PetscInt N, i; 3605 PetscErrorCode (*f)(Mat, Vec, Vec); 3606 PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE; 3607 3608 PetscFunctionBegin; 3609 if (A->factorerrortype) { 3610 PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype)); 3611 PetscCall(MatSetInf(X)); 3612 PetscFunctionReturn(PETSC_SUCCESS); 3613 } 3614 f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose; 3615 PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 3616 PetscCall(MatBoundToCPU(A, &Abound)); 3617 if (!Abound) { 3618 PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3619 PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3620 } 3621 #if PetscDefined(HAVE_CUDA) 3622 if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B)); 3623 if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X)); 3624 #elif PetscDefined(HAVE_HIP) 3625 if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B)); 3626 if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X)); 3627 #endif 3628 PetscCall(MatGetSize(B, NULL, &N)); 3629 for (i = 0; i < N; i++) { 3630 PetscCall(MatDenseGetColumnVecRead(B, i, &b)); 3631 PetscCall(MatDenseGetColumnVecWrite(X, i, &x)); 3632 PetscCall((*f)(A, b, x)); 3633 PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x)); 3634 PetscCall(MatDenseRestoreColumnVecRead(B, i, &b)); 3635 } 3636 if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B)); 3637 if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X)); 3638 PetscFunctionReturn(PETSC_SUCCESS); 3639 } 3640 3641 /*@ 3642 MatMatSolve - Solves A X = B, given a factored matrix. 3643 3644 Neighbor-wise Collective 3645 3646 Input Parameters: 3647 + A - the factored matrix 3648 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS) 3649 3650 Output Parameter: 3651 . X - the result matrix (dense matrix) 3652 3653 Level: developer 3654 3655 Note: 3656 If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`; 3657 otherwise, `B` and `X` cannot be the same. 3658 3659 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3660 @*/ 3661 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X) 3662 { 3663 PetscFunctionBegin; 3664 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3665 PetscValidType(A, 1); 3666 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3667 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3668 PetscCheckSameComm(A, 1, B, 2); 3669 PetscCheckSameComm(A, 1, X, 3); 3670 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); 3671 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); 3672 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"); 3673 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3674 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3675 MatCheckPreallocated(A, 1); 3676 3677 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3678 if (!A->ops->matsolve) { 3679 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name)); 3680 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE)); 3681 } else PetscUseTypeMethod(A, matsolve, B, X); 3682 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3683 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3684 PetscFunctionReturn(PETSC_SUCCESS); 3685 } 3686 3687 /*@ 3688 MatMatSolveTranspose - Solves A^T X = B, given a factored matrix. 3689 3690 Neighbor-wise Collective 3691 3692 Input Parameters: 3693 + A - the factored matrix 3694 - B - the right-hand-side matrix (`MATDENSE` matrix) 3695 3696 Output Parameter: 3697 . X - the result matrix (dense matrix) 3698 3699 Level: developer 3700 3701 Note: 3702 The matrices `B` and `X` cannot be the same. I.e., one cannot 3703 call `MatMatSolveTranspose`(A,X,X). 3704 3705 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()` 3706 @*/ 3707 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X) 3708 { 3709 PetscFunctionBegin; 3710 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3711 PetscValidType(A, 1); 3712 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3713 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3714 PetscCheckSameComm(A, 1, B, 2); 3715 PetscCheckSameComm(A, 1, X, 3); 3716 PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3717 PetscCheck(A->cmap->N == X->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat X: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->cmap->N, X->rmap->N); 3718 PetscCheck(A->rmap->N == B->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat B: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->N, B->rmap->N); 3719 PetscCheck(A->rmap->n == B->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat A,Mat B: local dim %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->n, B->rmap->n); 3720 PetscCheck(X->cmap->N >= B->cmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Solution matrix must have same number of columns as rhs matrix"); 3721 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3722 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3723 MatCheckPreallocated(A, 1); 3724 3725 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3726 if (!A->ops->matsolvetranspose) { 3727 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name)); 3728 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE)); 3729 } else PetscUseTypeMethod(A, matsolvetranspose, B, X); 3730 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3731 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3732 PetscFunctionReturn(PETSC_SUCCESS); 3733 } 3734 3735 /*@ 3736 MatMatTransposeSolve - Solves A X = B^T, given a factored matrix. 3737 3738 Neighbor-wise Collective 3739 3740 Input Parameters: 3741 + A - the factored matrix 3742 - Bt - the transpose of right-hand-side matrix as a `MATDENSE` 3743 3744 Output Parameter: 3745 . X - the result matrix (dense matrix) 3746 3747 Level: developer 3748 3749 Note: 3750 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 3751 format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`. 3752 3753 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3754 @*/ 3755 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X) 3756 { 3757 PetscFunctionBegin; 3758 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3759 PetscValidType(A, 1); 3760 PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2); 3761 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3762 PetscCheckSameComm(A, 1, Bt, 2); 3763 PetscCheckSameComm(A, 1, X, 3); 3764 3765 PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3766 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); 3767 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); 3768 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"); 3769 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3770 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3771 MatCheckPreallocated(A, 1); 3772 3773 PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0)); 3774 PetscUseTypeMethod(A, mattransposesolve, Bt, X); 3775 PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0)); 3776 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3777 PetscFunctionReturn(PETSC_SUCCESS); 3778 } 3779 3780 /*@ 3781 MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or 3782 U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U, 3783 3784 Neighbor-wise Collective 3785 3786 Input Parameters: 3787 + mat - the factored matrix 3788 - b - the right-hand-side vector 3789 3790 Output Parameter: 3791 . x - the result vector 3792 3793 Level: developer 3794 3795 Notes: 3796 `MatSolve()` should be used for most applications, as it performs 3797 a forward solve followed by a backward solve. 3798 3799 The vectors `b` and `x` cannot be the same, i.e., one cannot 3800 call `MatForwardSolve`(A,x,x). 3801 3802 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3803 the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet. 3804 `MatForwardSolve()` solves U^T*D y = b, and 3805 `MatBackwardSolve()` solves U x = y. 3806 Thus they do not provide a symmetric preconditioner. 3807 3808 .seealso: [](chapter_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatBackwardSolve()` 3809 @*/ 3810 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x) 3811 { 3812 PetscFunctionBegin; 3813 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3814 PetscValidType(mat, 1); 3815 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3816 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3817 PetscCheckSameComm(mat, 1, b, 2); 3818 PetscCheckSameComm(mat, 1, x, 3); 3819 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3820 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); 3821 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); 3822 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); 3823 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3824 MatCheckPreallocated(mat, 1); 3825 3826 PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0)); 3827 PetscUseTypeMethod(mat, forwardsolve, b, x); 3828 PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0)); 3829 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3830 PetscFunctionReturn(PETSC_SUCCESS); 3831 } 3832 3833 /*@ 3834 MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU. 3835 D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U, 3836 3837 Neighbor-wise Collective 3838 3839 Input Parameters: 3840 + mat - the factored matrix 3841 - b - the right-hand-side vector 3842 3843 Output Parameter: 3844 . x - the result vector 3845 3846 Level: developer 3847 3848 Notes: 3849 `MatSolve()` should be used for most applications, as it performs 3850 a forward solve followed by a backward solve. 3851 3852 The vectors `b` and `x` cannot be the same. I.e., one cannot 3853 call `MatBackwardSolve`(A,x,x). 3854 3855 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3856 the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet. 3857 `MatForwardSolve()` solves U^T*D y = b, and 3858 `MatBackwardSolve()` solves U x = y. 3859 Thus they do not provide a symmetric preconditioner. 3860 3861 .seealso: [](chapter_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatForwardSolve()` 3862 @*/ 3863 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x) 3864 { 3865 PetscFunctionBegin; 3866 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3867 PetscValidType(mat, 1); 3868 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3869 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3870 PetscCheckSameComm(mat, 1, b, 2); 3871 PetscCheckSameComm(mat, 1, x, 3); 3872 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3873 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); 3874 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); 3875 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); 3876 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3877 MatCheckPreallocated(mat, 1); 3878 3879 PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0)); 3880 PetscUseTypeMethod(mat, backwardsolve, b, x); 3881 PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0)); 3882 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3883 PetscFunctionReturn(PETSC_SUCCESS); 3884 } 3885 3886 /*@ 3887 MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix. 3888 3889 Neighbor-wise Collective 3890 3891 Input Parameters: 3892 + mat - the factored matrix 3893 . b - the right-hand-side vector 3894 - y - the vector to be added to 3895 3896 Output Parameter: 3897 . x - the result vector 3898 3899 Level: developer 3900 3901 Note: 3902 The vectors `b` and `x` cannot be the same. I.e., one cannot 3903 call `MatSolveAdd`(A,x,y,x). 3904 3905 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3906 @*/ 3907 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x) 3908 { 3909 PetscScalar one = 1.0; 3910 Vec tmp; 3911 3912 PetscFunctionBegin; 3913 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3914 PetscValidType(mat, 1); 3915 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 3916 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3917 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 3918 PetscCheckSameComm(mat, 1, b, 2); 3919 PetscCheckSameComm(mat, 1, y, 3); 3920 PetscCheckSameComm(mat, 1, x, 4); 3921 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3922 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); 3923 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); 3924 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); 3925 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); 3926 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); 3927 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3928 MatCheckPreallocated(mat, 1); 3929 3930 PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y)); 3931 if (mat->factorerrortype) { 3932 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3933 PetscCall(VecSetInf(x)); 3934 } else if (mat->ops->solveadd) { 3935 PetscUseTypeMethod(mat, solveadd, b, y, x); 3936 } else { 3937 /* do the solve then the add manually */ 3938 if (x != y) { 3939 PetscCall(MatSolve(mat, b, x)); 3940 PetscCall(VecAXPY(x, one, y)); 3941 } else { 3942 PetscCall(VecDuplicate(x, &tmp)); 3943 PetscCall(VecCopy(x, tmp)); 3944 PetscCall(MatSolve(mat, b, x)); 3945 PetscCall(VecAXPY(x, one, tmp)); 3946 PetscCall(VecDestroy(&tmp)); 3947 } 3948 } 3949 PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y)); 3950 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3951 PetscFunctionReturn(PETSC_SUCCESS); 3952 } 3953 3954 /*@ 3955 MatSolveTranspose - Solves A' x = b, given a factored matrix. 3956 3957 Neighbor-wise Collective 3958 3959 Input Parameters: 3960 + mat - the factored matrix 3961 - b - the right-hand-side vector 3962 3963 Output Parameter: 3964 . x - the result vector 3965 3966 Level: developer 3967 3968 Notes: 3969 The vectors `b` and `x` cannot be the same. I.e., one cannot 3970 call `MatSolveTranspose`(A,x,x). 3971 3972 Most users should employ the `KSP` interface for linear solvers 3973 instead of working directly with matrix algebra routines such as this. 3974 See, e.g., `KSPCreate()`. 3975 3976 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()` 3977 @*/ 3978 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x) 3979 { 3980 PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose; 3981 3982 PetscFunctionBegin; 3983 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3984 PetscValidType(mat, 1); 3985 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3986 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3987 PetscCheckSameComm(mat, 1, b, 2); 3988 PetscCheckSameComm(mat, 1, x, 3); 3989 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3990 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); 3991 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); 3992 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3993 MatCheckPreallocated(mat, 1); 3994 PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0)); 3995 if (mat->factorerrortype) { 3996 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3997 PetscCall(VecSetInf(x)); 3998 } else { 3999 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name); 4000 PetscCall((*f)(mat, b, x)); 4001 } 4002 PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0)); 4003 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4004 PetscFunctionReturn(PETSC_SUCCESS); 4005 } 4006 4007 /*@ 4008 MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a 4009 factored matrix. 4010 4011 Neighbor-wise Collective 4012 4013 Input Parameters: 4014 + mat - the factored matrix 4015 . b - the right-hand-side vector 4016 - y - the vector to be added to 4017 4018 Output Parameter: 4019 . x - the result vector 4020 4021 Level: developer 4022 4023 Note: 4024 The vectors `b` and `x` cannot be the same. I.e., one cannot 4025 call `MatSolveTransposeAdd`(A,x,y,x). 4026 4027 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()` 4028 @*/ 4029 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x) 4030 { 4031 PetscScalar one = 1.0; 4032 Vec tmp; 4033 PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd; 4034 4035 PetscFunctionBegin; 4036 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4037 PetscValidType(mat, 1); 4038 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4039 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4040 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4041 PetscCheckSameComm(mat, 1, b, 2); 4042 PetscCheckSameComm(mat, 1, y, 3); 4043 PetscCheckSameComm(mat, 1, x, 4); 4044 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4045 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); 4046 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); 4047 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); 4048 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); 4049 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4050 MatCheckPreallocated(mat, 1); 4051 4052 PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y)); 4053 if (mat->factorerrortype) { 4054 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4055 PetscCall(VecSetInf(x)); 4056 } else if (f) { 4057 PetscCall((*f)(mat, b, y, x)); 4058 } else { 4059 /* do the solve then the add manually */ 4060 if (x != y) { 4061 PetscCall(MatSolveTranspose(mat, b, x)); 4062 PetscCall(VecAXPY(x, one, y)); 4063 } else { 4064 PetscCall(VecDuplicate(x, &tmp)); 4065 PetscCall(VecCopy(x, tmp)); 4066 PetscCall(MatSolveTranspose(mat, b, x)); 4067 PetscCall(VecAXPY(x, one, tmp)); 4068 PetscCall(VecDestroy(&tmp)); 4069 } 4070 } 4071 PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y)); 4072 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4073 PetscFunctionReturn(PETSC_SUCCESS); 4074 } 4075 4076 /*@ 4077 MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps. 4078 4079 Neighbor-wise Collective 4080 4081 Input Parameters: 4082 + mat - the matrix 4083 . b - the right hand side 4084 . omega - the relaxation factor 4085 . flag - flag indicating the type of SOR (see below) 4086 . shift - diagonal shift 4087 . its - the number of iterations 4088 - lits - the number of local iterations 4089 4090 Output Parameter: 4091 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess) 4092 4093 SOR Flags: 4094 + `SOR_FORWARD_SWEEP` - forward SOR 4095 . `SOR_BACKWARD_SWEEP` - backward SOR 4096 . `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR) 4097 . `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR 4098 . `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR 4099 . `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR 4100 . `SOR_EISENSTAT` - SOR with Eisenstat trick 4101 . `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies 4102 upper/lower triangular part of matrix to 4103 vector (with omega) 4104 - `SOR_ZERO_INITIAL_GUESS` - zero initial guess 4105 4106 Level: developer 4107 4108 Notes: 4109 `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and 4110 `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings 4111 on each processor. 4112 4113 Application programmers will not generally use `MatSOR()` directly, 4114 but instead will employ the `KSP`/`PC` interface. 4115 4116 For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing 4117 4118 Most users should employ the `KSP` interface for linear solvers 4119 instead of working directly with matrix algebra routines such as this. 4120 See, e.g., `KSPCreate()`. 4121 4122 Vectors `x` and `b` CANNOT be the same 4123 4124 The flags are implemented as bitwise inclusive or operations. 4125 For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`) 4126 to specify a zero initial guess for SSOR. 4127 4128 Developer Note: 4129 We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes 4130 4131 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()` 4132 @*/ 4133 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x) 4134 { 4135 PetscFunctionBegin; 4136 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4137 PetscValidType(mat, 1); 4138 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4139 PetscValidHeaderSpecific(x, VEC_CLASSID, 8); 4140 PetscCheckSameComm(mat, 1, b, 2); 4141 PetscCheckSameComm(mat, 1, x, 8); 4142 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4143 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4144 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); 4145 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); 4146 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); 4147 PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its); 4148 PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits); 4149 PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same"); 4150 4151 MatCheckPreallocated(mat, 1); 4152 PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0)); 4153 PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x); 4154 PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0)); 4155 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4156 PetscFunctionReturn(PETSC_SUCCESS); 4157 } 4158 4159 /* 4160 Default matrix copy routine. 4161 */ 4162 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str) 4163 { 4164 PetscInt i, rstart = 0, rend = 0, nz; 4165 const PetscInt *cwork; 4166 const PetscScalar *vwork; 4167 4168 PetscFunctionBegin; 4169 if (B->assembled) PetscCall(MatZeroEntries(B)); 4170 if (str == SAME_NONZERO_PATTERN) { 4171 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 4172 for (i = rstart; i < rend; i++) { 4173 PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork)); 4174 PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES)); 4175 PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork)); 4176 } 4177 } else { 4178 PetscCall(MatAYPX(B, 0.0, A, str)); 4179 } 4180 PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 4181 PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 4182 PetscFunctionReturn(PETSC_SUCCESS); 4183 } 4184 4185 /*@ 4186 MatCopy - Copies a matrix to another matrix. 4187 4188 Collective 4189 4190 Input Parameters: 4191 + A - the matrix 4192 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN` 4193 4194 Output Parameter: 4195 . B - where the copy is put 4196 4197 Level: intermediate 4198 4199 Notes: 4200 If you use `SAME_NONZERO_PATTERN` then the two matrices must have the same nonzero pattern or the routine will crash. 4201 4202 `MatCopy()` copies the matrix entries of a matrix to another existing 4203 matrix (after first zeroing the second matrix). A related routine is 4204 `MatConvert()`, which first creates a new matrix and then copies the data. 4205 4206 .seealso: [](chapter_matrices), `Mat`, `MatConvert()`, `MatDuplicate()` 4207 @*/ 4208 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str) 4209 { 4210 PetscInt i; 4211 4212 PetscFunctionBegin; 4213 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 4214 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 4215 PetscValidType(A, 1); 4216 PetscValidType(B, 2); 4217 PetscCheckSameComm(A, 1, B, 2); 4218 MatCheckPreallocated(B, 2); 4219 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4220 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4221 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, 4222 A->cmap->N, B->cmap->N); 4223 MatCheckPreallocated(A, 1); 4224 if (A == B) PetscFunctionReturn(PETSC_SUCCESS); 4225 4226 PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0)); 4227 if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str); 4228 else PetscCall(MatCopy_Basic(A, B, str)); 4229 4230 B->stencil.dim = A->stencil.dim; 4231 B->stencil.noc = A->stencil.noc; 4232 for (i = 0; i <= A->stencil.dim; i++) { 4233 B->stencil.dims[i] = A->stencil.dims[i]; 4234 B->stencil.starts[i] = A->stencil.starts[i]; 4235 } 4236 4237 PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0)); 4238 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4239 PetscFunctionReturn(PETSC_SUCCESS); 4240 } 4241 4242 /*@C 4243 MatConvert - Converts a matrix to another matrix, either of the same 4244 or different type. 4245 4246 Collective 4247 4248 Input Parameters: 4249 + mat - the matrix 4250 . newtype - new matrix type. Use `MATSAME` to create a new matrix of the 4251 same type as the original matrix. 4252 - reuse - denotes if the destination matrix is to be created or reused. 4253 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 4254 `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). 4255 4256 Output Parameter: 4257 . M - pointer to place new matrix 4258 4259 Level: intermediate 4260 4261 Notes: 4262 `MatConvert()` first creates a new matrix and then copies the data from 4263 the first matrix. A related routine is `MatCopy()`, which copies the matrix 4264 entries of one matrix to another already existing matrix context. 4265 4266 Cannot be used to convert a sequential matrix to parallel or parallel to sequential, 4267 the MPI communicator of the generated matrix is always the same as the communicator 4268 of the input matrix. 4269 4270 .seealso: [](chapter_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 4271 @*/ 4272 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M) 4273 { 4274 PetscBool sametype, issame, flg; 4275 PetscBool3 issymmetric, ishermitian; 4276 char convname[256], mtype[256]; 4277 Mat B; 4278 4279 PetscFunctionBegin; 4280 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4281 PetscValidType(mat, 1); 4282 PetscValidPointer(M, 4); 4283 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4284 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4285 MatCheckPreallocated(mat, 1); 4286 4287 PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg)); 4288 if (flg) newtype = mtype; 4289 4290 PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype)); 4291 PetscCall(PetscStrcmp(newtype, "same", &issame)); 4292 PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix"); 4293 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"); 4294 4295 if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) { 4296 PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4297 PetscFunctionReturn(PETSC_SUCCESS); 4298 } 4299 4300 /* Cache Mat options because some converters use MatHeaderReplace */ 4301 issymmetric = mat->symmetric; 4302 ishermitian = mat->hermitian; 4303 4304 if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) { 4305 PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4306 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4307 } else { 4308 PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL; 4309 const char *prefix[3] = {"seq", "mpi", ""}; 4310 PetscInt i; 4311 /* 4312 Order of precedence: 4313 0) See if newtype is a superclass of the current matrix. 4314 1) See if a specialized converter is known to the current matrix. 4315 2) See if a specialized converter is known to the desired matrix class. 4316 3) See if a good general converter is registered for the desired class 4317 (as of 6/27/03 only MATMPIADJ falls into this category). 4318 4) See if a good general converter is known for the current matrix. 4319 5) Use a really basic converter. 4320 */ 4321 4322 /* 0) See if newtype is a superclass of the current matrix. 4323 i.e mat is mpiaij and newtype is aij */ 4324 for (i = 0; i < 2; i++) { 4325 PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname))); 4326 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4327 PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg)); 4328 PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg)); 4329 if (flg) { 4330 if (reuse == MAT_INPLACE_MATRIX) { 4331 PetscCall(PetscInfo(mat, "Early return\n")); 4332 PetscFunctionReturn(PETSC_SUCCESS); 4333 } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) { 4334 PetscCall(PetscInfo(mat, "Calling MatDuplicate\n")); 4335 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4336 PetscFunctionReturn(PETSC_SUCCESS); 4337 } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) { 4338 PetscCall(PetscInfo(mat, "Calling MatCopy\n")); 4339 PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN)); 4340 PetscFunctionReturn(PETSC_SUCCESS); 4341 } 4342 } 4343 } 4344 /* 1) See if a specialized converter is known to the current matrix and the desired class */ 4345 for (i = 0; i < 3; i++) { 4346 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4347 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4348 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4349 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4350 PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname))); 4351 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4352 PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv)); 4353 PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv)); 4354 if (conv) goto foundconv; 4355 } 4356 4357 /* 2) See if a specialized converter is known to the desired matrix class. */ 4358 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B)); 4359 PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 4360 PetscCall(MatSetType(B, newtype)); 4361 for (i = 0; i < 3; i++) { 4362 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4363 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4364 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4365 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4366 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4367 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4368 PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv)); 4369 PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv)); 4370 if (conv) { 4371 PetscCall(MatDestroy(&B)); 4372 goto foundconv; 4373 } 4374 } 4375 4376 /* 3) See if a good general converter is registered for the desired class */ 4377 conv = B->ops->convertfrom; 4378 PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv)); 4379 PetscCall(MatDestroy(&B)); 4380 if (conv) goto foundconv; 4381 4382 /* 4) See if a good general converter is known for the current matrix */ 4383 if (mat->ops->convert) conv = mat->ops->convert; 4384 PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv)); 4385 if (conv) goto foundconv; 4386 4387 /* 5) Use a really basic converter. */ 4388 PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n")); 4389 conv = MatConvert_Basic; 4390 4391 foundconv: 4392 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4393 PetscCall((*conv)(mat, newtype, reuse, M)); 4394 if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) { 4395 /* the block sizes must be same if the mappings are copied over */ 4396 (*M)->rmap->bs = mat->rmap->bs; 4397 (*M)->cmap->bs = mat->cmap->bs; 4398 PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping)); 4399 PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping)); 4400 (*M)->rmap->mapping = mat->rmap->mapping; 4401 (*M)->cmap->mapping = mat->cmap->mapping; 4402 } 4403 (*M)->stencil.dim = mat->stencil.dim; 4404 (*M)->stencil.noc = mat->stencil.noc; 4405 for (i = 0; i <= mat->stencil.dim; i++) { 4406 (*M)->stencil.dims[i] = mat->stencil.dims[i]; 4407 (*M)->stencil.starts[i] = mat->stencil.starts[i]; 4408 } 4409 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4410 } 4411 PetscCall(PetscObjectStateIncrease((PetscObject)*M)); 4412 4413 /* Copy Mat options */ 4414 if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE)); 4415 else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE)); 4416 if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE)); 4417 else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE)); 4418 PetscFunctionReturn(PETSC_SUCCESS); 4419 } 4420 4421 /*@C 4422 MatFactorGetSolverType - Returns name of the package providing the factorization routines 4423 4424 Not Collective 4425 4426 Input Parameter: 4427 . mat - the matrix, must be a factored matrix 4428 4429 Output Parameter: 4430 . type - the string name of the package (do not free this string) 4431 4432 Level: intermediate 4433 4434 Fortran Note: 4435 Pass in an empty string and the package name will be copied into it. Make sure the string is long enough. 4436 4437 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()` 4438 @*/ 4439 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type) 4440 { 4441 PetscErrorCode (*conv)(Mat, MatSolverType *); 4442 4443 PetscFunctionBegin; 4444 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4445 PetscValidType(mat, 1); 4446 PetscValidPointer(type, 2); 4447 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 4448 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv)); 4449 if (conv) PetscCall((*conv)(mat, type)); 4450 else *type = MATSOLVERPETSC; 4451 PetscFunctionReturn(PETSC_SUCCESS); 4452 } 4453 4454 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType; 4455 struct _MatSolverTypeForSpecifcType { 4456 MatType mtype; 4457 /* no entry for MAT_FACTOR_NONE */ 4458 PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *); 4459 MatSolverTypeForSpecifcType next; 4460 }; 4461 4462 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder; 4463 struct _MatSolverTypeHolder { 4464 char *name; 4465 MatSolverTypeForSpecifcType handlers; 4466 MatSolverTypeHolder next; 4467 }; 4468 4469 static MatSolverTypeHolder MatSolverTypeHolders = NULL; 4470 4471 /*@C 4472 MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type 4473 4474 Input Parameters: 4475 + package - name of the package, for example petsc or superlu 4476 . mtype - the matrix type that works with this package 4477 . ftype - the type of factorization supported by the package 4478 - createfactor - routine that will create the factored matrix ready to be used 4479 4480 Level: developer 4481 4482 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()` 4483 @*/ 4484 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *)) 4485 { 4486 MatSolverTypeHolder next = MatSolverTypeHolders, prev = NULL; 4487 PetscBool flg; 4488 MatSolverTypeForSpecifcType inext, iprev = NULL; 4489 4490 PetscFunctionBegin; 4491 PetscCall(MatInitializePackage()); 4492 if (!next) { 4493 PetscCall(PetscNew(&MatSolverTypeHolders)); 4494 PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name)); 4495 PetscCall(PetscNew(&MatSolverTypeHolders->handlers)); 4496 PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype)); 4497 MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor; 4498 PetscFunctionReturn(PETSC_SUCCESS); 4499 } 4500 while (next) { 4501 PetscCall(PetscStrcasecmp(package, next->name, &flg)); 4502 if (flg) { 4503 PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers"); 4504 inext = next->handlers; 4505 while (inext) { 4506 PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg)); 4507 if (flg) { 4508 inext->createfactor[(int)ftype - 1] = createfactor; 4509 PetscFunctionReturn(PETSC_SUCCESS); 4510 } 4511 iprev = inext; 4512 inext = inext->next; 4513 } 4514 PetscCall(PetscNew(&iprev->next)); 4515 PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype)); 4516 iprev->next->createfactor[(int)ftype - 1] = createfactor; 4517 PetscFunctionReturn(PETSC_SUCCESS); 4518 } 4519 prev = next; 4520 next = next->next; 4521 } 4522 PetscCall(PetscNew(&prev->next)); 4523 PetscCall(PetscStrallocpy(package, &prev->next->name)); 4524 PetscCall(PetscNew(&prev->next->handlers)); 4525 PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype)); 4526 prev->next->handlers->createfactor[(int)ftype - 1] = createfactor; 4527 PetscFunctionReturn(PETSC_SUCCESS); 4528 } 4529 4530 /*@C 4531 MatSolverTypeGet - Gets the function that creates the factor matrix if it exist 4532 4533 Input Parameters: 4534 + type - name of the package, for example petsc or superlu 4535 . ftype - the type of factorization supported by the type 4536 - mtype - the matrix type that works with this type 4537 4538 Output Parameters: 4539 + foundtype - `PETSC_TRUE` if the type was registered 4540 . foundmtype - `PETSC_TRUE` if the type supports the requested mtype 4541 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found 4542 4543 Level: developer 4544 4545 .seealso: [](chapter_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()` 4546 @*/ 4547 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *)) 4548 { 4549 MatSolverTypeHolder next = MatSolverTypeHolders; 4550 PetscBool flg; 4551 MatSolverTypeForSpecifcType inext; 4552 4553 PetscFunctionBegin; 4554 if (foundtype) *foundtype = PETSC_FALSE; 4555 if (foundmtype) *foundmtype = PETSC_FALSE; 4556 if (createfactor) *createfactor = NULL; 4557 4558 if (type) { 4559 while (next) { 4560 PetscCall(PetscStrcasecmp(type, next->name, &flg)); 4561 if (flg) { 4562 if (foundtype) *foundtype = PETSC_TRUE; 4563 inext = next->handlers; 4564 while (inext) { 4565 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4566 if (flg) { 4567 if (foundmtype) *foundmtype = PETSC_TRUE; 4568 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4569 PetscFunctionReturn(PETSC_SUCCESS); 4570 } 4571 inext = inext->next; 4572 } 4573 } 4574 next = next->next; 4575 } 4576 } else { 4577 while (next) { 4578 inext = next->handlers; 4579 while (inext) { 4580 PetscCall(PetscStrcmp(mtype, inext->mtype, &flg)); 4581 if (flg && inext->createfactor[(int)ftype - 1]) { 4582 if (foundtype) *foundtype = PETSC_TRUE; 4583 if (foundmtype) *foundmtype = PETSC_TRUE; 4584 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4585 PetscFunctionReturn(PETSC_SUCCESS); 4586 } 4587 inext = inext->next; 4588 } 4589 next = next->next; 4590 } 4591 /* try with base classes inext->mtype */ 4592 next = MatSolverTypeHolders; 4593 while (next) { 4594 inext = next->handlers; 4595 while (inext) { 4596 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4597 if (flg && inext->createfactor[(int)ftype - 1]) { 4598 if (foundtype) *foundtype = PETSC_TRUE; 4599 if (foundmtype) *foundmtype = PETSC_TRUE; 4600 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4601 PetscFunctionReturn(PETSC_SUCCESS); 4602 } 4603 inext = inext->next; 4604 } 4605 next = next->next; 4606 } 4607 } 4608 PetscFunctionReturn(PETSC_SUCCESS); 4609 } 4610 4611 PetscErrorCode MatSolverTypeDestroy(void) 4612 { 4613 MatSolverTypeHolder next = MatSolverTypeHolders, prev; 4614 MatSolverTypeForSpecifcType inext, iprev; 4615 4616 PetscFunctionBegin; 4617 while (next) { 4618 PetscCall(PetscFree(next->name)); 4619 inext = next->handlers; 4620 while (inext) { 4621 PetscCall(PetscFree(inext->mtype)); 4622 iprev = inext; 4623 inext = inext->next; 4624 PetscCall(PetscFree(iprev)); 4625 } 4626 prev = next; 4627 next = next->next; 4628 PetscCall(PetscFree(prev)); 4629 } 4630 MatSolverTypeHolders = NULL; 4631 PetscFunctionReturn(PETSC_SUCCESS); 4632 } 4633 4634 /*@C 4635 MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4636 4637 Logically Collective 4638 4639 Input Parameter: 4640 . mat - the matrix 4641 4642 Output Parameter: 4643 . flg - `PETSC_TRUE` if uses the ordering 4644 4645 Level: developer 4646 4647 Note: 4648 Most internal PETSc factorizations use the ordering passed to the factorization routine but external 4649 packages do not, thus we want to skip generating the ordering when it is not needed or used. 4650 4651 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4652 @*/ 4653 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg) 4654 { 4655 PetscFunctionBegin; 4656 *flg = mat->canuseordering; 4657 PetscFunctionReturn(PETSC_SUCCESS); 4658 } 4659 4660 /*@C 4661 MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object 4662 4663 Logically Collective 4664 4665 Input Parameters: 4666 + mat - the matrix obtained with `MatGetFactor()` 4667 - ftype - the factorization type to be used 4668 4669 Output Parameter: 4670 . otype - the preferred ordering type 4671 4672 Level: developer 4673 4674 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4675 @*/ 4676 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype) 4677 { 4678 PetscFunctionBegin; 4679 *otype = mat->preferredordering[ftype]; 4680 PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering"); 4681 PetscFunctionReturn(PETSC_SUCCESS); 4682 } 4683 4684 /*@C 4685 MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic() 4686 4687 Collective 4688 4689 Input Parameters: 4690 + mat - the matrix 4691 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4692 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4693 4694 Output Parameter: 4695 . f - the factor matrix used with MatXXFactorSymbolic() calls. Can be `NULL` in some cases, see notes below. 4696 4697 Options Database Key: 4698 . -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory. 4699 One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices. 4700 4701 Level: intermediate 4702 4703 Notes: 4704 The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization 4705 types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime. 4706 4707 Users usually access the factorization solvers via `KSP` 4708 4709 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4710 such as pastix, superlu, mumps etc. 4711 4712 PETSc must have been ./configure to use the external solver, using the option --download-package 4713 4714 Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption 4715 where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set 4716 call `MatSetOptionsPrefixFactor()` on the originating matrix or `MatSetOptionsPrefix()` on the resulting factor matrix. 4717 4718 Developer Note: 4719 This should actually be called `MatCreateFactor()` since it creates a new factor object 4720 4721 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, 4722 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4723 @*/ 4724 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f) 4725 { 4726 PetscBool foundtype, foundmtype; 4727 PetscErrorCode (*conv)(Mat, MatFactorType, Mat *); 4728 4729 PetscFunctionBegin; 4730 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4731 PetscValidType(mat, 1); 4732 4733 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4734 MatCheckPreallocated(mat, 1); 4735 4736 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv)); 4737 if (!foundtype) { 4738 if (type) { 4739 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], 4740 ((PetscObject)mat)->type_name, type); 4741 } else { 4742 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); 4743 } 4744 } 4745 PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name); 4746 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); 4747 4748 PetscCall((*conv)(mat, ftype, f)); 4749 if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix)); 4750 PetscFunctionReturn(PETSC_SUCCESS); 4751 } 4752 4753 /*@C 4754 MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type 4755 4756 Not Collective 4757 4758 Input Parameters: 4759 + mat - the matrix 4760 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4761 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4762 4763 Output Parameter: 4764 . flg - PETSC_TRUE if the factorization is available 4765 4766 Level: intermediate 4767 4768 Notes: 4769 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4770 such as pastix, superlu, mumps etc. 4771 4772 PETSc must have been ./configure to use the external solver, using the option --download-package 4773 4774 Developer Note: 4775 This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object 4776 4777 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactor()`, `MatSolverTypeRegister()`, 4778 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4779 @*/ 4780 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg) 4781 { 4782 PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *); 4783 4784 PetscFunctionBegin; 4785 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4786 PetscValidType(mat, 1); 4787 PetscValidBoolPointer(flg, 4); 4788 4789 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4790 MatCheckPreallocated(mat, 1); 4791 4792 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv)); 4793 *flg = gconv ? PETSC_TRUE : PETSC_FALSE; 4794 PetscFunctionReturn(PETSC_SUCCESS); 4795 } 4796 4797 /*@ 4798 MatDuplicate - Duplicates a matrix including the non-zero structure. 4799 4800 Collective 4801 4802 Input Parameters: 4803 + mat - the matrix 4804 - op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`. 4805 See the manual page for `MatDuplicateOption()` for an explanation of these options. 4806 4807 Output Parameter: 4808 . M - pointer to place new matrix 4809 4810 Level: intermediate 4811 4812 Notes: 4813 You cannot change the nonzero pattern for the parent or child matrix if you use `MAT_SHARE_NONZERO_PATTERN`. 4814 4815 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. 4816 4817 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 4818 is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated. 4819 User should not use `MatDuplicate()` to create new matrix M if M is intended to be reused as the product of matrix operation. 4820 4821 .seealso: [](chapter_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption` 4822 @*/ 4823 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M) 4824 { 4825 Mat B; 4826 VecType vtype; 4827 PetscInt i; 4828 PetscObject dm, container_h, container_d; 4829 void (*viewf)(void); 4830 4831 PetscFunctionBegin; 4832 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4833 PetscValidType(mat, 1); 4834 PetscValidPointer(M, 3); 4835 PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix"); 4836 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4837 MatCheckPreallocated(mat, 1); 4838 4839 *M = NULL; 4840 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4841 PetscUseTypeMethod(mat, duplicate, op, M); 4842 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4843 B = *M; 4844 4845 PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf)); 4846 if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf)); 4847 PetscCall(MatGetVecType(mat, &vtype)); 4848 PetscCall(MatSetVecType(B, vtype)); 4849 4850 B->stencil.dim = mat->stencil.dim; 4851 B->stencil.noc = mat->stencil.noc; 4852 for (i = 0; i <= mat->stencil.dim; i++) { 4853 B->stencil.dims[i] = mat->stencil.dims[i]; 4854 B->stencil.starts[i] = mat->stencil.starts[i]; 4855 } 4856 4857 B->nooffproczerorows = mat->nooffproczerorows; 4858 B->nooffprocentries = mat->nooffprocentries; 4859 4860 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm)); 4861 if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm)); 4862 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h)); 4863 if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h)); 4864 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d)); 4865 if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d)); 4866 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4867 PetscFunctionReturn(PETSC_SUCCESS); 4868 } 4869 4870 /*@ 4871 MatGetDiagonal - Gets the diagonal of a matrix as a `Vec` 4872 4873 Logically Collective 4874 4875 Input Parameter: 4876 . mat - the matrix 4877 4878 Output Parameter: 4879 . v - the diagonal of the matrix 4880 4881 Level: intermediate 4882 4883 Note: 4884 Currently only correct in parallel for square matrices. 4885 4886 .seealso: [](chapter_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()` 4887 @*/ 4888 PetscErrorCode MatGetDiagonal(Mat mat, Vec v) 4889 { 4890 PetscFunctionBegin; 4891 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4892 PetscValidType(mat, 1); 4893 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4894 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4895 MatCheckPreallocated(mat, 1); 4896 4897 PetscUseTypeMethod(mat, getdiagonal, v); 4898 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4899 PetscFunctionReturn(PETSC_SUCCESS); 4900 } 4901 4902 /*@C 4903 MatGetRowMin - Gets the minimum value (of the real part) of each 4904 row of the matrix 4905 4906 Logically Collective 4907 4908 Input Parameter: 4909 . mat - the matrix 4910 4911 Output Parameters: 4912 + v - the vector for storing the maximums 4913 - idx - the indices of the column found for each row (optional) 4914 4915 Level: intermediate 4916 4917 Note: 4918 The result of this call are the same as if one converted the matrix to dense format 4919 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 4920 4921 This code is only implemented for a couple of matrix formats. 4922 4923 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, 4924 `MatGetRowMax()` 4925 @*/ 4926 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[]) 4927 { 4928 PetscFunctionBegin; 4929 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4930 PetscValidType(mat, 1); 4931 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4932 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4933 4934 if (!mat->cmap->N) { 4935 PetscCall(VecSet(v, PETSC_MAX_REAL)); 4936 if (idx) { 4937 PetscInt i, m = mat->rmap->n; 4938 for (i = 0; i < m; i++) idx[i] = -1; 4939 } 4940 } else { 4941 MatCheckPreallocated(mat, 1); 4942 } 4943 PetscUseTypeMethod(mat, getrowmin, v, idx); 4944 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4945 PetscFunctionReturn(PETSC_SUCCESS); 4946 } 4947 4948 /*@C 4949 MatGetRowMinAbs - Gets the minimum value (in absolute value) of each 4950 row of the matrix 4951 4952 Logically Collective 4953 4954 Input Parameter: 4955 . mat - the matrix 4956 4957 Output Parameters: 4958 + v - the vector for storing the minimums 4959 - idx - the indices of the column found for each row (or `NULL` if not needed) 4960 4961 Level: intermediate 4962 4963 Notes: 4964 if a row is completely empty or has only 0.0 values then the idx[] value for that 4965 row is 0 (the first column). 4966 4967 This code is only implemented for a couple of matrix formats. 4968 4969 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()` 4970 @*/ 4971 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[]) 4972 { 4973 PetscFunctionBegin; 4974 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4975 PetscValidType(mat, 1); 4976 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4977 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4978 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4979 4980 if (!mat->cmap->N) { 4981 PetscCall(VecSet(v, 0.0)); 4982 if (idx) { 4983 PetscInt i, m = mat->rmap->n; 4984 for (i = 0; i < m; i++) idx[i] = -1; 4985 } 4986 } else { 4987 MatCheckPreallocated(mat, 1); 4988 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 4989 PetscUseTypeMethod(mat, getrowminabs, v, idx); 4990 } 4991 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4992 PetscFunctionReturn(PETSC_SUCCESS); 4993 } 4994 4995 /*@C 4996 MatGetRowMax - Gets the maximum value (of the real part) of each 4997 row of the matrix 4998 4999 Logically Collective 5000 5001 Input Parameter: 5002 . mat - the matrix 5003 5004 Output Parameters: 5005 + v - the vector for storing the maximums 5006 - idx - the indices of the column found for each row (optional) 5007 5008 Level: intermediate 5009 5010 Notes: 5011 The result of this call are the same as if one converted the matrix to dense format 5012 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5013 5014 This code is only implemented for a couple of matrix formats. 5015 5016 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5017 @*/ 5018 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[]) 5019 { 5020 PetscFunctionBegin; 5021 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5022 PetscValidType(mat, 1); 5023 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5024 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5025 5026 if (!mat->cmap->N) { 5027 PetscCall(VecSet(v, PETSC_MIN_REAL)); 5028 if (idx) { 5029 PetscInt i, m = mat->rmap->n; 5030 for (i = 0; i < m; i++) idx[i] = -1; 5031 } 5032 } else { 5033 MatCheckPreallocated(mat, 1); 5034 PetscUseTypeMethod(mat, getrowmax, v, idx); 5035 } 5036 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5037 PetscFunctionReturn(PETSC_SUCCESS); 5038 } 5039 5040 /*@C 5041 MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each 5042 row of the matrix 5043 5044 Logically Collective 5045 5046 Input Parameter: 5047 . mat - the matrix 5048 5049 Output Parameters: 5050 + v - the vector for storing the maximums 5051 - idx - the indices of the column found for each row (or `NULL` if not needed) 5052 5053 Level: intermediate 5054 5055 Notes: 5056 if a row is completely empty or has only 0.0 values then the idx[] value for that 5057 row is 0 (the first column). 5058 5059 This code is only implemented for a couple of matrix formats. 5060 5061 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5062 @*/ 5063 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[]) 5064 { 5065 PetscFunctionBegin; 5066 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5067 PetscValidType(mat, 1); 5068 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5069 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5070 5071 if (!mat->cmap->N) { 5072 PetscCall(VecSet(v, 0.0)); 5073 if (idx) { 5074 PetscInt i, m = mat->rmap->n; 5075 for (i = 0; i < m; i++) idx[i] = -1; 5076 } 5077 } else { 5078 MatCheckPreallocated(mat, 1); 5079 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5080 PetscUseTypeMethod(mat, getrowmaxabs, v, idx); 5081 } 5082 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5083 PetscFunctionReturn(PETSC_SUCCESS); 5084 } 5085 5086 /*@ 5087 MatGetRowSum - Gets the sum of each row of the matrix 5088 5089 Logically or Neighborhood Collective 5090 5091 Input Parameter: 5092 . mat - the matrix 5093 5094 Output Parameter: 5095 . v - the vector for storing the sum of rows 5096 5097 Level: intermediate 5098 5099 Notes: 5100 This code is slow since it is not currently specialized for different formats 5101 5102 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()` 5103 @*/ 5104 PetscErrorCode MatGetRowSum(Mat mat, Vec v) 5105 { 5106 Vec ones; 5107 5108 PetscFunctionBegin; 5109 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5110 PetscValidType(mat, 1); 5111 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5112 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5113 MatCheckPreallocated(mat, 1); 5114 PetscCall(MatCreateVecs(mat, &ones, NULL)); 5115 PetscCall(VecSet(ones, 1.)); 5116 PetscCall(MatMult(mat, ones, v)); 5117 PetscCall(VecDestroy(&ones)); 5118 PetscFunctionReturn(PETSC_SUCCESS); 5119 } 5120 5121 /*@ 5122 MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) 5123 when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B) 5124 5125 Collective 5126 5127 Input Parameter: 5128 . mat - the matrix to provide the transpose 5129 5130 Output Parameter: 5131 . 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 5132 5133 Level: advanced 5134 5135 Note: 5136 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 5137 routine allows bypassing that call. 5138 5139 .seealso: [](chapter_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5140 @*/ 5141 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B) 5142 { 5143 PetscContainer rB = NULL; 5144 MatParentState *rb = NULL; 5145 5146 PetscFunctionBegin; 5147 PetscCall(PetscNew(&rb)); 5148 rb->id = ((PetscObject)mat)->id; 5149 rb->state = 0; 5150 PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate)); 5151 PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB)); 5152 PetscCall(PetscContainerSetPointer(rB, rb)); 5153 PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault)); 5154 PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB)); 5155 PetscCall(PetscObjectDereference((PetscObject)rB)); 5156 PetscFunctionReturn(PETSC_SUCCESS); 5157 } 5158 5159 /*@ 5160 MatTranspose - Computes an in-place or out-of-place transpose of a matrix. 5161 5162 Collective 5163 5164 Input Parameters: 5165 + mat - the matrix to transpose 5166 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5167 5168 Output Parameter: 5169 . B - the transpose 5170 5171 Level: intermediate 5172 5173 Notes: 5174 If you use `MAT_INPLACE_MATRIX` then you must pass in &mat for B 5175 5176 `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 5177 transpose, call `MatTransposeSetPrecursor`(mat,B) before calling this routine. 5178 5179 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. 5180 5181 Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed. 5182 5183 If mat is unchanged from the last call this function returns immediately without recomputing the result 5184 5185 If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()` 5186 5187 .seealso: [](chapter_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`, 5188 `MatTransposeSymbolic()`, `MatCreateTranspose()` 5189 @*/ 5190 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B) 5191 { 5192 PetscContainer rB = NULL; 5193 MatParentState *rb = NULL; 5194 5195 PetscFunctionBegin; 5196 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5197 PetscValidType(mat, 1); 5198 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5199 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5200 PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first"); 5201 PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX"); 5202 MatCheckPreallocated(mat, 1); 5203 if (reuse == MAT_REUSE_MATRIX) { 5204 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5205 PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor()."); 5206 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5207 PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5208 if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS); 5209 } 5210 5211 PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0)); 5212 if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) { 5213 PetscUseTypeMethod(mat, transpose, reuse, B); 5214 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5215 } 5216 PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0)); 5217 5218 if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B)); 5219 if (reuse != MAT_INPLACE_MATRIX) { 5220 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5221 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5222 rb->state = ((PetscObject)mat)->state; 5223 rb->nonzerostate = mat->nonzerostate; 5224 } 5225 PetscFunctionReturn(PETSC_SUCCESS); 5226 } 5227 5228 /*@ 5229 MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix. 5230 5231 Collective 5232 5233 Input Parameter: 5234 . A - the matrix to transpose 5235 5236 Output Parameter: 5237 . 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 5238 numerical portion. 5239 5240 Level: intermediate 5241 5242 Note: 5243 This is not supported for many matrix types, use `MatTranspose()` in those cases 5244 5245 .seealso: [](chapter_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5246 @*/ 5247 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B) 5248 { 5249 PetscFunctionBegin; 5250 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5251 PetscValidType(A, 1); 5252 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5253 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5254 PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0)); 5255 PetscUseTypeMethod(A, transposesymbolic, B); 5256 PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0)); 5257 5258 PetscCall(MatTransposeSetPrecursor(A, *B)); 5259 PetscFunctionReturn(PETSC_SUCCESS); 5260 } 5261 5262 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B) 5263 { 5264 PetscContainer rB; 5265 MatParentState *rb; 5266 5267 PetscFunctionBegin; 5268 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5269 PetscValidType(A, 1); 5270 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5271 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5272 PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB)); 5273 PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()"); 5274 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5275 PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5276 PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure"); 5277 PetscFunctionReturn(PETSC_SUCCESS); 5278 } 5279 5280 /*@ 5281 MatIsTranspose - Test whether a matrix is another one's transpose, 5282 or its own, in which case it tests symmetry. 5283 5284 Collective 5285 5286 Input Parameters: 5287 + A - the matrix to test 5288 . B - the matrix to test against, this can equal the first parameter 5289 - tol - tolerance, differences between entries smaller than this are counted as zero 5290 5291 Output Parameter: 5292 . flg - the result 5293 5294 Level: intermediate 5295 5296 Notes: 5297 Only available for `MATAIJ` matrices. 5298 5299 The sequential algorithm has a running time of the order of the number of nonzeros; the parallel 5300 test involves parallel copies of the block-offdiagonal parts of the matrix. 5301 5302 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()` 5303 @*/ 5304 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5305 { 5306 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5307 5308 PetscFunctionBegin; 5309 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5310 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5311 PetscValidBoolPointer(flg, 4); 5312 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f)); 5313 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g)); 5314 *flg = PETSC_FALSE; 5315 if (f && g) { 5316 PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test"); 5317 PetscCall((*f)(A, B, tol, flg)); 5318 } else { 5319 MatType mattype; 5320 5321 PetscCall(MatGetType(f ? B : A, &mattype)); 5322 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype); 5323 } 5324 PetscFunctionReturn(PETSC_SUCCESS); 5325 } 5326 5327 /*@ 5328 MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate. 5329 5330 Collective 5331 5332 Input Parameters: 5333 + mat - the matrix to transpose and complex conjugate 5334 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5335 5336 Output Parameter: 5337 . B - the Hermitian transpose 5338 5339 Level: intermediate 5340 5341 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse` 5342 @*/ 5343 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B) 5344 { 5345 PetscFunctionBegin; 5346 PetscCall(MatTranspose(mat, reuse, B)); 5347 #if defined(PETSC_USE_COMPLEX) 5348 PetscCall(MatConjugate(*B)); 5349 #endif 5350 PetscFunctionReturn(PETSC_SUCCESS); 5351 } 5352 5353 /*@ 5354 MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose, 5355 5356 Collective 5357 5358 Input Parameters: 5359 + A - the matrix to test 5360 . B - the matrix to test against, this can equal the first parameter 5361 - tol - tolerance, differences between entries smaller than this are counted as zero 5362 5363 Output Parameter: 5364 . flg - the result 5365 5366 Level: intermediate 5367 5368 Notes: 5369 Only available for `MATAIJ` matrices. 5370 5371 The sequential algorithm 5372 has a running time of the order of the number of nonzeros; the parallel 5373 test involves parallel copies of the block-offdiagonal parts of the matrix. 5374 5375 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()` 5376 @*/ 5377 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5378 { 5379 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5380 5381 PetscFunctionBegin; 5382 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5383 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5384 PetscValidBoolPointer(flg, 4); 5385 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f)); 5386 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g)); 5387 if (f && g) { 5388 PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test"); 5389 PetscCall((*f)(A, B, tol, flg)); 5390 } 5391 PetscFunctionReturn(PETSC_SUCCESS); 5392 } 5393 5394 /*@ 5395 MatPermute - Creates a new matrix with rows and columns permuted from the 5396 original. 5397 5398 Collective 5399 5400 Input Parameters: 5401 + mat - the matrix to permute 5402 . row - row permutation, each processor supplies only the permutation for its rows 5403 - col - column permutation, each processor supplies only the permutation for its columns 5404 5405 Output Parameter: 5406 . B - the permuted matrix 5407 5408 Level: advanced 5409 5410 Note: 5411 The index sets map from row/col of permuted matrix to row/col of original matrix. 5412 The index sets should be on the same communicator as mat and have the same local sizes. 5413 5414 Developer Note: 5415 If you want to implement `MatPermute()` for a matrix type, and your approach doesn't 5416 exploit the fact that row and col are permutations, consider implementing the 5417 more general `MatCreateSubMatrix()` instead. 5418 5419 .seealso: [](chapter_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()` 5420 @*/ 5421 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B) 5422 { 5423 PetscFunctionBegin; 5424 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5425 PetscValidType(mat, 1); 5426 PetscValidHeaderSpecific(row, IS_CLASSID, 2); 5427 PetscValidHeaderSpecific(col, IS_CLASSID, 3); 5428 PetscValidPointer(B, 4); 5429 PetscCheckSameComm(mat, 1, row, 2); 5430 if (row != col) PetscCheckSameComm(row, 2, col, 3); 5431 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5432 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5433 PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name); 5434 MatCheckPreallocated(mat, 1); 5435 5436 if (mat->ops->permute) { 5437 PetscUseTypeMethod(mat, permute, row, col, B); 5438 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5439 } else { 5440 PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B)); 5441 } 5442 PetscFunctionReturn(PETSC_SUCCESS); 5443 } 5444 5445 /*@ 5446 MatEqual - Compares two matrices. 5447 5448 Collective 5449 5450 Input Parameters: 5451 + A - the first matrix 5452 - B - the second matrix 5453 5454 Output Parameter: 5455 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise. 5456 5457 Level: intermediate 5458 5459 .seealso: [](chapter_matrices), `Mat` 5460 @*/ 5461 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg) 5462 { 5463 PetscFunctionBegin; 5464 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5465 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5466 PetscValidType(A, 1); 5467 PetscValidType(B, 2); 5468 PetscValidBoolPointer(flg, 3); 5469 PetscCheckSameComm(A, 1, B, 2); 5470 MatCheckPreallocated(A, 1); 5471 MatCheckPreallocated(B, 2); 5472 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5473 PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5474 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, 5475 B->cmap->N); 5476 if (A->ops->equal && A->ops->equal == B->ops->equal) { 5477 PetscUseTypeMethod(A, equal, B, flg); 5478 } else { 5479 PetscCall(MatMultEqual(A, B, 10, flg)); 5480 } 5481 PetscFunctionReturn(PETSC_SUCCESS); 5482 } 5483 5484 /*@ 5485 MatDiagonalScale - Scales a matrix on the left and right by diagonal 5486 matrices that are stored as vectors. Either of the two scaling 5487 matrices can be `NULL`. 5488 5489 Collective 5490 5491 Input Parameters: 5492 + mat - the matrix to be scaled 5493 . l - the left scaling vector (or `NULL`) 5494 - r - the right scaling vector (or `NULL`) 5495 5496 Level: intermediate 5497 5498 Note: 5499 `MatDiagonalScale()` computes A = LAR, where 5500 L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector) 5501 The L scales the rows of the matrix, the R scales the columns of the matrix. 5502 5503 .seealso: [](chapter_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()` 5504 @*/ 5505 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r) 5506 { 5507 PetscFunctionBegin; 5508 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5509 PetscValidType(mat, 1); 5510 if (l) { 5511 PetscValidHeaderSpecific(l, VEC_CLASSID, 2); 5512 PetscCheckSameComm(mat, 1, l, 2); 5513 } 5514 if (r) { 5515 PetscValidHeaderSpecific(r, VEC_CLASSID, 3); 5516 PetscCheckSameComm(mat, 1, r, 3); 5517 } 5518 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5519 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5520 MatCheckPreallocated(mat, 1); 5521 if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS); 5522 5523 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5524 PetscUseTypeMethod(mat, diagonalscale, l, r); 5525 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5526 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5527 if (l != r) mat->symmetric = PETSC_BOOL3_FALSE; 5528 PetscFunctionReturn(PETSC_SUCCESS); 5529 } 5530 5531 /*@ 5532 MatScale - Scales all elements of a matrix by a given number. 5533 5534 Logically Collective 5535 5536 Input Parameters: 5537 + mat - the matrix to be scaled 5538 - a - the scaling value 5539 5540 Level: intermediate 5541 5542 .seealso: [](chapter_matrices), `Mat`, `MatDiagonalScale()` 5543 @*/ 5544 PetscErrorCode MatScale(Mat mat, PetscScalar a) 5545 { 5546 PetscFunctionBegin; 5547 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5548 PetscValidType(mat, 1); 5549 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5550 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5551 PetscValidLogicalCollectiveScalar(mat, a, 2); 5552 MatCheckPreallocated(mat, 1); 5553 5554 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5555 if (a != (PetscScalar)1.0) { 5556 PetscUseTypeMethod(mat, scale, a); 5557 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5558 } 5559 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5560 PetscFunctionReturn(PETSC_SUCCESS); 5561 } 5562 5563 /*@ 5564 MatNorm - Calculates various norms of a matrix. 5565 5566 Collective 5567 5568 Input Parameters: 5569 + mat - the matrix 5570 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY` 5571 5572 Output Parameter: 5573 . nrm - the resulting norm 5574 5575 Level: intermediate 5576 5577 .seealso: [](chapter_matrices), `Mat` 5578 @*/ 5579 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm) 5580 { 5581 PetscFunctionBegin; 5582 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5583 PetscValidType(mat, 1); 5584 PetscValidRealPointer(nrm, 3); 5585 5586 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5587 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5588 MatCheckPreallocated(mat, 1); 5589 5590 PetscUseTypeMethod(mat, norm, type, nrm); 5591 PetscFunctionReturn(PETSC_SUCCESS); 5592 } 5593 5594 /* 5595 This variable is used to prevent counting of MatAssemblyBegin() that 5596 are called from within a MatAssemblyEnd(). 5597 */ 5598 static PetscInt MatAssemblyEnd_InUse = 0; 5599 /*@ 5600 MatAssemblyBegin - Begins assembling the matrix. This routine should 5601 be called after completing all calls to `MatSetValues()`. 5602 5603 Collective 5604 5605 Input Parameters: 5606 + mat - the matrix 5607 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5608 5609 Level: beginner 5610 5611 Notes: 5612 `MatSetValues()` generally caches the values that belong to other MPI ranks. The matrix is ready to 5613 use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called. 5614 5615 Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES` 5616 in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before 5617 using the matrix. 5618 5619 ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the 5620 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 5621 a global collective operation requiring all processes that share the matrix. 5622 5623 Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed 5624 out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros 5625 before `MAT_FINAL_ASSEMBLY` so the space is not compressed out. 5626 5627 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()` 5628 @*/ 5629 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type) 5630 { 5631 PetscFunctionBegin; 5632 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5633 PetscValidType(mat, 1); 5634 MatCheckPreallocated(mat, 1); 5635 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?"); 5636 if (mat->assembled) { 5637 mat->was_assembled = PETSC_TRUE; 5638 mat->assembled = PETSC_FALSE; 5639 } 5640 5641 if (!MatAssemblyEnd_InUse) { 5642 PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0)); 5643 PetscTryTypeMethod(mat, assemblybegin, type); 5644 PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0)); 5645 } else PetscTryTypeMethod(mat, assemblybegin, type); 5646 PetscFunctionReturn(PETSC_SUCCESS); 5647 } 5648 5649 /*@ 5650 MatAssembled - Indicates if a matrix has been assembled and is ready for 5651 use; for example, in matrix-vector product. 5652 5653 Not Collective 5654 5655 Input Parameter: 5656 . mat - the matrix 5657 5658 Output Parameter: 5659 . assembled - `PETSC_TRUE` or `PETSC_FALSE` 5660 5661 Level: advanced 5662 5663 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()` 5664 @*/ 5665 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled) 5666 { 5667 PetscFunctionBegin; 5668 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5669 PetscValidBoolPointer(assembled, 2); 5670 *assembled = mat->assembled; 5671 PetscFunctionReturn(PETSC_SUCCESS); 5672 } 5673 5674 /*@ 5675 MatAssemblyEnd - Completes assembling the matrix. This routine should 5676 be called after `MatAssemblyBegin()`. 5677 5678 Collective 5679 5680 Input Parameters: 5681 + mat - the matrix 5682 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5683 5684 Options Database Keys: 5685 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatEndAssembly()` 5686 . -mat_view ::ascii_info_detail - Prints more detailed info 5687 . -mat_view - Prints matrix in ASCII format 5688 . -mat_view ::ascii_matlab - Prints matrix in Matlab format 5689 . -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 5690 . -display <name> - Sets display name (default is host) 5691 . -draw_pause <sec> - Sets number of seconds to pause after display 5692 . -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See [Using MATLAB with PETSc](ch_matlab)) 5693 . -viewer_socket_machine <machine> - Machine to use for socket 5694 . -viewer_socket_port <port> - Port number to use for socket 5695 - -mat_view binary:filename[:append] - Save matrix to file in binary format 5696 5697 Level: beginner 5698 5699 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()` 5700 @*/ 5701 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type) 5702 { 5703 static PetscInt inassm = 0; 5704 PetscBool flg = PETSC_FALSE; 5705 5706 PetscFunctionBegin; 5707 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5708 PetscValidType(mat, 1); 5709 5710 inassm++; 5711 MatAssemblyEnd_InUse++; 5712 if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */ 5713 PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0)); 5714 PetscTryTypeMethod(mat, assemblyend, type); 5715 PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0)); 5716 } else PetscTryTypeMethod(mat, assemblyend, type); 5717 5718 /* Flush assembly is not a true assembly */ 5719 if (type != MAT_FLUSH_ASSEMBLY) { 5720 if (mat->num_ass) { 5721 if (!mat->symmetry_eternal) { 5722 mat->symmetric = PETSC_BOOL3_UNKNOWN; 5723 mat->hermitian = PETSC_BOOL3_UNKNOWN; 5724 } 5725 if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN; 5726 if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN; 5727 } 5728 mat->num_ass++; 5729 mat->assembled = PETSC_TRUE; 5730 mat->ass_nonzerostate = mat->nonzerostate; 5731 } 5732 5733 mat->insertmode = NOT_SET_VALUES; 5734 MatAssemblyEnd_InUse--; 5735 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5736 if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) { 5737 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 5738 5739 if (mat->checksymmetryonassembly) { 5740 PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg)); 5741 if (flg) { 5742 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5743 } else { 5744 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5745 } 5746 } 5747 if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL)); 5748 } 5749 inassm--; 5750 PetscFunctionReturn(PETSC_SUCCESS); 5751 } 5752 5753 /*@ 5754 MatSetOption - Sets a parameter option for a matrix. Some options 5755 may be specific to certain storage formats. Some options 5756 determine how values will be inserted (or added). Sorted, 5757 row-oriented input will generally assemble the fastest. The default 5758 is row-oriented. 5759 5760 Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption` 5761 5762 Input Parameters: 5763 + mat - the matrix 5764 . option - the option, one of those listed below (and possibly others), 5765 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5766 5767 Options Describing Matrix Structure: 5768 + `MAT_SPD` - symmetric positive definite 5769 . `MAT_SYMMETRIC` - symmetric in terms of both structure and value 5770 . `MAT_HERMITIAN` - transpose is the complex conjugation 5771 . `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure 5772 . `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix 5773 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix 5774 - `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix 5775 5776 These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they 5777 do not need to be computed (usually at a high cost) 5778 5779 Options For Use with `MatSetValues()`: 5780 Insert a logically dense subblock, which can be 5781 . `MAT_ROW_ORIENTED` - row-oriented (default) 5782 5783 These options reflect the data you pass in with `MatSetValues()`; it has 5784 nothing to do with how the data is stored internally in the matrix 5785 data structure. 5786 5787 When (re)assembling a matrix, we can restrict the input for 5788 efficiency/debugging purposes. These options include 5789 + `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow) 5790 . `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated 5791 . `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries 5792 . `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry 5793 . `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly 5794 . `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if 5795 any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves 5796 performance for very large process counts. 5797 - `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset 5798 of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly 5799 functions, instead sending only neighbor messages. 5800 5801 Level: intermediate 5802 5803 Notes: 5804 Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg! 5805 5806 Some options are relevant only for particular matrix types and 5807 are thus ignored by others. Other options are not supported by 5808 certain matrix types and will generate an error message if set. 5809 5810 If using Fortran to compute a matrix, one may need to 5811 use the column-oriented option (or convert to the row-oriented 5812 format). 5813 5814 `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion 5815 that would generate a new entry in the nonzero structure is instead 5816 ignored. Thus, if memory has not already been allocated for this particular 5817 data, then the insertion is ignored. For dense matrices, in which 5818 the entire array is allocated, no entries are ever ignored. 5819 Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction 5820 5821 `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion 5822 that would generate a new entry in the nonzero structure instead produces 5823 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 5824 5825 `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion 5826 that would generate a new entry that has not been preallocated will 5827 instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats 5828 only.) This is a useful flag when debugging matrix memory preallocation. 5829 If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 5830 5831 `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for 5832 other processors should be dropped, rather than stashed. 5833 This is useful if you know that the "owning" processor is also 5834 always generating the correct matrix entries, so that PETSc need 5835 not transfer duplicate entries generated on another processor. 5836 5837 `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the 5838 searches during matrix assembly. When this flag is set, the hash table 5839 is created during the first matrix assembly. This hash table is 5840 used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()` 5841 to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag 5842 should be used with `MAT_USE_HASH_TABLE` flag. This option is currently 5843 supported by `MATMPIBAIJ` format only. 5844 5845 `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries 5846 are kept in the nonzero structure 5847 5848 `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating 5849 a zero location in the matrix 5850 5851 `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types 5852 5853 `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the 5854 zero row routines and thus improves performance for very large process counts. 5855 5856 `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular 5857 part of the matrix (since they should match the upper triangular part). 5858 5859 `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a 5860 single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common 5861 with finite difference schemes with non-periodic boundary conditions. 5862 5863 Developer Note: 5864 `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other 5865 places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRIC` or `MAT_SPD` would need to be changed back 5866 to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had 5867 not changed. 5868 5869 .seealso: [](chapter_matrices), `MatOption`, `Mat`, `MatGetOption()` 5870 @*/ 5871 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg) 5872 { 5873 PetscFunctionBegin; 5874 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5875 if (op > 0) { 5876 PetscValidLogicalCollectiveEnum(mat, op, 2); 5877 PetscValidLogicalCollectiveBool(mat, flg, 3); 5878 } 5879 5880 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); 5881 5882 switch (op) { 5883 case MAT_FORCE_DIAGONAL_ENTRIES: 5884 mat->force_diagonals = flg; 5885 PetscFunctionReturn(PETSC_SUCCESS); 5886 case MAT_NO_OFF_PROC_ENTRIES: 5887 mat->nooffprocentries = flg; 5888 PetscFunctionReturn(PETSC_SUCCESS); 5889 case MAT_SUBSET_OFF_PROC_ENTRIES: 5890 mat->assembly_subset = flg; 5891 if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */ 5892 #if !defined(PETSC_HAVE_MPIUNI) 5893 PetscCall(MatStashScatterDestroy_BTS(&mat->stash)); 5894 #endif 5895 mat->stash.first_assembly_done = PETSC_FALSE; 5896 } 5897 PetscFunctionReturn(PETSC_SUCCESS); 5898 case MAT_NO_OFF_PROC_ZERO_ROWS: 5899 mat->nooffproczerorows = flg; 5900 PetscFunctionReturn(PETSC_SUCCESS); 5901 case MAT_SPD: 5902 if (flg) { 5903 mat->spd = PETSC_BOOL3_TRUE; 5904 mat->symmetric = PETSC_BOOL3_TRUE; 5905 mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5906 } else { 5907 mat->spd = PETSC_BOOL3_FALSE; 5908 } 5909 break; 5910 case MAT_SYMMETRIC: 5911 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5912 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5913 #if !defined(PETSC_USE_COMPLEX) 5914 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5915 #endif 5916 break; 5917 case MAT_HERMITIAN: 5918 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5919 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5920 #if !defined(PETSC_USE_COMPLEX) 5921 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5922 #endif 5923 break; 5924 case MAT_STRUCTURALLY_SYMMETRIC: 5925 mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5926 break; 5927 case MAT_SYMMETRY_ETERNAL: 5928 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"); 5929 mat->symmetry_eternal = flg; 5930 if (flg) mat->structural_symmetry_eternal = PETSC_TRUE; 5931 break; 5932 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 5933 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"); 5934 mat->structural_symmetry_eternal = flg; 5935 break; 5936 case MAT_SPD_ETERNAL: 5937 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"); 5938 mat->spd_eternal = flg; 5939 if (flg) { 5940 mat->structural_symmetry_eternal = PETSC_TRUE; 5941 mat->symmetry_eternal = PETSC_TRUE; 5942 } 5943 break; 5944 case MAT_STRUCTURE_ONLY: 5945 mat->structure_only = flg; 5946 break; 5947 case MAT_SORTED_FULL: 5948 mat->sortedfull = flg; 5949 break; 5950 default: 5951 break; 5952 } 5953 PetscTryTypeMethod(mat, setoption, op, flg); 5954 PetscFunctionReturn(PETSC_SUCCESS); 5955 } 5956 5957 /*@ 5958 MatGetOption - Gets a parameter option that has been set for a matrix. 5959 5960 Logically Collective 5961 5962 Input Parameters: 5963 + mat - the matrix 5964 - option - the option, this only responds to certain options, check the code for which ones 5965 5966 Output Parameter: 5967 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5968 5969 Level: intermediate 5970 5971 Notes: 5972 Can only be called after `MatSetSizes()` and `MatSetType()` have been set. 5973 5974 Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or 5975 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 5976 5977 .seealso: [](chapter_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, 5978 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 5979 @*/ 5980 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg) 5981 { 5982 PetscFunctionBegin; 5983 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5984 PetscValidType(mat, 1); 5985 5986 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); 5987 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()"); 5988 5989 switch (op) { 5990 case MAT_NO_OFF_PROC_ENTRIES: 5991 *flg = mat->nooffprocentries; 5992 break; 5993 case MAT_NO_OFF_PROC_ZERO_ROWS: 5994 *flg = mat->nooffproczerorows; 5995 break; 5996 case MAT_SYMMETRIC: 5997 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()"); 5998 break; 5999 case MAT_HERMITIAN: 6000 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()"); 6001 break; 6002 case MAT_STRUCTURALLY_SYMMETRIC: 6003 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()"); 6004 break; 6005 case MAT_SPD: 6006 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()"); 6007 break; 6008 case MAT_SYMMETRY_ETERNAL: 6009 *flg = mat->symmetry_eternal; 6010 break; 6011 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6012 *flg = mat->symmetry_eternal; 6013 break; 6014 default: 6015 break; 6016 } 6017 PetscFunctionReturn(PETSC_SUCCESS); 6018 } 6019 6020 /*@ 6021 MatZeroEntries - Zeros all entries of a matrix. For sparse matrices 6022 this routine retains the old nonzero structure. 6023 6024 Logically Collective 6025 6026 Input Parameter: 6027 . mat - the matrix 6028 6029 Level: intermediate 6030 6031 Note: 6032 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. 6033 See the Performance chapter of the users manual for information on preallocating matrices. 6034 6035 .seealso: [](chapter_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()` 6036 @*/ 6037 PetscErrorCode MatZeroEntries(Mat mat) 6038 { 6039 PetscFunctionBegin; 6040 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6041 PetscValidType(mat, 1); 6042 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6043 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"); 6044 MatCheckPreallocated(mat, 1); 6045 6046 PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0)); 6047 PetscUseTypeMethod(mat, zeroentries); 6048 PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0)); 6049 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6050 PetscFunctionReturn(PETSC_SUCCESS); 6051 } 6052 6053 /*@ 6054 MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal) 6055 of a set of rows and columns of a matrix. 6056 6057 Collective 6058 6059 Input Parameters: 6060 + mat - the matrix 6061 . numRows - the number of rows/columns to zero 6062 . rows - the global row indices 6063 . diag - value put in the diagonal of the eliminated rows 6064 . x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call 6065 - b - optional vector of the right hand side, that will be adjusted by provided solution entries 6066 6067 Level: intermediate 6068 6069 Notes: 6070 This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6071 6072 For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`. 6073 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 6074 6075 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6076 Krylov method to take advantage of the known solution on the zeroed rows. 6077 6078 For the parallel case, all processes that share the matrix (i.e., 6079 those in the communicator used for matrix creation) MUST call this 6080 routine, regardless of whether any rows being zeroed are owned by 6081 them. 6082 6083 Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix. 6084 6085 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6086 list only rows local to itself). 6087 6088 The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine. 6089 6090 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6091 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6092 @*/ 6093 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6094 { 6095 PetscFunctionBegin; 6096 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6097 PetscValidType(mat, 1); 6098 if (numRows) PetscValidIntPointer(rows, 3); 6099 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6100 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6101 MatCheckPreallocated(mat, 1); 6102 6103 PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b); 6104 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6105 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6106 PetscFunctionReturn(PETSC_SUCCESS); 6107 } 6108 6109 /*@ 6110 MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal) 6111 of a set of rows and columns of a matrix. 6112 6113 Collective 6114 6115 Input Parameters: 6116 + mat - the matrix 6117 . is - the rows to zero 6118 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6119 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6120 - b - optional vector of right hand side, that will be adjusted by provided solution 6121 6122 Level: intermediate 6123 6124 Note: 6125 See `MatZeroRowsColumns()` for details on how this routine operates. 6126 6127 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6128 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()` 6129 @*/ 6130 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6131 { 6132 PetscInt numRows; 6133 const PetscInt *rows; 6134 6135 PetscFunctionBegin; 6136 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6137 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6138 PetscValidType(mat, 1); 6139 PetscValidType(is, 2); 6140 PetscCall(ISGetLocalSize(is, &numRows)); 6141 PetscCall(ISGetIndices(is, &rows)); 6142 PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b)); 6143 PetscCall(ISRestoreIndices(is, &rows)); 6144 PetscFunctionReturn(PETSC_SUCCESS); 6145 } 6146 6147 /*@ 6148 MatZeroRows - Zeros all entries (except possibly the main diagonal) 6149 of a set of rows of a matrix. 6150 6151 Collective 6152 6153 Input Parameters: 6154 + mat - the matrix 6155 . numRows - the number of rows to zero 6156 . rows - the global row indices 6157 . diag - value put in the diagonal of the zeroed rows 6158 . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call 6159 - b - optional vector of right hand side, that will be adjusted by provided solution entries 6160 6161 Level: intermediate 6162 6163 Notes: 6164 This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6165 6166 For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`. 6167 6168 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6169 Krylov method to take advantage of the known solution on the zeroed rows. 6170 6171 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) 6172 from the matrix. 6173 6174 Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix 6175 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 6176 formats this does not alter the nonzero structure. 6177 6178 If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure 6179 of the matrix is not changed the values are 6180 merely zeroed. 6181 6182 The user can set a value in the diagonal entry (or for the `MATAIJ` format 6183 formats can optionally remove the main diagonal entry from the 6184 nonzero structure as well, by passing 0.0 as the final argument). 6185 6186 For the parallel case, all processes that share the matrix (i.e., 6187 those in the communicator used for matrix creation) MUST call this 6188 routine, regardless of whether any rows being zeroed are owned by 6189 them. 6190 6191 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6192 list only rows local to itself). 6193 6194 You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it 6195 owns that are to be zeroed. This saves a global synchronization in the implementation. 6196 6197 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6198 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE` 6199 @*/ 6200 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6201 { 6202 PetscFunctionBegin; 6203 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6204 PetscValidType(mat, 1); 6205 if (numRows) PetscValidIntPointer(rows, 3); 6206 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6207 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6208 MatCheckPreallocated(mat, 1); 6209 6210 PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b); 6211 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6212 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6213 PetscFunctionReturn(PETSC_SUCCESS); 6214 } 6215 6216 /*@ 6217 MatZeroRowsIS - Zeros all entries (except possibly the main diagonal) 6218 of a set of rows of a matrix. 6219 6220 Collective 6221 6222 Input Parameters: 6223 + mat - the matrix 6224 . is - index set of rows to remove (if `NULL` then no row is removed) 6225 . diag - value put in all diagonals of eliminated rows 6226 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6227 - b - optional vector of right hand side, that will be adjusted by provided solution 6228 6229 Level: intermediate 6230 6231 Note: 6232 See `MatZeroRows()` for details on how this routine operates. 6233 6234 .seealso: [](chapter_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6235 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6236 @*/ 6237 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6238 { 6239 PetscInt numRows = 0; 6240 const PetscInt *rows = NULL; 6241 6242 PetscFunctionBegin; 6243 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6244 PetscValidType(mat, 1); 6245 if (is) { 6246 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6247 PetscCall(ISGetLocalSize(is, &numRows)); 6248 PetscCall(ISGetIndices(is, &rows)); 6249 } 6250 PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b)); 6251 if (is) PetscCall(ISRestoreIndices(is, &rows)); 6252 PetscFunctionReturn(PETSC_SUCCESS); 6253 } 6254 6255 /*@ 6256 MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal) 6257 of a set of rows of a matrix. These rows must be local to the process. 6258 6259 Collective 6260 6261 Input Parameters: 6262 + mat - the matrix 6263 . numRows - the number of rows to remove 6264 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6265 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 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 Notes: 6272 See `MatZeroRows()` for details on how this routine operates. 6273 6274 The grid coordinates are across the entire grid, not just the local portion 6275 6276 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6277 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6278 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6279 `DM_BOUNDARY_PERIODIC` boundary type. 6280 6281 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 6282 a single value per point) you can skip filling those indices. 6283 6284 Fortran Note: 6285 `idxm` and `idxn` should be declared as 6286 $ MatStencil idxm(4,m) 6287 and the values inserted using 6288 .vb 6289 idxm(MatStencil_i,1) = i 6290 idxm(MatStencil_j,1) = j 6291 idxm(MatStencil_k,1) = k 6292 idxm(MatStencil_c,1) = c 6293 etc 6294 .ve 6295 6296 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6297 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6298 @*/ 6299 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6300 { 6301 PetscInt dim = mat->stencil.dim; 6302 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6303 PetscInt *dims = mat->stencil.dims + 1; 6304 PetscInt *starts = mat->stencil.starts; 6305 PetscInt *dxm = (PetscInt *)rows; 6306 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6307 6308 PetscFunctionBegin; 6309 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6310 PetscValidType(mat, 1); 6311 if (numRows) PetscValidPointer(rows, 3); 6312 6313 PetscCall(PetscMalloc1(numRows, &jdxm)); 6314 for (i = 0; i < numRows; ++i) { 6315 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6316 for (j = 0; j < 3 - sdim; ++j) dxm++; 6317 /* Local index in X dir */ 6318 tmp = *dxm++ - starts[0]; 6319 /* Loop over remaining dimensions */ 6320 for (j = 0; j < dim - 1; ++j) { 6321 /* If nonlocal, set index to be negative */ 6322 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6323 /* Update local index */ 6324 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6325 } 6326 /* Skip component slot if necessary */ 6327 if (mat->stencil.noc) dxm++; 6328 /* Local row number */ 6329 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6330 } 6331 PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b)); 6332 PetscCall(PetscFree(jdxm)); 6333 PetscFunctionReturn(PETSC_SUCCESS); 6334 } 6335 6336 /*@ 6337 MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal) 6338 of a set of rows and columns of a matrix. 6339 6340 Collective 6341 6342 Input Parameters: 6343 + mat - the matrix 6344 . numRows - the number of rows/columns to remove 6345 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6346 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6347 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6348 - b - optional vector of right hand side, that will be adjusted by provided solution 6349 6350 Level: intermediate 6351 6352 Notes: 6353 See `MatZeroRowsColumns()` for details on how this routine operates. 6354 6355 The grid coordinates are across the entire grid, not just the local portion 6356 6357 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6358 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6359 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6360 `DM_BOUNDARY_PERIODIC` boundary type. 6361 6362 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 6363 a single value per point) you can skip filling those indices. 6364 6365 Fortran Note: 6366 `idxm` and `idxn` should be declared as 6367 $ MatStencil idxm(4,m) 6368 and the values inserted using 6369 .vb 6370 idxm(MatStencil_i,1) = i 6371 idxm(MatStencil_j,1) = j 6372 idxm(MatStencil_k,1) = k 6373 idxm(MatStencil_c,1) = c 6374 etc 6375 .ve 6376 6377 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6378 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()` 6379 @*/ 6380 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6381 { 6382 PetscInt dim = mat->stencil.dim; 6383 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6384 PetscInt *dims = mat->stencil.dims + 1; 6385 PetscInt *starts = mat->stencil.starts; 6386 PetscInt *dxm = (PetscInt *)rows; 6387 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6388 6389 PetscFunctionBegin; 6390 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6391 PetscValidType(mat, 1); 6392 if (numRows) PetscValidPointer(rows, 3); 6393 6394 PetscCall(PetscMalloc1(numRows, &jdxm)); 6395 for (i = 0; i < numRows; ++i) { 6396 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6397 for (j = 0; j < 3 - sdim; ++j) dxm++; 6398 /* Local index in X dir */ 6399 tmp = *dxm++ - starts[0]; 6400 /* Loop over remaining dimensions */ 6401 for (j = 0; j < dim - 1; ++j) { 6402 /* If nonlocal, set index to be negative */ 6403 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6404 /* Update local index */ 6405 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6406 } 6407 /* Skip component slot if necessary */ 6408 if (mat->stencil.noc) dxm++; 6409 /* Local row number */ 6410 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6411 } 6412 PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b)); 6413 PetscCall(PetscFree(jdxm)); 6414 PetscFunctionReturn(PETSC_SUCCESS); 6415 } 6416 6417 /*@C 6418 MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal) 6419 of a set of rows of a matrix; using local numbering of rows. 6420 6421 Collective 6422 6423 Input Parameters: 6424 + mat - the matrix 6425 . numRows - the number of rows to remove 6426 . rows - the local row indices 6427 . diag - value put in all diagonals of eliminated rows 6428 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6429 - b - optional vector of right hand side, that will be adjusted by provided solution 6430 6431 Level: intermediate 6432 6433 Notes: 6434 Before calling `MatZeroRowsLocal()`, the user must first set the 6435 local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`. 6436 6437 See `MatZeroRows()` for details on how this routine operates. 6438 6439 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`, 6440 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6441 @*/ 6442 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6443 { 6444 PetscFunctionBegin; 6445 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6446 PetscValidType(mat, 1); 6447 if (numRows) PetscValidIntPointer(rows, 3); 6448 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6449 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6450 MatCheckPreallocated(mat, 1); 6451 6452 if (mat->ops->zerorowslocal) { 6453 PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b); 6454 } else { 6455 IS is, newis; 6456 const PetscInt *newRows; 6457 6458 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6459 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6460 PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis)); 6461 PetscCall(ISGetIndices(newis, &newRows)); 6462 PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b); 6463 PetscCall(ISRestoreIndices(newis, &newRows)); 6464 PetscCall(ISDestroy(&newis)); 6465 PetscCall(ISDestroy(&is)); 6466 } 6467 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6468 PetscFunctionReturn(PETSC_SUCCESS); 6469 } 6470 6471 /*@ 6472 MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal) 6473 of a set of rows of a matrix; using local numbering of rows. 6474 6475 Collective 6476 6477 Input Parameters: 6478 + mat - the matrix 6479 . is - index set of rows to remove 6480 . diag - value put in all diagonals of eliminated rows 6481 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6482 - b - optional vector of right hand side, that will be adjusted by provided solution 6483 6484 Level: intermediate 6485 6486 Notes: 6487 Before calling `MatZeroRowsLocalIS()`, the user must first set the 6488 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6489 6490 See `MatZeroRows()` for details on how this routine operates. 6491 6492 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6493 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6494 @*/ 6495 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6496 { 6497 PetscInt numRows; 6498 const PetscInt *rows; 6499 6500 PetscFunctionBegin; 6501 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6502 PetscValidType(mat, 1); 6503 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6504 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6505 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6506 MatCheckPreallocated(mat, 1); 6507 6508 PetscCall(ISGetLocalSize(is, &numRows)); 6509 PetscCall(ISGetIndices(is, &rows)); 6510 PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b)); 6511 PetscCall(ISRestoreIndices(is, &rows)); 6512 PetscFunctionReturn(PETSC_SUCCESS); 6513 } 6514 6515 /*@ 6516 MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal) 6517 of a set of rows and columns of a matrix; using local numbering of rows. 6518 6519 Collective 6520 6521 Input Parameters: 6522 + mat - the matrix 6523 . numRows - the number of rows to remove 6524 . rows - the global row indices 6525 . diag - value put in all diagonals of eliminated rows 6526 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6527 - b - optional vector of right hand side, that will be adjusted by provided solution 6528 6529 Level: intermediate 6530 6531 Notes: 6532 Before calling `MatZeroRowsColumnsLocal()`, the user must first set the 6533 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6534 6535 See `MatZeroRowsColumns()` for details on how this routine operates. 6536 6537 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6538 `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6539 @*/ 6540 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6541 { 6542 IS is, newis; 6543 const PetscInt *newRows; 6544 6545 PetscFunctionBegin; 6546 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6547 PetscValidType(mat, 1); 6548 if (numRows) PetscValidIntPointer(rows, 3); 6549 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6550 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6551 MatCheckPreallocated(mat, 1); 6552 6553 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6554 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6555 PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis)); 6556 PetscCall(ISGetIndices(newis, &newRows)); 6557 PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b); 6558 PetscCall(ISRestoreIndices(newis, &newRows)); 6559 PetscCall(ISDestroy(&newis)); 6560 PetscCall(ISDestroy(&is)); 6561 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6562 PetscFunctionReturn(PETSC_SUCCESS); 6563 } 6564 6565 /*@ 6566 MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal) 6567 of a set of rows and columns of a matrix; using local numbering of rows. 6568 6569 Collective 6570 6571 Input Parameters: 6572 + mat - the matrix 6573 . is - index set of rows to remove 6574 . diag - value put in all diagonals of eliminated rows 6575 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6576 - b - optional vector of right hand side, that will be adjusted by provided solution 6577 6578 Level: intermediate 6579 6580 Notes: 6581 Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the 6582 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6583 6584 See `MatZeroRowsColumns()` for details on how this routine operates. 6585 6586 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6587 `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6588 @*/ 6589 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6590 { 6591 PetscInt numRows; 6592 const PetscInt *rows; 6593 6594 PetscFunctionBegin; 6595 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6596 PetscValidType(mat, 1); 6597 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6598 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6599 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6600 MatCheckPreallocated(mat, 1); 6601 6602 PetscCall(ISGetLocalSize(is, &numRows)); 6603 PetscCall(ISGetIndices(is, &rows)); 6604 PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b)); 6605 PetscCall(ISRestoreIndices(is, &rows)); 6606 PetscFunctionReturn(PETSC_SUCCESS); 6607 } 6608 6609 /*@C 6610 MatGetSize - Returns the numbers of rows and columns in a matrix. 6611 6612 Not Collective 6613 6614 Input Parameter: 6615 . mat - the matrix 6616 6617 Output Parameters: 6618 + m - the number of global rows 6619 - n - the number of global columns 6620 6621 Level: beginner 6622 6623 Note: 6624 Both output parameters can be `NULL` on input. 6625 6626 .seealso: [](chapter_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()` 6627 @*/ 6628 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n) 6629 { 6630 PetscFunctionBegin; 6631 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6632 if (m) *m = mat->rmap->N; 6633 if (n) *n = mat->cmap->N; 6634 PetscFunctionReturn(PETSC_SUCCESS); 6635 } 6636 6637 /*@C 6638 MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns 6639 of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`. 6640 6641 Not Collective 6642 6643 Input Parameter: 6644 . mat - the matrix 6645 6646 Output Parameters: 6647 + m - the number of local rows, use `NULL` to not obtain this value 6648 - n - the number of local columns, use `NULL` to not obtain this value 6649 6650 Level: beginner 6651 6652 .seealso: [](chapter_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()` 6653 @*/ 6654 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n) 6655 { 6656 PetscFunctionBegin; 6657 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6658 if (m) PetscValidIntPointer(m, 2); 6659 if (n) PetscValidIntPointer(n, 3); 6660 if (m) *m = mat->rmap->n; 6661 if (n) *n = mat->cmap->n; 6662 PetscFunctionReturn(PETSC_SUCCESS); 6663 } 6664 6665 /*@C 6666 MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by 6667 this processor. (The columns of the "diagonal block" for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts. 6668 6669 Not Collective, unless matrix has not been allocated, then collective 6670 6671 Input Parameter: 6672 . mat - the matrix 6673 6674 Output Parameters: 6675 + m - the global index of the first local column, use `NULL` to not obtain this value 6676 - n - one more than the global index of the last local column, use `NULL` to not obtain this value 6677 6678 Level: developer 6679 6680 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout` 6681 @*/ 6682 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n) 6683 { 6684 PetscFunctionBegin; 6685 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6686 PetscValidType(mat, 1); 6687 if (m) PetscValidIntPointer(m, 2); 6688 if (n) PetscValidIntPointer(n, 3); 6689 MatCheckPreallocated(mat, 1); 6690 if (m) *m = mat->cmap->rstart; 6691 if (n) *n = mat->cmap->rend; 6692 PetscFunctionReturn(PETSC_SUCCESS); 6693 } 6694 6695 /*@C 6696 MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6697 this MPI rank. For all matrices it returns the range of matrix rows associated with rows of a vector that would contain the result of a matrix 6698 vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts 6699 6700 Not Collective 6701 6702 Input Parameter: 6703 . mat - the matrix 6704 6705 Output Parameters: 6706 + m - the global index of the first local row, use `NULL` to not obtain this value 6707 - n - one more than the global index of the last local row, use `NULL` to not obtain this value 6708 6709 Level: beginner 6710 6711 Note: 6712 This function requires that the matrix be preallocated. If you have not preallocated, consider using 6713 `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N) 6714 and then `MPI_Scan()` to calculate prefix sums of the local sizes. 6715 6716 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, 6717 `PetscLayout` 6718 @*/ 6719 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n) 6720 { 6721 PetscFunctionBegin; 6722 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6723 PetscValidType(mat, 1); 6724 if (m) PetscValidIntPointer(m, 2); 6725 if (n) PetscValidIntPointer(n, 3); 6726 MatCheckPreallocated(mat, 1); 6727 if (m) *m = mat->rmap->rstart; 6728 if (n) *n = mat->rmap->rend; 6729 PetscFunctionReturn(PETSC_SUCCESS); 6730 } 6731 6732 /*@C 6733 MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6734 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 6735 vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts 6736 6737 Not Collective, unless matrix has not been allocated 6738 6739 Input Parameter: 6740 . mat - the matrix 6741 6742 Output Parameter: 6743 . ranges - start of each processors portion plus one more than the total length at the end 6744 6745 Level: beginner 6746 6747 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout` 6748 @*/ 6749 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges) 6750 { 6751 PetscFunctionBegin; 6752 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6753 PetscValidType(mat, 1); 6754 MatCheckPreallocated(mat, 1); 6755 PetscCall(PetscLayoutGetRanges(mat->rmap, ranges)); 6756 PetscFunctionReturn(PETSC_SUCCESS); 6757 } 6758 6759 /*@C 6760 MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by 6761 each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts. 6762 6763 Not Collective, unless matrix has not been allocated 6764 6765 Input Parameter: 6766 . mat - the matrix 6767 6768 Output Parameter: 6769 . ranges - start of each processors portion plus one more then the total length at the end 6770 6771 Level: beginner 6772 6773 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()` 6774 @*/ 6775 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges) 6776 { 6777 PetscFunctionBegin; 6778 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6779 PetscValidType(mat, 1); 6780 MatCheckPreallocated(mat, 1); 6781 PetscCall(PetscLayoutGetRanges(mat->cmap, ranges)); 6782 PetscFunctionReturn(PETSC_SUCCESS); 6783 } 6784 6785 /*@C 6786 MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this 6787 corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership 6788 is more complicated. See :any:`<sec_matlayout>` for details on matrix layouts. 6789 6790 Not Collective 6791 6792 Input Parameter: 6793 . A - matrix 6794 6795 Output Parameters: 6796 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value 6797 - cols - columns in which this process owns elements, use `NULL` to not obtain this value 6798 6799 Level: intermediate 6800 6801 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK`` 6802 @*/ 6803 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols) 6804 { 6805 PetscErrorCode (*f)(Mat, IS *, IS *); 6806 6807 PetscFunctionBegin; 6808 MatCheckPreallocated(A, 1); 6809 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f)); 6810 if (f) { 6811 PetscCall((*f)(A, rows, cols)); 6812 } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */ 6813 if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows)); 6814 if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols)); 6815 } 6816 PetscFunctionReturn(PETSC_SUCCESS); 6817 } 6818 6819 /*@C 6820 MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()` 6821 Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()` 6822 to complete the factorization. 6823 6824 Collective 6825 6826 Input Parameters: 6827 + fact - the factorized matrix obtained with `MatGetFactor()` 6828 . mat - the matrix 6829 . row - row permutation 6830 . col - column permutation 6831 - info - structure containing 6832 .vb 6833 levels - number of levels of fill. 6834 expected fill - as ratio of original fill. 6835 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 6836 missing diagonal entries) 6837 .ve 6838 6839 Level: developer 6840 6841 Notes: 6842 See [Matrix Factorization](sec_matfactor) for additional information. 6843 6844 Most users should employ the `KSP` interface for linear solvers 6845 instead of working directly with matrix algebra routines such as this. 6846 See, e.g., `KSPCreate()`. 6847 6848 Uses the definition of level of fill as in Y. Saad, 2003 6849 6850 Developer Note: 6851 The Fortran interface is not autogenerated as the 6852 interface definition cannot be generated correctly [due to `MatFactorInfo`] 6853 6854 References: 6855 . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003 6856 6857 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 6858 `MatGetOrdering()`, `MatFactorInfo` 6859 @*/ 6860 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 6861 { 6862 PetscFunctionBegin; 6863 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 6864 PetscValidType(mat, 2); 6865 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 6866 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 6867 PetscValidPointer(info, 5); 6868 PetscValidPointer(fact, 1); 6869 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels); 6870 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 6871 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6872 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6873 MatCheckPreallocated(mat, 2); 6874 6875 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0)); 6876 PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info); 6877 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0)); 6878 PetscFunctionReturn(PETSC_SUCCESS); 6879 } 6880 6881 /*@C 6882 MatICCFactorSymbolic - Performs symbolic incomplete 6883 Cholesky factorization for a symmetric matrix. Use 6884 `MatCholeskyFactorNumeric()` to complete the factorization. 6885 6886 Collective 6887 6888 Input Parameters: 6889 + fact - the factorized matrix obtained with `MatGetFactor()` 6890 . mat - the matrix to be factored 6891 . perm - row and column permutation 6892 - info - structure containing 6893 .vb 6894 levels - number of levels of fill. 6895 expected fill - as ratio of original fill. 6896 .ve 6897 6898 Level: developer 6899 6900 Notes: 6901 Most users should employ the `KSP` interface for linear solvers 6902 instead of working directly with matrix algebra routines such as this. 6903 See, e.g., `KSPCreate()`. 6904 6905 This uses the definition of level of fill as in Y. Saad, 2003 6906 6907 Developer Note: 6908 The Fortran interface is not autogenerated as the 6909 interface definition cannot be generated correctly [due to `MatFactorInfo`] 6910 6911 References: 6912 . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003 6913 6914 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 6915 @*/ 6916 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 6917 { 6918 PetscFunctionBegin; 6919 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 6920 PetscValidType(mat, 2); 6921 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 6922 PetscValidPointer(info, 4); 6923 PetscValidPointer(fact, 1); 6924 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6925 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels); 6926 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 6927 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6928 MatCheckPreallocated(mat, 2); 6929 6930 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 6931 PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info); 6932 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 6933 PetscFunctionReturn(PETSC_SUCCESS); 6934 } 6935 6936 /*@C 6937 MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat 6938 points to an array of valid matrices, they may be reused to store the new 6939 submatrices. 6940 6941 Collective 6942 6943 Input Parameters: 6944 + mat - the matrix 6945 . n - the number of submatrixes to be extracted (on this processor, may be zero) 6946 . irow - index set of rows to extract 6947 . icol - index set of columns to extract 6948 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 6949 6950 Output Parameter: 6951 . submat - the array of submatrices 6952 6953 Level: advanced 6954 6955 Notes: 6956 `MatCreateSubMatrices()` can extract ONLY sequential submatrices 6957 (from both sequential and parallel matrices). Use `MatCreateSubMatrix()` 6958 to extract a parallel submatrix. 6959 6960 Some matrix types place restrictions on the row and column 6961 indices, such as that they be sorted or that they be equal to each other. 6962 6963 The index sets may not have duplicate entries. 6964 6965 When extracting submatrices from a parallel matrix, each processor can 6966 form a different submatrix by setting the rows and columns of its 6967 individual index sets according to the local submatrix desired. 6968 6969 When finished using the submatrices, the user should destroy 6970 them with `MatDestroySubMatrices()`. 6971 6972 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 6973 original matrix has not changed from that last call to `MatCreateSubMatrices()`. 6974 6975 This routine creates the matrices in submat; you should NOT create them before 6976 calling it. It also allocates the array of matrix pointers submat. 6977 6978 For `MATBAIJ` matrices the index sets must respect the block structure, that is if they 6979 request one row/column in a block, they must request all rows/columns that are in 6980 that block. For example, if the block size is 2 you cannot request just row 0 and 6981 column 0. 6982 6983 Fortran Note: 6984 The Fortran interface is slightly different from that given below; it 6985 requires one to pass in as `submat` a `Mat` (integer) array of size at least n+1. 6986 6987 .seealso: [](chapter_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 6988 @*/ 6989 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 6990 { 6991 PetscInt i; 6992 PetscBool eq; 6993 6994 PetscFunctionBegin; 6995 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6996 PetscValidType(mat, 1); 6997 if (n) { 6998 PetscValidPointer(irow, 3); 6999 for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3); 7000 PetscValidPointer(icol, 4); 7001 for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4); 7002 } 7003 PetscValidPointer(submat, 6); 7004 if (n && scall == MAT_REUSE_MATRIX) { 7005 PetscValidPointer(*submat, 6); 7006 for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6); 7007 } 7008 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7009 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7010 MatCheckPreallocated(mat, 1); 7011 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7012 PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat); 7013 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7014 for (i = 0; i < n; i++) { 7015 (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */ 7016 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7017 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7018 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 7019 if (mat->boundtocpu && mat->bindingpropagates) { 7020 PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE)); 7021 PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE)); 7022 } 7023 #endif 7024 } 7025 PetscFunctionReturn(PETSC_SUCCESS); 7026 } 7027 7028 /*@C 7029 MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms). 7030 7031 Collective 7032 7033 Input Parameters: 7034 + mat - the matrix 7035 . n - the number of submatrixes to be extracted 7036 . irow - index set of rows to extract 7037 . icol - index set of columns to extract 7038 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7039 7040 Output Parameter: 7041 . submat - the array of submatrices 7042 7043 Level: advanced 7044 7045 Note: 7046 This is used by `PCGASM` 7047 7048 .seealso: [](chapter_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7049 @*/ 7050 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7051 { 7052 PetscInt i; 7053 PetscBool eq; 7054 7055 PetscFunctionBegin; 7056 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7057 PetscValidType(mat, 1); 7058 if (n) { 7059 PetscValidPointer(irow, 3); 7060 PetscValidHeaderSpecific(*irow, IS_CLASSID, 3); 7061 PetscValidPointer(icol, 4); 7062 PetscValidHeaderSpecific(*icol, IS_CLASSID, 4); 7063 } 7064 PetscValidPointer(submat, 6); 7065 if (n && scall == MAT_REUSE_MATRIX) { 7066 PetscValidPointer(*submat, 6); 7067 PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6); 7068 } 7069 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7070 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7071 MatCheckPreallocated(mat, 1); 7072 7073 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7074 PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat); 7075 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7076 for (i = 0; i < n; i++) { 7077 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7078 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7079 } 7080 PetscFunctionReturn(PETSC_SUCCESS); 7081 } 7082 7083 /*@C 7084 MatDestroyMatrices - Destroys an array of matrices. 7085 7086 Collective 7087 7088 Input Parameters: 7089 + n - the number of local matrices 7090 - mat - the matrices (this is a pointer to the array of matrices) 7091 7092 Level: advanced 7093 7094 Note: 7095 Frees not only the matrices, but also the array that contains the matrices 7096 7097 Fortran Note: 7098 This does not free the array. 7099 7100 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()` 7101 @*/ 7102 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[]) 7103 { 7104 PetscInt i; 7105 7106 PetscFunctionBegin; 7107 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7108 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7109 PetscValidPointer(mat, 2); 7110 7111 for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i])); 7112 7113 /* memory is allocated even if n = 0 */ 7114 PetscCall(PetscFree(*mat)); 7115 PetscFunctionReturn(PETSC_SUCCESS); 7116 } 7117 7118 /*@C 7119 MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`. 7120 7121 Collective 7122 7123 Input Parameters: 7124 + n - the number of local matrices 7125 - mat - the matrices (this is a pointer to the array of matrices, just to match the calling 7126 sequence of `MatCreateSubMatrices()`) 7127 7128 Level: advanced 7129 7130 Note: 7131 Frees not only the matrices, but also the array that contains the matrices 7132 7133 Fortran Note: 7134 This does not free the array. 7135 7136 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7137 @*/ 7138 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[]) 7139 { 7140 Mat mat0; 7141 7142 PetscFunctionBegin; 7143 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7144 /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */ 7145 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7146 PetscValidPointer(mat, 2); 7147 7148 mat0 = (*mat)[0]; 7149 if (mat0 && mat0->ops->destroysubmatrices) { 7150 PetscCall((*mat0->ops->destroysubmatrices)(n, mat)); 7151 } else { 7152 PetscCall(MatDestroyMatrices(n, mat)); 7153 } 7154 PetscFunctionReturn(PETSC_SUCCESS); 7155 } 7156 7157 /*@C 7158 MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process 7159 7160 Collective 7161 7162 Input Parameter: 7163 . mat - the matrix 7164 7165 Output Parameter: 7166 . matstruct - the sequential matrix with the nonzero structure of mat 7167 7168 Level: developer 7169 7170 .seealso: [](chapter_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7171 @*/ 7172 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct) 7173 { 7174 PetscFunctionBegin; 7175 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7176 PetscValidPointer(matstruct, 2); 7177 7178 PetscValidType(mat, 1); 7179 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7180 MatCheckPreallocated(mat, 1); 7181 7182 PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7183 PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct); 7184 PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7185 PetscFunctionReturn(PETSC_SUCCESS); 7186 } 7187 7188 /*@C 7189 MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`. 7190 7191 Collective 7192 7193 Input Parameter: 7194 . mat - the matrix (this is a pointer to the array of matrices, just to match the calling 7195 sequence of `MatGetSeqNonzeroStructure()`) 7196 7197 Level: advanced 7198 7199 Note: 7200 Frees not only the matrices, but also the array that contains the matrices 7201 7202 .seealso: [](chapter_matrices), `Mat`, `MatGetSeqNonzeroStructure()` 7203 @*/ 7204 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat) 7205 { 7206 PetscFunctionBegin; 7207 PetscValidPointer(mat, 1); 7208 PetscCall(MatDestroy(mat)); 7209 PetscFunctionReturn(PETSC_SUCCESS); 7210 } 7211 7212 /*@ 7213 MatIncreaseOverlap - Given a set of submatrices indicated by index sets, 7214 replaces the index sets by larger ones that represent submatrices with 7215 additional overlap. 7216 7217 Collective 7218 7219 Input Parameters: 7220 + mat - the matrix 7221 . n - the number of index sets 7222 . is - the array of index sets (these index sets will changed during the call) 7223 - ov - the additional overlap requested 7224 7225 Options Database Key: 7226 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7227 7228 Level: developer 7229 7230 Note: 7231 The computed overlap preserves the matrix block sizes when the blocks are square. 7232 That is: if a matrix nonzero for a given block would increase the overlap all columns associated with 7233 that block are included in the overlap regardless of whether each specific column would increase the overlap. 7234 7235 .seealso: [](chapter_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()` 7236 @*/ 7237 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov) 7238 { 7239 PetscInt i, bs, cbs; 7240 7241 PetscFunctionBegin; 7242 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7243 PetscValidType(mat, 1); 7244 PetscValidLogicalCollectiveInt(mat, n, 2); 7245 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7246 if (n) { 7247 PetscValidPointer(is, 3); 7248 for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3); 7249 } 7250 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7251 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7252 MatCheckPreallocated(mat, 1); 7253 7254 if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS); 7255 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7256 PetscUseTypeMethod(mat, increaseoverlap, n, is, ov); 7257 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7258 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 7259 if (bs == cbs) { 7260 for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs)); 7261 } 7262 PetscFunctionReturn(PETSC_SUCCESS); 7263 } 7264 7265 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt); 7266 7267 /*@ 7268 MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across 7269 a sub communicator, replaces the index sets by larger ones that represent submatrices with 7270 additional overlap. 7271 7272 Collective 7273 7274 Input Parameters: 7275 + mat - the matrix 7276 . n - the number of index sets 7277 . is - the array of index sets (these index sets will changed during the call) 7278 - ov - the additional overlap requested 7279 7280 ` Options Database Key: 7281 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7282 7283 Level: developer 7284 7285 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()` 7286 @*/ 7287 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov) 7288 { 7289 PetscInt i; 7290 7291 PetscFunctionBegin; 7292 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7293 PetscValidType(mat, 1); 7294 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7295 if (n) { 7296 PetscValidPointer(is, 3); 7297 PetscValidHeaderSpecific(*is, IS_CLASSID, 3); 7298 } 7299 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7300 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7301 MatCheckPreallocated(mat, 1); 7302 if (!ov) PetscFunctionReturn(PETSC_SUCCESS); 7303 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7304 for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov)); 7305 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7306 PetscFunctionReturn(PETSC_SUCCESS); 7307 } 7308 7309 /*@ 7310 MatGetBlockSize - Returns the matrix block size. 7311 7312 Not Collective 7313 7314 Input Parameter: 7315 . mat - the matrix 7316 7317 Output Parameter: 7318 . bs - block size 7319 7320 Level: intermediate 7321 7322 Notes: 7323 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7324 7325 If the block size has not been set yet this routine returns 1. 7326 7327 .seealso: [](chapter_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()` 7328 @*/ 7329 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs) 7330 { 7331 PetscFunctionBegin; 7332 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7333 PetscValidIntPointer(bs, 2); 7334 *bs = PetscAbs(mat->rmap->bs); 7335 PetscFunctionReturn(PETSC_SUCCESS); 7336 } 7337 7338 /*@ 7339 MatGetBlockSizes - Returns the matrix block row and column sizes. 7340 7341 Not Collective 7342 7343 Input Parameter: 7344 . mat - the matrix 7345 7346 Output Parameters: 7347 + rbs - row block size 7348 - cbs - column block size 7349 7350 Level: intermediate 7351 7352 Notes: 7353 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7354 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7355 7356 If a block size has not been set yet this routine returns 1. 7357 7358 .seealso: [](chapter_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()` 7359 @*/ 7360 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs) 7361 { 7362 PetscFunctionBegin; 7363 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7364 if (rbs) PetscValidIntPointer(rbs, 2); 7365 if (cbs) PetscValidIntPointer(cbs, 3); 7366 if (rbs) *rbs = PetscAbs(mat->rmap->bs); 7367 if (cbs) *cbs = PetscAbs(mat->cmap->bs); 7368 PetscFunctionReturn(PETSC_SUCCESS); 7369 } 7370 7371 /*@ 7372 MatSetBlockSize - Sets the matrix block size. 7373 7374 Logically Collective 7375 7376 Input Parameters: 7377 + mat - the matrix 7378 - bs - block size 7379 7380 Level: intermediate 7381 7382 Notes: 7383 Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix. 7384 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7385 7386 For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size 7387 is compatible with the matrix local sizes. 7388 7389 .seealso: [](chapter_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()` 7390 @*/ 7391 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs) 7392 { 7393 PetscFunctionBegin; 7394 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7395 PetscValidLogicalCollectiveInt(mat, bs, 2); 7396 PetscCall(MatSetBlockSizes(mat, bs, bs)); 7397 PetscFunctionReturn(PETSC_SUCCESS); 7398 } 7399 7400 typedef struct { 7401 PetscInt n; 7402 IS *is; 7403 Mat *mat; 7404 PetscObjectState nonzerostate; 7405 Mat C; 7406 } EnvelopeData; 7407 7408 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata) 7409 { 7410 for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i])); 7411 PetscCall(PetscFree(edata->is)); 7412 PetscCall(PetscFree(edata)); 7413 return PETSC_SUCCESS; 7414 } 7415 7416 /* 7417 MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores 7418 the sizes of these blocks in the matrix. An individual block may lie over several processes. 7419 7420 Collective 7421 7422 Input Parameter: 7423 . mat - the matrix 7424 7425 Notes: 7426 There can be zeros within the blocks 7427 7428 The blocks can overlap between processes, including laying on more than two processes 7429 7430 .seealso: [](chapter_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()` 7431 */ 7432 static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat) 7433 { 7434 PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend; 7435 PetscInt *diag, *odiag, sc; 7436 VecScatter scatter; 7437 PetscScalar *seqv; 7438 const PetscScalar *parv; 7439 const PetscInt *ia, *ja; 7440 PetscBool set, flag, done; 7441 Mat AA = mat, A; 7442 MPI_Comm comm; 7443 PetscMPIInt rank, size, tag; 7444 MPI_Status status; 7445 PetscContainer container; 7446 EnvelopeData *edata; 7447 Vec seq, par; 7448 IS isglobal; 7449 7450 PetscFunctionBegin; 7451 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7452 PetscCall(MatIsSymmetricKnown(mat, &set, &flag)); 7453 if (!set || !flag) { 7454 /* TOO: only needs nonzero structure of transpose */ 7455 PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA)); 7456 PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN)); 7457 } 7458 PetscCall(MatAIJGetLocalMat(AA, &A)); 7459 PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7460 PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix"); 7461 7462 PetscCall(MatGetLocalSize(mat, &n, NULL)); 7463 PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag)); 7464 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 7465 PetscCallMPI(MPI_Comm_size(comm, &size)); 7466 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7467 7468 PetscCall(PetscMalloc2(n, &sizes, n, &starts)); 7469 7470 if (rank > 0) { 7471 PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7472 PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7473 } 7474 PetscCall(MatGetOwnershipRange(mat, &rstart, NULL)); 7475 for (i = 0; i < n; i++) { 7476 env = PetscMax(env, ja[ia[i + 1] - 1]); 7477 II = rstart + i; 7478 if (env == II) { 7479 starts[lblocks] = tbs; 7480 sizes[lblocks++] = 1 + II - tbs; 7481 tbs = 1 + II; 7482 } 7483 } 7484 if (rank < size - 1) { 7485 PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm)); 7486 PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm)); 7487 } 7488 7489 PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7490 if (!set || !flag) PetscCall(MatDestroy(&AA)); 7491 PetscCall(MatDestroy(&A)); 7492 7493 PetscCall(PetscNew(&edata)); 7494 PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate)); 7495 edata->n = lblocks; 7496 /* create IS needed for extracting blocks from the original matrix */ 7497 PetscCall(PetscMalloc1(lblocks, &edata->is)); 7498 for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i])); 7499 7500 /* Create the resulting inverse matrix structure with preallocation information */ 7501 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C)); 7502 PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 7503 PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat)); 7504 PetscCall(MatSetType(edata->C, MATAIJ)); 7505 7506 /* Communicate the start and end of each row, from each block to the correct rank */ 7507 /* TODO: Use PetscSF instead of VecScatter */ 7508 for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i]; 7509 PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq)); 7510 PetscCall(VecGetArrayWrite(seq, &seqv)); 7511 for (PetscInt i = 0; i < lblocks; i++) { 7512 for (PetscInt j = 0; j < sizes[i]; j++) { 7513 seqv[cnt] = starts[i]; 7514 seqv[cnt + 1] = starts[i] + sizes[i]; 7515 cnt += 2; 7516 } 7517 } 7518 PetscCall(VecRestoreArrayWrite(seq, &seqv)); 7519 PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 7520 sc -= cnt; 7521 PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par)); 7522 PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal)); 7523 PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter)); 7524 PetscCall(ISDestroy(&isglobal)); 7525 PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7526 PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7527 PetscCall(VecScatterDestroy(&scatter)); 7528 PetscCall(VecDestroy(&seq)); 7529 PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend)); 7530 PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag)); 7531 PetscCall(VecGetArrayRead(par, &parv)); 7532 cnt = 0; 7533 PetscCall(MatGetSize(mat, NULL, &n)); 7534 for (PetscInt i = 0; i < mat->rmap->n; i++) { 7535 PetscInt start, end, d = 0, od = 0; 7536 7537 start = (PetscInt)PetscRealPart(parv[cnt]); 7538 end = (PetscInt)PetscRealPart(parv[cnt + 1]); 7539 cnt += 2; 7540 7541 if (start < cstart) { 7542 od += cstart - start + n - cend; 7543 d += cend - cstart; 7544 } else if (start < cend) { 7545 od += n - cend; 7546 d += cend - start; 7547 } else od += n - start; 7548 if (end <= cstart) { 7549 od -= cstart - end + n - cend; 7550 d -= cend - cstart; 7551 } else if (end < cend) { 7552 od -= n - cend; 7553 d -= cend - end; 7554 } else od -= n - end; 7555 7556 odiag[i] = od; 7557 diag[i] = d; 7558 } 7559 PetscCall(VecRestoreArrayRead(par, &parv)); 7560 PetscCall(VecDestroy(&par)); 7561 PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL)); 7562 PetscCall(PetscFree2(diag, odiag)); 7563 PetscCall(PetscFree2(sizes, starts)); 7564 7565 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container)); 7566 PetscCall(PetscContainerSetPointer(container, edata)); 7567 PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy)); 7568 PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container)); 7569 PetscCall(PetscObjectDereference((PetscObject)container)); 7570 PetscFunctionReturn(PETSC_SUCCESS); 7571 } 7572 7573 /*@ 7574 MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A 7575 7576 Collective 7577 7578 Input Parameters: 7579 + A - the matrix 7580 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine 7581 7582 Output Parameter: 7583 . C - matrix with inverted block diagonal of `A` 7584 7585 Level: advanced 7586 7587 Note: 7588 For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal. 7589 7590 .seealso: [](chapter_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()` 7591 @*/ 7592 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C) 7593 { 7594 PetscContainer container; 7595 EnvelopeData *edata; 7596 PetscObjectState nonzerostate; 7597 7598 PetscFunctionBegin; 7599 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7600 if (!container) { 7601 PetscCall(MatComputeVariableBlockEnvelope(A)); 7602 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7603 } 7604 PetscCall(PetscContainerGetPointer(container, (void **)&edata)); 7605 PetscCall(MatGetNonzeroState(A, &nonzerostate)); 7606 PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure"); 7607 PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output"); 7608 7609 PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat)); 7610 *C = edata->C; 7611 7612 for (PetscInt i = 0; i < edata->n; i++) { 7613 Mat D; 7614 PetscScalar *dvalues; 7615 7616 PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D)); 7617 PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE)); 7618 PetscCall(MatSeqDenseInvert(D)); 7619 PetscCall(MatDenseGetArray(D, &dvalues)); 7620 PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES)); 7621 PetscCall(MatDestroy(&D)); 7622 } 7623 PetscCall(MatDestroySubMatrices(edata->n, &edata->mat)); 7624 PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY)); 7625 PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY)); 7626 PetscFunctionReturn(PETSC_SUCCESS); 7627 } 7628 7629 /*@ 7630 MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size 7631 7632 Logically Collective 7633 7634 Input Parameters: 7635 + mat - the matrix 7636 . nblocks - the number of blocks on this process, each block can only exist on a single process 7637 - bsizes - the block sizes 7638 7639 Level: intermediate 7640 7641 Notes: 7642 Currently used by `PCVPBJACOBI` for `MATAIJ` matrices 7643 7644 Each variable point-block set of degrees of freedom must live on a single MPI rank. That is a point block cannot straddle two MPI ranks. 7645 7646 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, 7647 `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI` 7648 @*/ 7649 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes) 7650 { 7651 PetscInt i, ncnt = 0, nlocal; 7652 7653 PetscFunctionBegin; 7654 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7655 PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero"); 7656 PetscCall(MatGetLocalSize(mat, &nlocal, NULL)); 7657 for (i = 0; i < nblocks; i++) ncnt += bsizes[i]; 7658 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); 7659 PetscCall(PetscFree(mat->bsizes)); 7660 mat->nblocks = nblocks; 7661 PetscCall(PetscMalloc1(nblocks, &mat->bsizes)); 7662 PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks)); 7663 PetscFunctionReturn(PETSC_SUCCESS); 7664 } 7665 7666 /*@C 7667 MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size 7668 7669 Logically Collective; No Fortran Support 7670 7671 Input Parameter: 7672 . mat - the matrix 7673 7674 Output Parameters: 7675 + nblocks - the number of blocks on this process 7676 - bsizes - the block sizes 7677 7678 Level: intermediate 7679 7680 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()` 7681 @*/ 7682 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes) 7683 { 7684 PetscFunctionBegin; 7685 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7686 *nblocks = mat->nblocks; 7687 *bsizes = mat->bsizes; 7688 PetscFunctionReturn(PETSC_SUCCESS); 7689 } 7690 7691 /*@ 7692 MatSetBlockSizes - Sets the matrix block row and column sizes. 7693 7694 Logically Collective 7695 7696 Input Parameters: 7697 + mat - the matrix 7698 . rbs - row block size 7699 - cbs - column block size 7700 7701 Level: intermediate 7702 7703 Notes: 7704 Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix. 7705 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7706 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7707 7708 For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes 7709 are compatible with the matrix local sizes. 7710 7711 The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`. 7712 7713 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()` 7714 @*/ 7715 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs) 7716 { 7717 PetscFunctionBegin; 7718 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7719 PetscValidLogicalCollectiveInt(mat, rbs, 2); 7720 PetscValidLogicalCollectiveInt(mat, cbs, 3); 7721 PetscTryTypeMethod(mat, setblocksizes, rbs, cbs); 7722 if (mat->rmap->refcnt) { 7723 ISLocalToGlobalMapping l2g = NULL; 7724 PetscLayout nmap = NULL; 7725 7726 PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap)); 7727 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g)); 7728 PetscCall(PetscLayoutDestroy(&mat->rmap)); 7729 mat->rmap = nmap; 7730 mat->rmap->mapping = l2g; 7731 } 7732 if (mat->cmap->refcnt) { 7733 ISLocalToGlobalMapping l2g = NULL; 7734 PetscLayout nmap = NULL; 7735 7736 PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap)); 7737 if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g)); 7738 PetscCall(PetscLayoutDestroy(&mat->cmap)); 7739 mat->cmap = nmap; 7740 mat->cmap->mapping = l2g; 7741 } 7742 PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs)); 7743 PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs)); 7744 PetscFunctionReturn(PETSC_SUCCESS); 7745 } 7746 7747 /*@ 7748 MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices 7749 7750 Logically Collective 7751 7752 Input Parameters: 7753 + mat - the matrix 7754 . fromRow - matrix from which to copy row block size 7755 - fromCol - matrix from which to copy column block size (can be same as fromRow) 7756 7757 Level: developer 7758 7759 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()` 7760 @*/ 7761 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol) 7762 { 7763 PetscFunctionBegin; 7764 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7765 PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2); 7766 PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3); 7767 if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs)); 7768 if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs)); 7769 PetscFunctionReturn(PETSC_SUCCESS); 7770 } 7771 7772 /*@ 7773 MatResidual - Default routine to calculate the residual r = b - Ax 7774 7775 Collective 7776 7777 Input Parameters: 7778 + mat - the matrix 7779 . b - the right-hand-side 7780 - x - the approximate solution 7781 7782 Output Parameter: 7783 . r - location to store the residual 7784 7785 Level: developer 7786 7787 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()` 7788 @*/ 7789 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r) 7790 { 7791 PetscFunctionBegin; 7792 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7793 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 7794 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 7795 PetscValidHeaderSpecific(r, VEC_CLASSID, 4); 7796 PetscValidType(mat, 1); 7797 MatCheckPreallocated(mat, 1); 7798 PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0)); 7799 if (!mat->ops->residual) { 7800 PetscCall(MatMult(mat, x, r)); 7801 PetscCall(VecAYPX(r, -1.0, b)); 7802 } else { 7803 PetscUseTypeMethod(mat, residual, b, x, r); 7804 } 7805 PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0)); 7806 PetscFunctionReturn(PETSC_SUCCESS); 7807 } 7808 7809 /*MC 7810 MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix 7811 7812 Synopsis: 7813 MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 7814 7815 Not Collective 7816 7817 Input Parameters: 7818 + A - the matrix 7819 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7820 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7821 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7822 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7823 always used. 7824 7825 Output Parameters: 7826 + n - number of local rows in the (possibly compressed) matrix 7827 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 7828 . ja - the column indices 7829 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7830 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7831 7832 Level: developer 7833 7834 Note: 7835 Use `MatRestoreRowIJF90()` when you no longer need access to the data 7836 7837 .seealso: [](chapter_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()` 7838 M*/ 7839 7840 /*MC 7841 MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()` 7842 7843 Synopsis: 7844 MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 7845 7846 Not Collective 7847 7848 Input Parameters: 7849 + A - the matrix 7850 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7851 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7852 inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7853 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7854 always used. 7855 . n - number of local rows in the (possibly compressed) matrix 7856 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 7857 . ja - the column indices 7858 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7859 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7860 7861 Level: developer 7862 7863 .seealso: [](chapter_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()` 7864 M*/ 7865 7866 /*@C 7867 MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix 7868 7869 Collective 7870 7871 Input Parameters: 7872 + mat - the matrix 7873 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7874 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7875 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7876 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7877 always used. 7878 7879 Output Parameters: 7880 + n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed 7881 . 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 7882 . ja - the column indices, use `NULL` if not needed 7883 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7884 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7885 7886 Level: developer 7887 7888 Notes: 7889 You CANNOT change any of the ia[] or ja[] values. 7890 7891 Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values. 7892 7893 Fortran Notes: 7894 Use 7895 .vb 7896 PetscInt, pointer :: ia(:),ja(:) 7897 call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr) 7898 ! Access the ith and jth entries via ia(i) and ja(j) 7899 .ve 7900 `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()` 7901 7902 .seealso: [](chapter_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()` 7903 @*/ 7904 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7905 { 7906 PetscFunctionBegin; 7907 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7908 PetscValidType(mat, 1); 7909 if (n) PetscValidIntPointer(n, 5); 7910 if (ia) PetscValidPointer(ia, 6); 7911 if (ja) PetscValidPointer(ja, 7); 7912 if (done) PetscValidBoolPointer(done, 8); 7913 MatCheckPreallocated(mat, 1); 7914 if (!mat->ops->getrowij && done) *done = PETSC_FALSE; 7915 else { 7916 if (done) *done = PETSC_TRUE; 7917 PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0)); 7918 PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done); 7919 PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0)); 7920 } 7921 PetscFunctionReturn(PETSC_SUCCESS); 7922 } 7923 7924 /*@C 7925 MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices. 7926 7927 Collective 7928 7929 Input Parameters: 7930 + mat - the matrix 7931 . shift - 1 or zero indicating we want the indices starting at 0 or 1 7932 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be 7933 symmetrized 7934 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7935 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7936 always used. 7937 . n - number of columns in the (possibly compressed) matrix 7938 . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix 7939 - ja - the row indices 7940 7941 Output Parameter: 7942 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned 7943 7944 Level: developer 7945 7946 .seealso: [](chapter_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 7947 @*/ 7948 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7949 { 7950 PetscFunctionBegin; 7951 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7952 PetscValidType(mat, 1); 7953 PetscValidIntPointer(n, 5); 7954 if (ia) PetscValidPointer(ia, 6); 7955 if (ja) PetscValidPointer(ja, 7); 7956 PetscValidBoolPointer(done, 8); 7957 MatCheckPreallocated(mat, 1); 7958 if (!mat->ops->getcolumnij) *done = PETSC_FALSE; 7959 else { 7960 *done = PETSC_TRUE; 7961 PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 7962 } 7963 PetscFunctionReturn(PETSC_SUCCESS); 7964 } 7965 7966 /*@C 7967 MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`. 7968 7969 Collective 7970 7971 Input Parameters: 7972 + mat - the matrix 7973 . shift - 1 or zero indicating we want the indices starting at 0 or 1 7974 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7975 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7976 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7977 always used. 7978 . n - size of (possibly compressed) matrix 7979 . ia - the row pointers 7980 - ja - the column indices 7981 7982 Output Parameter: 7983 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 7984 7985 Level: developer 7986 7987 Note: 7988 This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental 7989 us of the array after it has been restored. If you pass `NULL`, it will 7990 not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid. 7991 7992 Fortran Note: 7993 `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()` 7994 7995 .seealso: [](chapter_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()` 7996 @*/ 7997 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7998 { 7999 PetscFunctionBegin; 8000 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8001 PetscValidType(mat, 1); 8002 if (ia) PetscValidPointer(ia, 6); 8003 if (ja) PetscValidPointer(ja, 7); 8004 if (done) PetscValidBoolPointer(done, 8); 8005 MatCheckPreallocated(mat, 1); 8006 8007 if (!mat->ops->restorerowij && done) *done = PETSC_FALSE; 8008 else { 8009 if (done) *done = PETSC_TRUE; 8010 PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8011 if (n) *n = 0; 8012 if (ia) *ia = NULL; 8013 if (ja) *ja = NULL; 8014 } 8015 PetscFunctionReturn(PETSC_SUCCESS); 8016 } 8017 8018 /*@C 8019 MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`. 8020 8021 Collective 8022 8023 Input Parameters: 8024 + mat - the matrix 8025 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8026 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8027 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8028 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8029 always used. 8030 8031 Output Parameters: 8032 + n - size of (possibly compressed) matrix 8033 . ia - the column pointers 8034 . ja - the row indices 8035 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8036 8037 Level: developer 8038 8039 .seealso: [](chapter_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()` 8040 @*/ 8041 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8042 { 8043 PetscFunctionBegin; 8044 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8045 PetscValidType(mat, 1); 8046 if (ia) PetscValidPointer(ia, 6); 8047 if (ja) PetscValidPointer(ja, 7); 8048 PetscValidBoolPointer(done, 8); 8049 MatCheckPreallocated(mat, 1); 8050 8051 if (!mat->ops->restorecolumnij) *done = PETSC_FALSE; 8052 else { 8053 *done = PETSC_TRUE; 8054 PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8055 if (n) *n = 0; 8056 if (ia) *ia = NULL; 8057 if (ja) *ja = NULL; 8058 } 8059 PetscFunctionReturn(PETSC_SUCCESS); 8060 } 8061 8062 /*@C 8063 MatColoringPatch -Used inside matrix coloring routines that use `MatGetRowIJ()` and/or `MatGetColumnIJ()`. 8064 8065 Collective 8066 8067 Input Parameters: 8068 + mat - the matrix 8069 . ncolors - maximum color value 8070 . n - number of entries in colorarray 8071 - colorarray - array indicating color for each column 8072 8073 Output Parameter: 8074 . iscoloring - coloring generated using colorarray information 8075 8076 Level: developer 8077 8078 .seealso: [](chapter_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()` 8079 @*/ 8080 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring) 8081 { 8082 PetscFunctionBegin; 8083 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8084 PetscValidType(mat, 1); 8085 PetscValidIntPointer(colorarray, 4); 8086 PetscValidPointer(iscoloring, 5); 8087 MatCheckPreallocated(mat, 1); 8088 8089 if (!mat->ops->coloringpatch) { 8090 PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring)); 8091 } else { 8092 PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring); 8093 } 8094 PetscFunctionReturn(PETSC_SUCCESS); 8095 } 8096 8097 /*@ 8098 MatSetUnfactored - Resets a factored matrix to be treated as unfactored. 8099 8100 Logically Collective 8101 8102 Input Parameter: 8103 . mat - the factored matrix to be reset 8104 8105 Level: developer 8106 8107 Notes: 8108 This routine should be used only with factored matrices formed by in-place 8109 factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE` 8110 format). This option can save memory, for example, when solving nonlinear 8111 systems with a matrix-free Newton-Krylov method and a matrix-based, in-place 8112 ILU(0) preconditioner. 8113 8114 One can specify in-place ILU(0) factorization by calling 8115 .vb 8116 PCType(pc,PCILU); 8117 PCFactorSeUseInPlace(pc); 8118 .ve 8119 or by using the options -pc_type ilu -pc_factor_in_place 8120 8121 In-place factorization ILU(0) can also be used as a local 8122 solver for the blocks within the block Jacobi or additive Schwarz 8123 methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc 8124 for details on setting local solver options. 8125 8126 Most users should employ the `KSP` interface for linear solvers 8127 instead of working directly with matrix algebra routines such as this. 8128 See, e.g., `KSPCreate()`. 8129 8130 .seealso: [](chapter_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()` 8131 @*/ 8132 PetscErrorCode MatSetUnfactored(Mat mat) 8133 { 8134 PetscFunctionBegin; 8135 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8136 PetscValidType(mat, 1); 8137 MatCheckPreallocated(mat, 1); 8138 mat->factortype = MAT_FACTOR_NONE; 8139 if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS); 8140 PetscUseTypeMethod(mat, setunfactored); 8141 PetscFunctionReturn(PETSC_SUCCESS); 8142 } 8143 8144 /*MC 8145 MatDenseGetArrayF90 - Accesses a matrix array from Fortran 8146 8147 Synopsis: 8148 MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8149 8150 Not Collective 8151 8152 Input Parameter: 8153 . x - matrix 8154 8155 Output Parameters: 8156 + xx_v - the Fortran pointer to the array 8157 - ierr - error code 8158 8159 Example of Usage: 8160 .vb 8161 PetscScalar, pointer xx_v(:,:) 8162 .... 8163 call MatDenseGetArrayF90(x,xx_v,ierr) 8164 a = xx_v(3) 8165 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8166 .ve 8167 8168 Level: advanced 8169 8170 .seealso: [](chapter_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()` 8171 M*/ 8172 8173 /*MC 8174 MatDenseRestoreArrayF90 - Restores a matrix array that has been 8175 accessed with `MatDenseGetArrayF90()`. 8176 8177 Synopsis: 8178 MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8179 8180 Not Collective 8181 8182 Input Parameters: 8183 + x - matrix 8184 - xx_v - the Fortran90 pointer to the array 8185 8186 Output Parameter: 8187 . ierr - error code 8188 8189 Example of Usage: 8190 .vb 8191 PetscScalar, pointer xx_v(:,:) 8192 .... 8193 call MatDenseGetArrayF90(x,xx_v,ierr) 8194 a = xx_v(3) 8195 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8196 .ve 8197 8198 Level: advanced 8199 8200 .seealso: [](chapter_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()` 8201 M*/ 8202 8203 /*MC 8204 MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran. 8205 8206 Synopsis: 8207 MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8208 8209 Not Collective 8210 8211 Input Parameter: 8212 . x - matrix 8213 8214 Output Parameters: 8215 + xx_v - the Fortran pointer to the array 8216 - ierr - error code 8217 8218 Example of Usage: 8219 .vb 8220 PetscScalar, pointer xx_v(:) 8221 .... 8222 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8223 a = xx_v(3) 8224 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8225 .ve 8226 8227 Level: advanced 8228 8229 .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()` 8230 M*/ 8231 8232 /*MC 8233 MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been 8234 accessed with `MatSeqAIJGetArrayF90()`. 8235 8236 Synopsis: 8237 MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8238 8239 Not Collective 8240 8241 Input Parameters: 8242 + x - matrix 8243 - xx_v - the Fortran90 pointer to the array 8244 8245 Output Parameter: 8246 . ierr - error code 8247 8248 Example of Usage: 8249 .vb 8250 PetscScalar, pointer xx_v(:) 8251 .... 8252 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8253 a = xx_v(3) 8254 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8255 .ve 8256 8257 Level: advanced 8258 8259 .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()` 8260 M*/ 8261 8262 /*@ 8263 MatCreateSubMatrix - Gets a single submatrix on the same number of processors 8264 as the original matrix. 8265 8266 Collective 8267 8268 Input Parameters: 8269 + mat - the original matrix 8270 . isrow - parallel `IS` containing the rows this processor should obtain 8271 . 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. 8272 - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 8273 8274 Output Parameter: 8275 . newmat - the new submatrix, of the same type as the original matrix 8276 8277 Level: advanced 8278 8279 Notes: 8280 The submatrix will be able to be multiplied with vectors using the same layout as `iscol`. 8281 8282 Some matrix types place restrictions on the row and column indices, such 8283 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; 8284 for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row. 8285 8286 The index sets may not have duplicate entries. 8287 8288 The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`, 8289 the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls 8290 to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX` 8291 will reuse the matrix generated the first time. You should call `MatDestroy()` on `newmat` when 8292 you are finished using it. 8293 8294 The communicator of the newly obtained matrix is ALWAYS the same as the communicator of 8295 the input matrix. 8296 8297 If `iscol` is `NULL` then all columns are obtained (not supported in Fortran). 8298 8299 Example usage: 8300 Consider the following 8x8 matrix with 34 non-zero values, that is 8301 assembled across 3 processors. Let's assume that proc0 owns 3 rows, 8302 proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 8303 as follows 8304 .vb 8305 1 2 0 | 0 3 0 | 0 4 8306 Proc0 0 5 6 | 7 0 0 | 8 0 8307 9 0 10 | 11 0 0 | 12 0 8308 ------------------------------------- 8309 13 0 14 | 15 16 17 | 0 0 8310 Proc1 0 18 0 | 19 20 21 | 0 0 8311 0 0 0 | 22 23 0 | 24 0 8312 ------------------------------------- 8313 Proc2 25 26 27 | 0 0 28 | 29 0 8314 30 0 0 | 31 32 33 | 0 34 8315 .ve 8316 8317 Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6]. The resulting submatrix is 8318 8319 .vb 8320 2 0 | 0 3 0 | 0 8321 Proc0 5 6 | 7 0 0 | 8 8322 ------------------------------- 8323 Proc1 18 0 | 19 20 21 | 0 8324 ------------------------------- 8325 Proc2 26 27 | 0 0 28 | 29 8326 0 0 | 31 32 33 | 0 8327 .ve 8328 8329 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()` 8330 @*/ 8331 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat) 8332 { 8333 PetscMPIInt size; 8334 Mat *local; 8335 IS iscoltmp; 8336 PetscBool flg; 8337 8338 PetscFunctionBegin; 8339 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8340 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 8341 if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 8342 PetscValidPointer(newmat, 5); 8343 if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5); 8344 PetscValidType(mat, 1); 8345 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8346 PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX"); 8347 8348 MatCheckPreallocated(mat, 1); 8349 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8350 8351 if (!iscol || isrow == iscol) { 8352 PetscBool stride; 8353 PetscMPIInt grabentirematrix = 0, grab; 8354 PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride)); 8355 if (stride) { 8356 PetscInt first, step, n, rstart, rend; 8357 PetscCall(ISStrideGetInfo(isrow, &first, &step)); 8358 if (step == 1) { 8359 PetscCall(MatGetOwnershipRange(mat, &rstart, &rend)); 8360 if (rstart == first) { 8361 PetscCall(ISGetLocalSize(isrow, &n)); 8362 if (n == rend - rstart) grabentirematrix = 1; 8363 } 8364 } 8365 } 8366 PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat))); 8367 if (grab) { 8368 PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n")); 8369 if (cll == MAT_INITIAL_MATRIX) { 8370 *newmat = mat; 8371 PetscCall(PetscObjectReference((PetscObject)mat)); 8372 } 8373 PetscFunctionReturn(PETSC_SUCCESS); 8374 } 8375 } 8376 8377 if (!iscol) { 8378 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp)); 8379 } else { 8380 iscoltmp = iscol; 8381 } 8382 8383 /* if original matrix is on just one processor then use submatrix generated */ 8384 if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) { 8385 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat)); 8386 goto setproperties; 8387 } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) { 8388 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local)); 8389 *newmat = *local; 8390 PetscCall(PetscFree(local)); 8391 goto setproperties; 8392 } else if (!mat->ops->createsubmatrix) { 8393 /* Create a new matrix type that implements the operation using the full matrix */ 8394 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8395 switch (cll) { 8396 case MAT_INITIAL_MATRIX: 8397 PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat)); 8398 break; 8399 case MAT_REUSE_MATRIX: 8400 PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp)); 8401 break; 8402 default: 8403 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX"); 8404 } 8405 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8406 goto setproperties; 8407 } 8408 8409 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8410 PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat); 8411 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8412 8413 setproperties: 8414 PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg)); 8415 if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat)); 8416 if (!iscol) PetscCall(ISDestroy(&iscoltmp)); 8417 if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat)); 8418 PetscFunctionReturn(PETSC_SUCCESS); 8419 } 8420 8421 /*@ 8422 MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix 8423 8424 Not Collective 8425 8426 Input Parameters: 8427 + A - the matrix we wish to propagate options from 8428 - B - the matrix we wish to propagate options to 8429 8430 Level: beginner 8431 8432 Note: 8433 Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL` 8434 8435 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, MatIsStructurallySymmetricKnown()` 8436 @*/ 8437 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B) 8438 { 8439 PetscFunctionBegin; 8440 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8441 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 8442 B->symmetry_eternal = A->symmetry_eternal; 8443 B->structural_symmetry_eternal = A->structural_symmetry_eternal; 8444 B->symmetric = A->symmetric; 8445 B->structurally_symmetric = A->structurally_symmetric; 8446 B->spd = A->spd; 8447 B->hermitian = A->hermitian; 8448 PetscFunctionReturn(PETSC_SUCCESS); 8449 } 8450 8451 /*@ 8452 MatStashSetInitialSize - sets the sizes of the matrix stash, that is 8453 used during the assembly process to store values that belong to 8454 other processors. 8455 8456 Not Collective 8457 8458 Input Parameters: 8459 + mat - the matrix 8460 . size - the initial size of the stash. 8461 - bsize - the initial size of the block-stash(if used). 8462 8463 Options Database Keys: 8464 + -matstash_initial_size <size> or <size0,size1,...sizep-1> 8465 - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1> 8466 8467 Level: intermediate 8468 8469 Notes: 8470 The block-stash is used for values set with `MatSetValuesBlocked()` while 8471 the stash is used for values set with `MatSetValues()` 8472 8473 Run with the option -info and look for output of the form 8474 MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs. 8475 to determine the appropriate value, MM, to use for size and 8476 MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs. 8477 to determine the value, BMM to use for bsize 8478 8479 .seealso: [](chapter_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()` 8480 @*/ 8481 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize) 8482 { 8483 PetscFunctionBegin; 8484 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8485 PetscValidType(mat, 1); 8486 PetscCall(MatStashSetInitialSize_Private(&mat->stash, size)); 8487 PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize)); 8488 PetscFunctionReturn(PETSC_SUCCESS); 8489 } 8490 8491 /*@ 8492 MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of 8493 the matrix 8494 8495 Neighbor-wise Collective 8496 8497 Input Parameters: 8498 + mat - the matrix 8499 . x - the vector to be multiplied by the interpolation operator 8500 - y - the vector to be added to the result 8501 8502 Output Parameter: 8503 . w - the resulting vector 8504 8505 Level: intermediate 8506 8507 Notes: 8508 `w` may be the same vector as `y`. 8509 8510 This allows one to use either the restriction or interpolation (its transpose) 8511 matrix to do the interpolation 8512 8513 .seealso: [](chapter_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8514 @*/ 8515 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w) 8516 { 8517 PetscInt M, N, Ny; 8518 8519 PetscFunctionBegin; 8520 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8521 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8522 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8523 PetscValidHeaderSpecific(w, VEC_CLASSID, 4); 8524 PetscCall(MatGetSize(A, &M, &N)); 8525 PetscCall(VecGetSize(y, &Ny)); 8526 if (M == Ny) { 8527 PetscCall(MatMultAdd(A, x, y, w)); 8528 } else { 8529 PetscCall(MatMultTransposeAdd(A, x, y, w)); 8530 } 8531 PetscFunctionReturn(PETSC_SUCCESS); 8532 } 8533 8534 /*@ 8535 MatInterpolate - y = A*x or A'*x depending on the shape of 8536 the matrix 8537 8538 Neighbor-wise Collective 8539 8540 Input Parameters: 8541 + mat - the matrix 8542 - x - the vector to be interpolated 8543 8544 Output Parameter: 8545 . y - the resulting vector 8546 8547 Level: intermediate 8548 8549 Note: 8550 This allows one to use either the restriction or interpolation (its transpose) 8551 matrix to do the interpolation 8552 8553 .seealso: [](chapter_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8554 @*/ 8555 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y) 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 PetscCall(MatGetSize(A, &M, &N)); 8564 PetscCall(VecGetSize(y, &Ny)); 8565 if (M == Ny) { 8566 PetscCall(MatMult(A, x, y)); 8567 } else { 8568 PetscCall(MatMultTranspose(A, x, y)); 8569 } 8570 PetscFunctionReturn(PETSC_SUCCESS); 8571 } 8572 8573 /*@ 8574 MatRestrict - y = A*x or A'*x 8575 8576 Neighbor-wise Collective 8577 8578 Input Parameters: 8579 + mat - the matrix 8580 - x - the vector to be restricted 8581 8582 Output Parameter: 8583 . y - the resulting vector 8584 8585 Level: intermediate 8586 8587 Note: 8588 This allows one to use either the restriction or interpolation (its transpose) 8589 matrix to do the restriction 8590 8591 .seealso: [](chapter_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG` 8592 @*/ 8593 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y) 8594 { 8595 PetscInt M, N, Ny; 8596 8597 PetscFunctionBegin; 8598 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8599 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8600 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8601 PetscCall(MatGetSize(A, &M, &N)); 8602 PetscCall(VecGetSize(y, &Ny)); 8603 if (M == Ny) { 8604 PetscCall(MatMult(A, x, y)); 8605 } else { 8606 PetscCall(MatMultTranspose(A, x, y)); 8607 } 8608 PetscFunctionReturn(PETSC_SUCCESS); 8609 } 8610 8611 /*@ 8612 MatMatInterpolateAdd - Y = W + A*X or W + A'*X 8613 8614 Neighbor-wise Collective 8615 8616 Input Parameters: 8617 + mat - the matrix 8618 . x - the input dense matrix to be multiplied 8619 - w - the input dense matrix to be added to the result 8620 8621 Output Parameter: 8622 . y - the output dense matrix 8623 8624 Level: intermediate 8625 8626 Note: 8627 This allows one to use either the restriction or interpolation (its transpose) 8628 matrix to do the interpolation. y matrix can be reused if already created with the proper sizes, 8629 otherwise it will be recreated. y must be initialized to `NULL` if not supplied. 8630 8631 .seealso: [](chapter_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG` 8632 @*/ 8633 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y) 8634 { 8635 PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0; 8636 PetscBool trans = PETSC_TRUE; 8637 MatReuse reuse = MAT_INITIAL_MATRIX; 8638 8639 PetscFunctionBegin; 8640 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8641 PetscValidHeaderSpecific(x, MAT_CLASSID, 2); 8642 PetscValidType(x, 2); 8643 if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3); 8644 if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4); 8645 PetscCall(MatGetSize(A, &M, &N)); 8646 PetscCall(MatGetSize(x, &Mx, &Nx)); 8647 if (N == Mx) trans = PETSC_FALSE; 8648 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); 8649 Mo = trans ? N : M; 8650 if (*y) { 8651 PetscCall(MatGetSize(*y, &My, &Ny)); 8652 if (Mo == My && Nx == Ny) { 8653 reuse = MAT_REUSE_MATRIX; 8654 } else { 8655 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); 8656 PetscCall(MatDestroy(y)); 8657 } 8658 } 8659 8660 if (w && *y == w) { /* this is to minimize changes in PCMG */ 8661 PetscBool flg; 8662 8663 PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w)); 8664 if (w) { 8665 PetscInt My, Ny, Mw, Nw; 8666 8667 PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg)); 8668 PetscCall(MatGetSize(*y, &My, &Ny)); 8669 PetscCall(MatGetSize(w, &Mw, &Nw)); 8670 if (!flg || My != Mw || Ny != Nw) w = NULL; 8671 } 8672 if (!w) { 8673 PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w)); 8674 PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w)); 8675 PetscCall(PetscObjectDereference((PetscObject)w)); 8676 } else { 8677 PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN)); 8678 } 8679 } 8680 if (!trans) { 8681 PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8682 } else { 8683 PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8684 } 8685 if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN)); 8686 PetscFunctionReturn(PETSC_SUCCESS); 8687 } 8688 8689 /*@ 8690 MatMatInterpolate - Y = A*X or A'*X 8691 8692 Neighbor-wise Collective 8693 8694 Input Parameters: 8695 + mat - the matrix 8696 - x - the input dense matrix 8697 8698 Output Parameter: 8699 . y - the output dense matrix 8700 8701 Level: intermediate 8702 8703 Note: 8704 This allows one to use either the restriction or interpolation (its transpose) 8705 matrix to do the interpolation. y matrix can be reused if already created with the proper sizes, 8706 otherwise it will be recreated. y must be initialized to `NULL` if not supplied. 8707 8708 .seealso: [](chapter_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG` 8709 @*/ 8710 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y) 8711 { 8712 PetscFunctionBegin; 8713 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8714 PetscFunctionReturn(PETSC_SUCCESS); 8715 } 8716 8717 /*@ 8718 MatMatRestrict - Y = A*X or A'*X 8719 8720 Neighbor-wise Collective 8721 8722 Input Parameters: 8723 + mat - the matrix 8724 - x - the input dense matrix 8725 8726 Output Parameter: 8727 . y - the output dense matrix 8728 8729 Level: intermediate 8730 8731 Note: 8732 This allows one to use either the restriction or interpolation (its transpose) 8733 matrix to do the restriction. y matrix can be reused if already created with the proper sizes, 8734 otherwise it will be recreated. y must be initialized to `NULL` if not supplied. 8735 8736 .seealso: [](chapter_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG` 8737 @*/ 8738 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y) 8739 { 8740 PetscFunctionBegin; 8741 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8742 PetscFunctionReturn(PETSC_SUCCESS); 8743 } 8744 8745 /*@ 8746 MatGetNullSpace - retrieves the null space of a matrix. 8747 8748 Logically Collective 8749 8750 Input Parameters: 8751 + mat - the matrix 8752 - nullsp - the null space object 8753 8754 Level: developer 8755 8756 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace` 8757 @*/ 8758 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp) 8759 { 8760 PetscFunctionBegin; 8761 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8762 PetscValidPointer(nullsp, 2); 8763 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp; 8764 PetscFunctionReturn(PETSC_SUCCESS); 8765 } 8766 8767 /*@ 8768 MatSetNullSpace - attaches a null space to a matrix. 8769 8770 Logically Collective 8771 8772 Input Parameters: 8773 + mat - the matrix 8774 - nullsp - the null space object 8775 8776 Level: advanced 8777 8778 Notes: 8779 This null space is used by the `KSP` linear solvers to solve singular systems. 8780 8781 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` 8782 8783 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 8784 to zero but the linear system will still be solved in a least squares sense. 8785 8786 The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that 8787 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). 8788 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 8789 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 8790 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). 8791 This \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix. 8792 8793 If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called 8794 `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this 8795 routine also automatically calls `MatSetTransposeNullSpace()`. 8796 8797 The user should call `MatNullSpaceDestroy()`. 8798 8799 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, 8800 `KSPSetPCSide()` 8801 @*/ 8802 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp) 8803 { 8804 PetscFunctionBegin; 8805 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8806 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8807 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8808 PetscCall(MatNullSpaceDestroy(&mat->nullsp)); 8809 mat->nullsp = nullsp; 8810 if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp)); 8811 PetscFunctionReturn(PETSC_SUCCESS); 8812 } 8813 8814 /*@ 8815 MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix. 8816 8817 Logically Collective 8818 8819 Input Parameters: 8820 + mat - the matrix 8821 - nullsp - the null space object 8822 8823 Level: developer 8824 8825 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()` 8826 @*/ 8827 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp) 8828 { 8829 PetscFunctionBegin; 8830 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8831 PetscValidType(mat, 1); 8832 PetscValidPointer(nullsp, 2); 8833 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp; 8834 PetscFunctionReturn(PETSC_SUCCESS); 8835 } 8836 8837 /*@ 8838 MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix 8839 8840 Logically Collective 8841 8842 Input Parameters: 8843 + mat - the matrix 8844 - nullsp - the null space object 8845 8846 Level: advanced 8847 8848 Notes: 8849 This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning. 8850 8851 See `MatSetNullSpace()` 8852 8853 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()` 8854 @*/ 8855 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp) 8856 { 8857 PetscFunctionBegin; 8858 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8859 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8860 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8861 PetscCall(MatNullSpaceDestroy(&mat->transnullsp)); 8862 mat->transnullsp = nullsp; 8863 PetscFunctionReturn(PETSC_SUCCESS); 8864 } 8865 8866 /*@ 8867 MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions 8868 This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix. 8869 8870 Logically Collective 8871 8872 Input Parameters: 8873 + mat - the matrix 8874 - nullsp - the null space object 8875 8876 Level: advanced 8877 8878 Notes: 8879 Overwrites any previous near null space that may have been attached 8880 8881 You can remove the null space by calling this routine with an nullsp of `NULL` 8882 8883 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()` 8884 @*/ 8885 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp) 8886 { 8887 PetscFunctionBegin; 8888 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8889 PetscValidType(mat, 1); 8890 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8891 MatCheckPreallocated(mat, 1); 8892 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8893 PetscCall(MatNullSpaceDestroy(&mat->nearnullsp)); 8894 mat->nearnullsp = nullsp; 8895 PetscFunctionReturn(PETSC_SUCCESS); 8896 } 8897 8898 /*@ 8899 MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()` 8900 8901 Not Collective 8902 8903 Input Parameter: 8904 . mat - the matrix 8905 8906 Output Parameter: 8907 . nullsp - the null space object, `NULL` if not set 8908 8909 Level: advanced 8910 8911 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()` 8912 @*/ 8913 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp) 8914 { 8915 PetscFunctionBegin; 8916 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8917 PetscValidType(mat, 1); 8918 PetscValidPointer(nullsp, 2); 8919 MatCheckPreallocated(mat, 1); 8920 *nullsp = mat->nearnullsp; 8921 PetscFunctionReturn(PETSC_SUCCESS); 8922 } 8923 8924 /*@C 8925 MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix. 8926 8927 Collective 8928 8929 Input Parameters: 8930 + mat - the matrix 8931 . row - row/column permutation 8932 - info - information on desired factorization process 8933 8934 Level: developer 8935 8936 Notes: 8937 Probably really in-place only when level of fill is zero, otherwise allocates 8938 new space to store factored matrix and deletes previous memory. 8939 8940 Most users should employ the `KSP` interface for linear solvers 8941 instead of working directly with matrix algebra routines such as this. 8942 See, e.g., `KSPCreate()`. 8943 8944 Developer Note: 8945 The Fortran interface is not autogenerated as the 8946 interface definition cannot be generated correctly [due to `MatFactorInfo`] 8947 8948 .seealso: [](chapter_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 8949 @*/ 8950 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info) 8951 { 8952 PetscFunctionBegin; 8953 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8954 PetscValidType(mat, 1); 8955 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 8956 PetscValidPointer(info, 3); 8957 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 8958 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 8959 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8960 MatCheckPreallocated(mat, 1); 8961 PetscUseTypeMethod(mat, iccfactor, row, info); 8962 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 8963 PetscFunctionReturn(PETSC_SUCCESS); 8964 } 8965 8966 /*@ 8967 MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the 8968 ghosted ones. 8969 8970 Not Collective 8971 8972 Input Parameters: 8973 + mat - the matrix 8974 - diag - the diagonal values, including ghost ones 8975 8976 Level: developer 8977 8978 Notes: 8979 Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices 8980 8981 This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()` 8982 8983 .seealso: [](chapter_matrices), `Mat`, `MatDiagonalScale()` 8984 @*/ 8985 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag) 8986 { 8987 PetscMPIInt size; 8988 8989 PetscFunctionBegin; 8990 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8991 PetscValidHeaderSpecific(diag, VEC_CLASSID, 2); 8992 PetscValidType(mat, 1); 8993 8994 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled"); 8995 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 8996 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8997 if (size == 1) { 8998 PetscInt n, m; 8999 PetscCall(VecGetSize(diag, &n)); 9000 PetscCall(MatGetSize(mat, NULL, &m)); 9001 PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions"); 9002 PetscCall(MatDiagonalScale(mat, NULL, diag)); 9003 } else { 9004 PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag)); 9005 } 9006 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 9007 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9008 PetscFunctionReturn(PETSC_SUCCESS); 9009 } 9010 9011 /*@ 9012 MatGetInertia - Gets the inertia from a factored matrix 9013 9014 Collective 9015 9016 Input Parameter: 9017 . mat - the matrix 9018 9019 Output Parameters: 9020 + nneg - number of negative eigenvalues 9021 . nzero - number of zero eigenvalues 9022 - npos - number of positive eigenvalues 9023 9024 Level: advanced 9025 9026 Note: 9027 Matrix must have been factored by `MatCholeskyFactor()` 9028 9029 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()` 9030 @*/ 9031 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos) 9032 { 9033 PetscFunctionBegin; 9034 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9035 PetscValidType(mat, 1); 9036 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9037 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled"); 9038 PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos); 9039 PetscFunctionReturn(PETSC_SUCCESS); 9040 } 9041 9042 /*@C 9043 MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors 9044 9045 Neighbor-wise Collective 9046 9047 Input Parameters: 9048 + mat - the factored matrix obtained with `MatGetFactor()` 9049 - b - the right-hand-side vectors 9050 9051 Output Parameter: 9052 . x - the result vectors 9053 9054 Level: developer 9055 9056 Note: 9057 The vectors `b` and `x` cannot be the same. I.e., one cannot 9058 call `MatSolves`(A,x,x). 9059 9060 .seealso: [](chapter_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()` 9061 @*/ 9062 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x) 9063 { 9064 PetscFunctionBegin; 9065 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9066 PetscValidType(mat, 1); 9067 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 9068 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9069 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 9070 9071 MatCheckPreallocated(mat, 1); 9072 PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0)); 9073 PetscUseTypeMethod(mat, solves, b, x); 9074 PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0)); 9075 PetscFunctionReturn(PETSC_SUCCESS); 9076 } 9077 9078 /*@ 9079 MatIsSymmetric - Test whether a matrix is symmetric 9080 9081 Collective 9082 9083 Input Parameters: 9084 + A - the matrix to test 9085 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose) 9086 9087 Output Parameter: 9088 . flg - the result 9089 9090 Level: intermediate 9091 9092 Notes: 9093 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9094 9095 If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()` 9096 9097 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9098 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9099 9100 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`, 9101 `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()` 9102 @*/ 9103 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg) 9104 { 9105 PetscFunctionBegin; 9106 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9107 PetscValidBoolPointer(flg, 3); 9108 9109 if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE; 9110 else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE; 9111 else { 9112 PetscUseTypeMethod(A, issymmetric, tol, flg); 9113 if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg)); 9114 } 9115 PetscFunctionReturn(PETSC_SUCCESS); 9116 } 9117 9118 /*@ 9119 MatIsHermitian - Test whether a matrix is Hermitian 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 Hermitian) 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 Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()` 9136 9137 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9138 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`) 9139 9140 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, 9141 `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()` 9142 @*/ 9143 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg) 9144 { 9145 PetscFunctionBegin; 9146 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9147 PetscValidBoolPointer(flg, 3); 9148 9149 if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE; 9150 else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE; 9151 else { 9152 PetscUseTypeMethod(A, ishermitian, tol, flg); 9153 if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg)); 9154 } 9155 PetscFunctionReturn(PETSC_SUCCESS); 9156 } 9157 9158 /*@ 9159 MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state 9160 9161 Not Collective 9162 9163 Input Parameter: 9164 . A - the matrix to check 9165 9166 Output Parameters: 9167 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid) 9168 - flg - the result (only valid if set is `PETSC_TRUE`) 9169 9170 Level: advanced 9171 9172 Notes: 9173 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()` 9174 if you want it explicitly checked 9175 9176 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9177 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9178 9179 .seealso: [](chapter_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9180 @*/ 9181 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9182 { 9183 PetscFunctionBegin; 9184 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9185 PetscValidBoolPointer(set, 2); 9186 PetscValidBoolPointer(flg, 3); 9187 if (A->symmetric != PETSC_BOOL3_UNKNOWN) { 9188 *set = PETSC_TRUE; 9189 *flg = PetscBool3ToBool(A->symmetric); 9190 } else { 9191 *set = PETSC_FALSE; 9192 } 9193 PetscFunctionReturn(PETSC_SUCCESS); 9194 } 9195 9196 /*@ 9197 MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state 9198 9199 Not Collective 9200 9201 Input Parameter: 9202 . A - the matrix to check 9203 9204 Output Parameters: 9205 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid) 9206 - flg - the result (only valid if set is `PETSC_TRUE`) 9207 9208 Level: advanced 9209 9210 Notes: 9211 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). 9212 9213 One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD 9214 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`) 9215 9216 .seealso: [](chapter_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9217 @*/ 9218 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg) 9219 { 9220 PetscFunctionBegin; 9221 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9222 PetscValidBoolPointer(set, 2); 9223 PetscValidBoolPointer(flg, 3); 9224 if (A->spd != PETSC_BOOL3_UNKNOWN) { 9225 *set = PETSC_TRUE; 9226 *flg = PetscBool3ToBool(A->spd); 9227 } else { 9228 *set = PETSC_FALSE; 9229 } 9230 PetscFunctionReturn(PETSC_SUCCESS); 9231 } 9232 9233 /*@ 9234 MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state 9235 9236 Not Collective 9237 9238 Input Parameter: 9239 . A - the matrix to check 9240 9241 Output Parameters: 9242 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid) 9243 - flg - the result (only valid if set is `PETSC_TRUE`) 9244 9245 Level: advanced 9246 9247 Notes: 9248 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()` 9249 if you want it explicitly checked 9250 9251 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9252 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9253 9254 .seealso: [](chapter_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()` 9255 @*/ 9256 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg) 9257 { 9258 PetscFunctionBegin; 9259 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9260 PetscValidBoolPointer(set, 2); 9261 PetscValidBoolPointer(flg, 3); 9262 if (A->hermitian != PETSC_BOOL3_UNKNOWN) { 9263 *set = PETSC_TRUE; 9264 *flg = PetscBool3ToBool(A->hermitian); 9265 } else { 9266 *set = PETSC_FALSE; 9267 } 9268 PetscFunctionReturn(PETSC_SUCCESS); 9269 } 9270 9271 /*@ 9272 MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric 9273 9274 Collective 9275 9276 Input Parameter: 9277 . A - the matrix to test 9278 9279 Output Parameter: 9280 . flg - the result 9281 9282 Level: intermediate 9283 9284 Notes: 9285 If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()` 9286 9287 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 9288 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9289 9290 .seealso: [](chapter_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()` 9291 @*/ 9292 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg) 9293 { 9294 PetscFunctionBegin; 9295 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9296 PetscValidBoolPointer(flg, 2); 9297 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9298 *flg = PetscBool3ToBool(A->structurally_symmetric); 9299 } else { 9300 PetscUseTypeMethod(A, isstructurallysymmetric, flg); 9301 PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg)); 9302 } 9303 PetscFunctionReturn(PETSC_SUCCESS); 9304 } 9305 9306 /*@ 9307 MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state 9308 9309 Not Collective 9310 9311 Input Parameter: 9312 . A - the matrix to check 9313 9314 Output Parameters: 9315 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid) 9316 - flg - the result (only valid if set is PETSC_TRUE) 9317 9318 Level: advanced 9319 9320 Notes: 9321 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 9322 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9323 9324 Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation) 9325 9326 .seealso: [](chapter_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9327 @*/ 9328 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9329 { 9330 PetscFunctionBegin; 9331 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9332 PetscValidBoolPointer(set, 2); 9333 PetscValidBoolPointer(flg, 3); 9334 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9335 *set = PETSC_TRUE; 9336 *flg = PetscBool3ToBool(A->structurally_symmetric); 9337 } else { 9338 *set = PETSC_FALSE; 9339 } 9340 PetscFunctionReturn(PETSC_SUCCESS); 9341 } 9342 9343 /*@ 9344 MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need 9345 to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process 9346 9347 Not Collective 9348 9349 Input Parameter: 9350 . mat - the matrix 9351 9352 Output Parameters: 9353 + nstash - the size of the stash 9354 . reallocs - the number of additional mallocs incurred. 9355 . bnstash - the size of the block stash 9356 - breallocs - the number of additional mallocs incurred.in the block stash 9357 9358 Level: advanced 9359 9360 .seealso: [](chapter_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()` 9361 @*/ 9362 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs) 9363 { 9364 PetscFunctionBegin; 9365 PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs)); 9366 PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs)); 9367 PetscFunctionReturn(PETSC_SUCCESS); 9368 } 9369 9370 /*@C 9371 MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same 9372 parallel layout, `PetscLayout` for rows and columns 9373 9374 Collective 9375 9376 Input Parameter: 9377 . mat - the matrix 9378 9379 Output Parameters: 9380 + right - (optional) vector that the matrix can be multiplied against 9381 - left - (optional) vector that the matrix vector product can be stored in 9382 9383 Level: advanced 9384 9385 Notes: 9386 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()`. 9387 9388 These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed 9389 9390 .seealso: [](chapter_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()` 9391 @*/ 9392 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left) 9393 { 9394 PetscFunctionBegin; 9395 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9396 PetscValidType(mat, 1); 9397 if (mat->ops->getvecs) { 9398 PetscUseTypeMethod(mat, getvecs, right, left); 9399 } else { 9400 PetscInt rbs, cbs; 9401 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 9402 if (right) { 9403 PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup"); 9404 PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), right)); 9405 PetscCall(VecSetSizes(*right, mat->cmap->n, PETSC_DETERMINE)); 9406 PetscCall(VecSetBlockSize(*right, cbs)); 9407 PetscCall(VecSetType(*right, mat->defaultvectype)); 9408 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9409 if (mat->boundtocpu && mat->bindingpropagates) { 9410 PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE)); 9411 PetscCall(VecBindToCPU(*right, PETSC_TRUE)); 9412 } 9413 #endif 9414 PetscCall(PetscLayoutReference(mat->cmap, &(*right)->map)); 9415 } 9416 if (left) { 9417 PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup"); 9418 PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), left)); 9419 PetscCall(VecSetSizes(*left, mat->rmap->n, PETSC_DETERMINE)); 9420 PetscCall(VecSetBlockSize(*left, rbs)); 9421 PetscCall(VecSetType(*left, mat->defaultvectype)); 9422 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9423 if (mat->boundtocpu && mat->bindingpropagates) { 9424 PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE)); 9425 PetscCall(VecBindToCPU(*left, PETSC_TRUE)); 9426 } 9427 #endif 9428 PetscCall(PetscLayoutReference(mat->rmap, &(*left)->map)); 9429 } 9430 } 9431 PetscFunctionReturn(PETSC_SUCCESS); 9432 } 9433 9434 /*@C 9435 MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure 9436 with default values. 9437 9438 Not Collective 9439 9440 Input Parameter: 9441 . info - the `MatFactorInfo` data structure 9442 9443 Level: developer 9444 9445 Notes: 9446 The solvers are generally used through the `KSP` and `PC` objects, for example 9447 `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC` 9448 9449 Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed 9450 9451 Developer Note: 9452 The Fortran interface is not autogenerated as the 9453 interface definition cannot be generated correctly [due to `MatFactorInfo`] 9454 9455 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo` 9456 @*/ 9457 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info) 9458 { 9459 PetscFunctionBegin; 9460 PetscCall(PetscMemzero(info, sizeof(MatFactorInfo))); 9461 PetscFunctionReturn(PETSC_SUCCESS); 9462 } 9463 9464 /*@ 9465 MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed 9466 9467 Collective 9468 9469 Input Parameters: 9470 + mat - the factored matrix 9471 - is - the index set defining the Schur indices (0-based) 9472 9473 Level: advanced 9474 9475 Notes: 9476 Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system. 9477 9478 You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call. 9479 9480 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9481 9482 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`, 9483 `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9484 @*/ 9485 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is) 9486 { 9487 PetscErrorCode (*f)(Mat, IS); 9488 9489 PetscFunctionBegin; 9490 PetscValidType(mat, 1); 9491 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9492 PetscValidType(is, 2); 9493 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 9494 PetscCheckSameComm(mat, 1, is, 2); 9495 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 9496 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f)); 9497 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO"); 9498 PetscCall(MatDestroy(&mat->schur)); 9499 PetscCall((*f)(mat, is)); 9500 PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created"); 9501 PetscFunctionReturn(PETSC_SUCCESS); 9502 } 9503 9504 /*@ 9505 MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step 9506 9507 Logically Collective 9508 9509 Input Parameters: 9510 + F - the factored matrix obtained by calling `MatGetFactor()` 9511 . S - location where to return the Schur complement, can be `NULL` 9512 - status - the status of the Schur complement matrix, can be `NULL` 9513 9514 Level: advanced 9515 9516 Notes: 9517 You must call `MatFactorSetSchurIS()` before calling this routine. 9518 9519 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9520 9521 The routine provides a copy of the Schur matrix stored within the solver data structures. 9522 The caller must destroy the object when it is no longer needed. 9523 If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse. 9524 9525 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) 9526 9527 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9528 9529 Developer Note: 9530 The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc 9531 matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix. 9532 9533 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9534 @*/ 9535 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9536 { 9537 PetscFunctionBegin; 9538 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9539 if (S) PetscValidPointer(S, 2); 9540 if (status) PetscValidPointer(status, 3); 9541 if (S) { 9542 PetscErrorCode (*f)(Mat, Mat *); 9543 9544 PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f)); 9545 if (f) { 9546 PetscCall((*f)(F, S)); 9547 } else { 9548 PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S)); 9549 } 9550 } 9551 if (status) *status = F->schur_status; 9552 PetscFunctionReturn(PETSC_SUCCESS); 9553 } 9554 9555 /*@ 9556 MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix 9557 9558 Logically Collective 9559 9560 Input Parameters: 9561 + F - the factored matrix obtained by calling `MatGetFactor()` 9562 . *S - location where to return the Schur complement, can be `NULL` 9563 - status - the status of the Schur complement matrix, can be `NULL` 9564 9565 Level: advanced 9566 9567 Notes: 9568 You must call `MatFactorSetSchurIS()` before calling this routine. 9569 9570 Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS` 9571 9572 The routine returns a the Schur Complement stored within the data structures of the solver. 9573 9574 If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement. 9575 9576 The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed. 9577 9578 Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix 9579 9580 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9581 9582 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9583 @*/ 9584 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9585 { 9586 PetscFunctionBegin; 9587 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9588 if (S) PetscValidPointer(S, 2); 9589 if (status) PetscValidPointer(status, 3); 9590 if (S) *S = F->schur; 9591 if (status) *status = F->schur_status; 9592 PetscFunctionReturn(PETSC_SUCCESS); 9593 } 9594 9595 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F) 9596 { 9597 Mat S = F->schur; 9598 9599 PetscFunctionBegin; 9600 switch (F->schur_status) { 9601 case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through 9602 case MAT_FACTOR_SCHUR_INVERTED: 9603 if (S) { 9604 S->ops->solve = NULL; 9605 S->ops->matsolve = NULL; 9606 S->ops->solvetranspose = NULL; 9607 S->ops->matsolvetranspose = NULL; 9608 S->ops->solveadd = NULL; 9609 S->ops->solvetransposeadd = NULL; 9610 S->factortype = MAT_FACTOR_NONE; 9611 PetscCall(PetscFree(S->solvertype)); 9612 } 9613 case MAT_FACTOR_SCHUR_FACTORED: // fall-through 9614 break; 9615 default: 9616 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9617 } 9618 PetscFunctionReturn(PETSC_SUCCESS); 9619 } 9620 9621 /*@ 9622 MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()` 9623 9624 Logically Collective 9625 9626 Input Parameters: 9627 + F - the factored matrix obtained by calling `MatGetFactor()` 9628 . *S - location where the Schur complement is stored 9629 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`) 9630 9631 Level: advanced 9632 9633 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9634 @*/ 9635 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status) 9636 { 9637 PetscFunctionBegin; 9638 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9639 if (S) { 9640 PetscValidHeaderSpecific(*S, MAT_CLASSID, 2); 9641 *S = NULL; 9642 } 9643 F->schur_status = status; 9644 PetscCall(MatFactorUpdateSchurStatus_Private(F)); 9645 PetscFunctionReturn(PETSC_SUCCESS); 9646 } 9647 9648 /*@ 9649 MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step 9650 9651 Logically Collective 9652 9653 Input Parameters: 9654 + F - the factored matrix obtained by calling `MatGetFactor()` 9655 . rhs - location where the right hand side of the Schur complement system is stored 9656 - sol - location where the solution of the Schur complement system has to be returned 9657 9658 Level: advanced 9659 9660 Notes: 9661 The sizes of the vectors should match the size of the Schur complement 9662 9663 Must be called after `MatFactorSetSchurIS()` 9664 9665 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()` 9666 @*/ 9667 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol) 9668 { 9669 PetscFunctionBegin; 9670 PetscValidType(F, 1); 9671 PetscValidType(rhs, 2); 9672 PetscValidType(sol, 3); 9673 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9674 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9675 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9676 PetscCheckSameComm(F, 1, rhs, 2); 9677 PetscCheckSameComm(F, 1, sol, 3); 9678 PetscCall(MatFactorFactorizeSchurComplement(F)); 9679 switch (F->schur_status) { 9680 case MAT_FACTOR_SCHUR_FACTORED: 9681 PetscCall(MatSolveTranspose(F->schur, rhs, sol)); 9682 break; 9683 case MAT_FACTOR_SCHUR_INVERTED: 9684 PetscCall(MatMultTranspose(F->schur, rhs, sol)); 9685 break; 9686 default: 9687 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9688 } 9689 PetscFunctionReturn(PETSC_SUCCESS); 9690 } 9691 9692 /*@ 9693 MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step 9694 9695 Logically Collective 9696 9697 Input Parameters: 9698 + F - the factored matrix obtained by calling `MatGetFactor()` 9699 . rhs - location where the right hand side of the Schur complement system is stored 9700 - sol - location where the solution of the Schur complement system has to be returned 9701 9702 Level: advanced 9703 9704 Notes: 9705 The sizes of the vectors should match the size of the Schur complement 9706 9707 Must be called after `MatFactorSetSchurIS()` 9708 9709 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()` 9710 @*/ 9711 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol) 9712 { 9713 PetscFunctionBegin; 9714 PetscValidType(F, 1); 9715 PetscValidType(rhs, 2); 9716 PetscValidType(sol, 3); 9717 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9718 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9719 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9720 PetscCheckSameComm(F, 1, rhs, 2); 9721 PetscCheckSameComm(F, 1, sol, 3); 9722 PetscCall(MatFactorFactorizeSchurComplement(F)); 9723 switch (F->schur_status) { 9724 case MAT_FACTOR_SCHUR_FACTORED: 9725 PetscCall(MatSolve(F->schur, rhs, sol)); 9726 break; 9727 case MAT_FACTOR_SCHUR_INVERTED: 9728 PetscCall(MatMult(F->schur, rhs, sol)); 9729 break; 9730 default: 9731 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9732 } 9733 PetscFunctionReturn(PETSC_SUCCESS); 9734 } 9735 9736 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat); 9737 #if PetscDefined(HAVE_CUDA) 9738 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat); 9739 #endif 9740 9741 /* Schur status updated in the interface */ 9742 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F) 9743 { 9744 Mat S = F->schur; 9745 9746 PetscFunctionBegin; 9747 if (S) { 9748 PetscMPIInt size; 9749 PetscBool isdense, isdensecuda; 9750 9751 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size)); 9752 PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented"); 9753 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense)); 9754 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda)); 9755 PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name); 9756 PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0)); 9757 if (isdense) { 9758 PetscCall(MatSeqDenseInvertFactors_Private(S)); 9759 } else if (isdensecuda) { 9760 #if defined(PETSC_HAVE_CUDA) 9761 PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S)); 9762 #endif 9763 } 9764 // HIP?????????????? 9765 PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0)); 9766 } 9767 PetscFunctionReturn(PETSC_SUCCESS); 9768 } 9769 9770 /*@ 9771 MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step 9772 9773 Logically Collective 9774 9775 Input Parameter: 9776 . F - the factored matrix obtained by calling `MatGetFactor()` 9777 9778 Level: advanced 9779 9780 Notes: 9781 Must be called after `MatFactorSetSchurIS()`. 9782 9783 Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it. 9784 9785 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()` 9786 @*/ 9787 PetscErrorCode MatFactorInvertSchurComplement(Mat F) 9788 { 9789 PetscFunctionBegin; 9790 PetscValidType(F, 1); 9791 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9792 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS); 9793 PetscCall(MatFactorFactorizeSchurComplement(F)); 9794 PetscCall(MatFactorInvertSchurComplement_Private(F)); 9795 F->schur_status = MAT_FACTOR_SCHUR_INVERTED; 9796 PetscFunctionReturn(PETSC_SUCCESS); 9797 } 9798 9799 /*@ 9800 MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step 9801 9802 Logically Collective 9803 9804 Input Parameter: 9805 . F - the factored matrix obtained by calling `MatGetFactor()` 9806 9807 Level: advanced 9808 9809 Note: 9810 Must be called after `MatFactorSetSchurIS()` 9811 9812 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()` 9813 @*/ 9814 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F) 9815 { 9816 MatFactorInfo info; 9817 9818 PetscFunctionBegin; 9819 PetscValidType(F, 1); 9820 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9821 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS); 9822 PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0)); 9823 PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo))); 9824 if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */ 9825 PetscCall(MatCholeskyFactor(F->schur, NULL, &info)); 9826 } else { 9827 PetscCall(MatLUFactor(F->schur, NULL, NULL, &info)); 9828 } 9829 PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0)); 9830 F->schur_status = MAT_FACTOR_SCHUR_FACTORED; 9831 PetscFunctionReturn(PETSC_SUCCESS); 9832 } 9833 9834 /*@ 9835 MatPtAP - Creates the matrix product C = P^T * A * P 9836 9837 Neighbor-wise Collective 9838 9839 Input Parameters: 9840 + A - the matrix 9841 . P - the projection matrix 9842 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9843 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate 9844 if the result is a dense matrix this is irrelevant 9845 9846 Output Parameter: 9847 . C - the product matrix 9848 9849 Level: intermediate 9850 9851 Notes: 9852 C will be created and must be destroyed by the user with `MatDestroy()`. 9853 9854 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9855 9856 Developer Note: 9857 For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`. 9858 9859 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()` 9860 @*/ 9861 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C) 9862 { 9863 PetscFunctionBegin; 9864 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 9865 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9866 9867 if (scall == MAT_INITIAL_MATRIX) { 9868 PetscCall(MatProductCreate(A, P, NULL, C)); 9869 PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP)); 9870 PetscCall(MatProductSetAlgorithm(*C, "default")); 9871 PetscCall(MatProductSetFill(*C, fill)); 9872 9873 (*C)->product->api_user = PETSC_TRUE; 9874 PetscCall(MatProductSetFromOptions(*C)); 9875 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); 9876 PetscCall(MatProductSymbolic(*C)); 9877 } else { /* scall == MAT_REUSE_MATRIX */ 9878 PetscCall(MatProductReplaceMats(A, P, NULL, *C)); 9879 } 9880 9881 PetscCall(MatProductNumeric(*C)); 9882 (*C)->symmetric = A->symmetric; 9883 (*C)->spd = A->spd; 9884 PetscFunctionReturn(PETSC_SUCCESS); 9885 } 9886 9887 /*@ 9888 MatRARt - Creates the matrix product C = R * A * R^T 9889 9890 Neighbor-wise Collective 9891 9892 Input Parameters: 9893 + A - the matrix 9894 . R - the projection matrix 9895 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9896 - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate 9897 if the result is a dense matrix this is irrelevant 9898 9899 Output Parameter: 9900 . C - the product matrix 9901 9902 Level: intermediate 9903 9904 Notes: 9905 C will be created and must be destroyed by the user with `MatDestroy()`. 9906 9907 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9908 9909 This routine is currently only implemented for pairs of `MATAIJ` matrices and classes 9910 which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes, 9911 parallel MatRARt is implemented via explicit transpose of R, which could be very expensive. 9912 We recommend using MatPtAP(). 9913 9914 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()` 9915 @*/ 9916 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C) 9917 { 9918 PetscFunctionBegin; 9919 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 9920 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9921 9922 if (scall == MAT_INITIAL_MATRIX) { 9923 PetscCall(MatProductCreate(A, R, NULL, C)); 9924 PetscCall(MatProductSetType(*C, MATPRODUCT_RARt)); 9925 PetscCall(MatProductSetAlgorithm(*C, "default")); 9926 PetscCall(MatProductSetFill(*C, fill)); 9927 9928 (*C)->product->api_user = PETSC_TRUE; 9929 PetscCall(MatProductSetFromOptions(*C)); 9930 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); 9931 PetscCall(MatProductSymbolic(*C)); 9932 } else { /* scall == MAT_REUSE_MATRIX */ 9933 PetscCall(MatProductReplaceMats(A, R, NULL, *C)); 9934 } 9935 9936 PetscCall(MatProductNumeric(*C)); 9937 if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 9938 PetscFunctionReturn(PETSC_SUCCESS); 9939 } 9940 9941 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C) 9942 { 9943 PetscFunctionBegin; 9944 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9945 9946 if (scall == MAT_INITIAL_MATRIX) { 9947 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype])); 9948 PetscCall(MatProductCreate(A, B, NULL, C)); 9949 PetscCall(MatProductSetType(*C, ptype)); 9950 PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT)); 9951 PetscCall(MatProductSetFill(*C, fill)); 9952 9953 (*C)->product->api_user = PETSC_TRUE; 9954 PetscCall(MatProductSetFromOptions(*C)); 9955 PetscCall(MatProductSymbolic(*C)); 9956 } else { /* scall == MAT_REUSE_MATRIX */ 9957 Mat_Product *product = (*C)->product; 9958 PetscBool isdense; 9959 9960 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, "")); 9961 if (isdense && product && product->type != ptype) { 9962 PetscCall(MatProductClear(*C)); 9963 product = NULL; 9964 } 9965 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype])); 9966 if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */ 9967 PetscCheck(isdense, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first"); 9968 PetscCall(MatProductCreate_Private(A, B, NULL, *C)); 9969 product = (*C)->product; 9970 product->fill = fill; 9971 product->api_user = PETSC_TRUE; 9972 product->clear = PETSC_TRUE; 9973 9974 PetscCall(MatProductSetType(*C, ptype)); 9975 PetscCall(MatProductSetFromOptions(*C)); 9976 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); 9977 PetscCall(MatProductSymbolic(*C)); 9978 } else { /* user may change input matrices A or B when REUSE */ 9979 PetscCall(MatProductReplaceMats(A, B, NULL, *C)); 9980 } 9981 } 9982 PetscCall(MatProductNumeric(*C)); 9983 PetscFunctionReturn(PETSC_SUCCESS); 9984 } 9985 9986 /*@ 9987 MatMatMult - Performs matrix-matrix multiplication C=A*B. 9988 9989 Neighbor-wise Collective 9990 9991 Input Parameters: 9992 + A - the left matrix 9993 . B - the right matrix 9994 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9995 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate 9996 if the result is a dense matrix this is irrelevant 9997 9998 Output Parameter: 9999 . C - the product matrix 10000 10001 Notes: 10002 Unless scall is `MAT_REUSE_MATRIX` C will be created. 10003 10004 `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 10005 call to this function with `MAT_INITIAL_MATRIX`. 10006 10007 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed. 10008 10009 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`, 10010 rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse. 10011 10012 Example of Usage: 10013 .vb 10014 MatProductCreate(A,B,NULL,&C); 10015 MatProductSetType(C,MATPRODUCT_AB); 10016 MatProductSymbolic(C); 10017 MatProductNumeric(C); // compute C=A * B 10018 MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1 10019 MatProductNumeric(C); 10020 MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1 10021 MatProductNumeric(C); 10022 .ve 10023 10024 Level: intermediate 10025 10026 .seealso: [](chapter_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()` 10027 @*/ 10028 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10029 { 10030 PetscFunctionBegin; 10031 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C)); 10032 PetscFunctionReturn(PETSC_SUCCESS); 10033 } 10034 10035 /*@ 10036 MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T. 10037 10038 Neighbor-wise Collective 10039 10040 Input Parameters: 10041 + A - the left matrix 10042 . B - the right matrix 10043 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10044 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 10045 10046 Output Parameter: 10047 . C - the product matrix 10048 10049 Level: intermediate 10050 10051 Notes: 10052 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10053 10054 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call 10055 10056 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10057 actually needed. 10058 10059 This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class, 10060 and for pairs of `MATMPIDENSE` matrices. 10061 10062 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt` 10063 10064 Options Database Keys: 10065 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the 10066 first redundantly copies the transposed B matrix on each process and requiers O(log P) communication complexity; 10067 the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity. 10068 10069 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductCreate()`, `MatProductAlgorithm`, `MatProductType`, `MATPRODUCT_ABt` 10070 @*/ 10071 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10072 { 10073 PetscFunctionBegin; 10074 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C)); 10075 if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10076 PetscFunctionReturn(PETSC_SUCCESS); 10077 } 10078 10079 /*@ 10080 MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B. 10081 10082 Neighbor-wise Collective 10083 10084 Input Parameters: 10085 + A - the left matrix 10086 . B - the right matrix 10087 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10088 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 10089 10090 Output Parameter: 10091 . C - the product matrix 10092 10093 Level: intermediate 10094 10095 Notes: 10096 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10097 10098 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call. 10099 10100 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB` 10101 10102 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10103 actually needed. 10104 10105 This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes 10106 which inherit from `MATSEQAIJ`. C will be of the same type as the input matrices. 10107 10108 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()` 10109 @*/ 10110 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10111 { 10112 PetscFunctionBegin; 10113 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C)); 10114 PetscFunctionReturn(PETSC_SUCCESS); 10115 } 10116 10117 /*@ 10118 MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C. 10119 10120 Neighbor-wise Collective 10121 10122 Input Parameters: 10123 + A - the left matrix 10124 . B - the middle matrix 10125 . C - the right matrix 10126 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10127 - 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 10128 if the result is a dense matrix this is irrelevant 10129 10130 Output Parameter: 10131 . D - the product matrix 10132 10133 Level: intermediate 10134 10135 Notes: 10136 Unless scall is `MAT_REUSE_MATRIX` D will be created. 10137 10138 `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call 10139 10140 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC` 10141 10142 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10143 actually needed. 10144 10145 If you have many matrices with the same non-zero structure to multiply, you 10146 should use `MAT_REUSE_MATRIX` in all calls but the first 10147 10148 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()` 10149 @*/ 10150 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D) 10151 { 10152 PetscFunctionBegin; 10153 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6); 10154 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10155 10156 if (scall == MAT_INITIAL_MATRIX) { 10157 PetscCall(MatProductCreate(A, B, C, D)); 10158 PetscCall(MatProductSetType(*D, MATPRODUCT_ABC)); 10159 PetscCall(MatProductSetAlgorithm(*D, "default")); 10160 PetscCall(MatProductSetFill(*D, fill)); 10161 10162 (*D)->product->api_user = PETSC_TRUE; 10163 PetscCall(MatProductSetFromOptions(*D)); 10164 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, 10165 ((PetscObject)C)->type_name); 10166 PetscCall(MatProductSymbolic(*D)); 10167 } else { /* user may change input matrices when REUSE */ 10168 PetscCall(MatProductReplaceMats(A, B, C, *D)); 10169 } 10170 PetscCall(MatProductNumeric(*D)); 10171 PetscFunctionReturn(PETSC_SUCCESS); 10172 } 10173 10174 /*@ 10175 MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators. 10176 10177 Collective 10178 10179 Input Parameters: 10180 + mat - the matrix 10181 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices) 10182 . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used) 10183 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10184 10185 Output Parameter: 10186 . matredundant - redundant matrix 10187 10188 Level: advanced 10189 10190 Notes: 10191 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 10192 original matrix has not changed from that last call to MatCreateRedundantMatrix(). 10193 10194 This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before 10195 calling it. 10196 10197 `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be. 10198 10199 .seealso: [](chapter_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubComm` 10200 @*/ 10201 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant) 10202 { 10203 MPI_Comm comm; 10204 PetscMPIInt size; 10205 PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs; 10206 Mat_Redundant *redund = NULL; 10207 PetscSubcomm psubcomm = NULL; 10208 MPI_Comm subcomm_in = subcomm; 10209 Mat *matseq; 10210 IS isrow, iscol; 10211 PetscBool newsubcomm = PETSC_FALSE; 10212 10213 PetscFunctionBegin; 10214 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10215 if (nsubcomm && reuse == MAT_REUSE_MATRIX) { 10216 PetscValidPointer(*matredundant, 5); 10217 PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5); 10218 } 10219 10220 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10221 if (size == 1 || nsubcomm == 1) { 10222 if (reuse == MAT_INITIAL_MATRIX) { 10223 PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant)); 10224 } else { 10225 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"); 10226 PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN)); 10227 } 10228 PetscFunctionReturn(PETSC_SUCCESS); 10229 } 10230 10231 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10232 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10233 MatCheckPreallocated(mat, 1); 10234 10235 PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0)); 10236 if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */ 10237 /* create psubcomm, then get subcomm */ 10238 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10239 PetscCallMPI(MPI_Comm_size(comm, &size)); 10240 PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size); 10241 10242 PetscCall(PetscSubcommCreate(comm, &psubcomm)); 10243 PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm)); 10244 PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS)); 10245 PetscCall(PetscSubcommSetFromOptions(psubcomm)); 10246 PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL)); 10247 newsubcomm = PETSC_TRUE; 10248 PetscCall(PetscSubcommDestroy(&psubcomm)); 10249 } 10250 10251 /* get isrow, iscol and a local sequential matrix matseq[0] */ 10252 if (reuse == MAT_INITIAL_MATRIX) { 10253 mloc_sub = PETSC_DECIDE; 10254 nloc_sub = PETSC_DECIDE; 10255 if (bs < 1) { 10256 PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M)); 10257 PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N)); 10258 } else { 10259 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M)); 10260 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N)); 10261 } 10262 PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm)); 10263 rstart = rend - mloc_sub; 10264 PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow)); 10265 PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol)); 10266 } else { /* reuse == MAT_REUSE_MATRIX */ 10267 PetscCheck(*matredundant != mat, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "MAT_REUSE_MATRIX means reuse the matrix passed in as the final argument, not the original matrix"); 10268 /* retrieve subcomm */ 10269 PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm)); 10270 redund = (*matredundant)->redundant; 10271 isrow = redund->isrow; 10272 iscol = redund->iscol; 10273 matseq = redund->matseq; 10274 } 10275 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq)); 10276 10277 /* get matredundant over subcomm */ 10278 if (reuse == MAT_INITIAL_MATRIX) { 10279 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant)); 10280 10281 /* create a supporting struct and attach it to C for reuse */ 10282 PetscCall(PetscNew(&redund)); 10283 (*matredundant)->redundant = redund; 10284 redund->isrow = isrow; 10285 redund->iscol = iscol; 10286 redund->matseq = matseq; 10287 if (newsubcomm) { 10288 redund->subcomm = subcomm; 10289 } else { 10290 redund->subcomm = MPI_COMM_NULL; 10291 } 10292 } else { 10293 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant)); 10294 } 10295 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 10296 if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) { 10297 PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE)); 10298 PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE)); 10299 } 10300 #endif 10301 PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0)); 10302 PetscFunctionReturn(PETSC_SUCCESS); 10303 } 10304 10305 /*@C 10306 MatGetMultiProcBlock - Create multiple 'parallel submatrices' from 10307 a given `Mat`. Each submatrix can span multiple procs. 10308 10309 Collective 10310 10311 Input Parameters: 10312 + mat - the matrix 10313 . subcomm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))` 10314 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10315 10316 Output Parameter: 10317 . subMat - parallel sub-matrices each spanning a given `subcomm` 10318 10319 Level: advanced 10320 10321 Notes: 10322 The submatrix partition across processors is dictated by `subComm` a 10323 communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm` 10324 is not restricted to be grouped with consecutive original ranks. 10325 10326 Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices 10327 map directly to the layout of the original matrix [wrt the local 10328 row,col partitioning]. So the original 'DiagonalMat' naturally maps 10329 into the 'DiagonalMat' of the `subMat`, hence it is used directly from 10330 the `subMat`. However the offDiagMat looses some columns - and this is 10331 reconstructed with `MatSetValues()` 10332 10333 This is used by `PCBJACOBI` when a single block spans multiple MPI ranks 10334 10335 .seealso: [](chapter_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI` 10336 @*/ 10337 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) 10338 { 10339 PetscMPIInt commsize, subCommSize; 10340 10341 PetscFunctionBegin; 10342 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize)); 10343 PetscCallMPI(MPI_Comm_size(subComm, &subCommSize)); 10344 PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize); 10345 10346 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"); 10347 PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10348 PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat); 10349 PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10350 PetscFunctionReturn(PETSC_SUCCESS); 10351 } 10352 10353 /*@ 10354 MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering 10355 10356 Not Collective 10357 10358 Input Parameters: 10359 + mat - matrix to extract local submatrix from 10360 . isrow - local row indices for submatrix 10361 - iscol - local column indices for submatrix 10362 10363 Output Parameter: 10364 . submat - the submatrix 10365 10366 Level: intermediate 10367 10368 Notes: 10369 `submat` should be disposed of with `MatRestoreLocalSubMatrix()`. 10370 10371 Depending on the format of `mat`, the returned submat may not implement `MatMult()`. Its communicator may be 10372 the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of `mat`'s. 10373 10374 `submat` always implements `MatSetValuesLocal()`. If `isrow` and `iscol` have the same block size, then 10375 `MatSetValuesBlockedLocal()` will also be implemented. 10376 10377 `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`. 10378 Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided. 10379 10380 .seealso: [](chapter_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()` 10381 @*/ 10382 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10383 { 10384 PetscFunctionBegin; 10385 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10386 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10387 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10388 PetscCheckSameComm(isrow, 2, iscol, 3); 10389 PetscValidPointer(submat, 4); 10390 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call"); 10391 10392 if (mat->ops->getlocalsubmatrix) { 10393 PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat); 10394 } else { 10395 PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat)); 10396 } 10397 PetscFunctionReturn(PETSC_SUCCESS); 10398 } 10399 10400 /*@ 10401 MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()` 10402 10403 Not Collective 10404 10405 Input Parameters: 10406 + mat - matrix to extract local submatrix from 10407 . isrow - local row indices for submatrix 10408 . iscol - local column indices for submatrix 10409 - submat - the submatrix 10410 10411 Level: intermediate 10412 10413 .seealso: [](chapter_matrices), `Mat`, `MatGetLocalSubMatrix()` 10414 @*/ 10415 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10416 { 10417 PetscFunctionBegin; 10418 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10419 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10420 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10421 PetscCheckSameComm(isrow, 2, iscol, 3); 10422 PetscValidPointer(submat, 4); 10423 if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4); 10424 10425 if (mat->ops->restorelocalsubmatrix) { 10426 PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat); 10427 } else { 10428 PetscCall(MatDestroy(submat)); 10429 } 10430 *submat = NULL; 10431 PetscFunctionReturn(PETSC_SUCCESS); 10432 } 10433 10434 /*@ 10435 MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix 10436 10437 Collective 10438 10439 Input Parameter: 10440 . mat - the matrix 10441 10442 Output Parameter: 10443 . is - if any rows have zero diagonals this contains the list of them 10444 10445 Level: developer 10446 10447 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10448 @*/ 10449 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is) 10450 { 10451 PetscFunctionBegin; 10452 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10453 PetscValidType(mat, 1); 10454 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10455 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10456 10457 if (!mat->ops->findzerodiagonals) { 10458 Vec diag; 10459 const PetscScalar *a; 10460 PetscInt *rows; 10461 PetscInt rStart, rEnd, r, nrow = 0; 10462 10463 PetscCall(MatCreateVecs(mat, &diag, NULL)); 10464 PetscCall(MatGetDiagonal(mat, diag)); 10465 PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd)); 10466 PetscCall(VecGetArrayRead(diag, &a)); 10467 for (r = 0; r < rEnd - rStart; ++r) 10468 if (a[r] == 0.0) ++nrow; 10469 PetscCall(PetscMalloc1(nrow, &rows)); 10470 nrow = 0; 10471 for (r = 0; r < rEnd - rStart; ++r) 10472 if (a[r] == 0.0) rows[nrow++] = r + rStart; 10473 PetscCall(VecRestoreArrayRead(diag, &a)); 10474 PetscCall(VecDestroy(&diag)); 10475 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is)); 10476 } else { 10477 PetscUseTypeMethod(mat, findzerodiagonals, is); 10478 } 10479 PetscFunctionReturn(PETSC_SUCCESS); 10480 } 10481 10482 /*@ 10483 MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size) 10484 10485 Collective 10486 10487 Input Parameter: 10488 . mat - the matrix 10489 10490 Output Parameter: 10491 . is - contains the list of rows with off block diagonal entries 10492 10493 Level: developer 10494 10495 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10496 @*/ 10497 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is) 10498 { 10499 PetscFunctionBegin; 10500 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10501 PetscValidType(mat, 1); 10502 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10503 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10504 10505 PetscUseTypeMethod(mat, findoffblockdiagonalentries, is); 10506 PetscFunctionReturn(PETSC_SUCCESS); 10507 } 10508 10509 /*@C 10510 MatInvertBlockDiagonal - Inverts the block diagonal entries. 10511 10512 Collective; No Fortran Support 10513 10514 Input Parameter: 10515 . mat - the matrix 10516 10517 Output Parameter: 10518 . values - the block inverses in column major order (FORTRAN-like) 10519 10520 Level: advanced 10521 10522 Notes: 10523 The size of the blocks is determined by the block size of the matrix. 10524 10525 The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case 10526 10527 The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size 10528 10529 .seealso: [](chapter_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()` 10530 @*/ 10531 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values) 10532 { 10533 PetscFunctionBegin; 10534 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10535 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10536 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10537 PetscUseTypeMethod(mat, invertblockdiagonal, values); 10538 PetscFunctionReturn(PETSC_SUCCESS); 10539 } 10540 10541 /*@C 10542 MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries. 10543 10544 Collective; No Fortran Support 10545 10546 Input Parameters: 10547 + mat - the matrix 10548 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()` 10549 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()` 10550 10551 Output Parameter: 10552 . values - the block inverses in column major order (FORTRAN-like) 10553 10554 Level: advanced 10555 10556 Notes: 10557 Use `MatInvertBlockDiagonal()` if all blocks have the same size 10558 10559 The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case 10560 10561 .seealso: [](chapter_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()` 10562 @*/ 10563 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, 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, invertvariableblockdiagonal, nblocks, bsizes, values); 10570 PetscFunctionReturn(PETSC_SUCCESS); 10571 } 10572 10573 /*@ 10574 MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A 10575 10576 Collective 10577 10578 Input Parameters: 10579 + A - the matrix 10580 - C - matrix with inverted block diagonal of `A`. This matrix should be created and may have its type set. 10581 10582 Level: advanced 10583 10584 Note: 10585 The blocksize of the matrix is used to determine the blocks on the diagonal of `C` 10586 10587 .seealso: [](chapter_matrices), `Mat`, `MatInvertBlockDiagonal()` 10588 @*/ 10589 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C) 10590 { 10591 const PetscScalar *vals; 10592 PetscInt *dnnz; 10593 PetscInt m, rstart, rend, bs, i, j; 10594 10595 PetscFunctionBegin; 10596 PetscCall(MatInvertBlockDiagonal(A, &vals)); 10597 PetscCall(MatGetBlockSize(A, &bs)); 10598 PetscCall(MatGetLocalSize(A, &m, NULL)); 10599 PetscCall(MatSetLayouts(C, A->rmap, A->cmap)); 10600 PetscCall(PetscMalloc1(m / bs, &dnnz)); 10601 for (j = 0; j < m / bs; j++) dnnz[j] = 1; 10602 PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL)); 10603 PetscCall(PetscFree(dnnz)); 10604 PetscCall(MatGetOwnershipRange(C, &rstart, &rend)); 10605 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE)); 10606 for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES)); 10607 PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 10608 PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 10609 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE)); 10610 PetscFunctionReturn(PETSC_SUCCESS); 10611 } 10612 10613 /*@C 10614 MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created 10615 via `MatTransposeColoringCreate()`. 10616 10617 Collective 10618 10619 Input Parameter: 10620 . c - coloring context 10621 10622 Level: intermediate 10623 10624 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringCreate()` 10625 @*/ 10626 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c) 10627 { 10628 MatTransposeColoring matcolor = *c; 10629 10630 PetscFunctionBegin; 10631 if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS); 10632 if (--((PetscObject)matcolor)->refct > 0) { 10633 matcolor = NULL; 10634 PetscFunctionReturn(PETSC_SUCCESS); 10635 } 10636 10637 PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow)); 10638 PetscCall(PetscFree(matcolor->rows)); 10639 PetscCall(PetscFree(matcolor->den2sp)); 10640 PetscCall(PetscFree(matcolor->colorforcol)); 10641 PetscCall(PetscFree(matcolor->columns)); 10642 if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart)); 10643 PetscCall(PetscHeaderDestroy(c)); 10644 PetscFunctionReturn(PETSC_SUCCESS); 10645 } 10646 10647 /*@C 10648 MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which 10649 a `MatTransposeColoring` context has been created, computes a dense B^T by applying 10650 `MatTransposeColoring` to sparse B. 10651 10652 Collective 10653 10654 Input Parameters: 10655 + coloring - coloring context created with `MatTransposeColoringCreate()` 10656 - B - sparse matrix 10657 10658 Output Parameter: 10659 . Btdense - dense matrix B^T 10660 10661 Level: developer 10662 10663 Note: 10664 These are used internally for some implementations of `MatRARt()` 10665 10666 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()` 10667 @*/ 10668 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense) 10669 { 10670 PetscFunctionBegin; 10671 PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10672 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 10673 PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3); 10674 10675 PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense)); 10676 PetscFunctionReturn(PETSC_SUCCESS); 10677 } 10678 10679 /*@C 10680 MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which 10681 a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense 10682 in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix 10683 `Csp` from `Cden`. 10684 10685 Collective 10686 10687 Input Parameters: 10688 + matcoloring - coloring context created with `MatTransposeColoringCreate()` 10689 - Cden - matrix product of a sparse matrix and a dense matrix Btdense 10690 10691 Output Parameter: 10692 . Csp - sparse matrix 10693 10694 Level: developer 10695 10696 Note: 10697 These are used internally for some implementations of `MatRARt()` 10698 10699 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()` 10700 @*/ 10701 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp) 10702 { 10703 PetscFunctionBegin; 10704 PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10705 PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2); 10706 PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3); 10707 10708 PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp)); 10709 PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY)); 10710 PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY)); 10711 PetscFunctionReturn(PETSC_SUCCESS); 10712 } 10713 10714 /*@C 10715 MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T. 10716 10717 Collective 10718 10719 Input Parameters: 10720 + mat - the matrix product C 10721 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()` 10722 10723 Output Parameter: 10724 . color - the new coloring context 10725 10726 Level: intermediate 10727 10728 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`, 10729 `MatTransColoringApplyDenToSp()` 10730 @*/ 10731 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color) 10732 { 10733 MatTransposeColoring c; 10734 MPI_Comm comm; 10735 10736 PetscFunctionBegin; 10737 PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10738 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10739 PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL)); 10740 10741 c->ctype = iscoloring->ctype; 10742 PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c); 10743 10744 *color = c; 10745 PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10746 PetscFunctionReturn(PETSC_SUCCESS); 10747 } 10748 10749 /*@ 10750 MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the 10751 matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the 10752 same, otherwise it will be larger 10753 10754 Not Collective 10755 10756 Input Parameter: 10757 . A - the matrix 10758 10759 Output Parameter: 10760 . state - the current state 10761 10762 Level: intermediate 10763 10764 Notes: 10765 You can only compare states from two different calls to the SAME matrix, you cannot compare calls between 10766 different matrices 10767 10768 Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix 10769 10770 Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers. 10771 10772 .seealso: [](chapter_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()` 10773 @*/ 10774 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state) 10775 { 10776 PetscFunctionBegin; 10777 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10778 *state = mat->nonzerostate; 10779 PetscFunctionReturn(PETSC_SUCCESS); 10780 } 10781 10782 /*@ 10783 MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential 10784 matrices from each processor 10785 10786 Collective 10787 10788 Input Parameters: 10789 + comm - the communicators the parallel matrix will live on 10790 . seqmat - the input sequential matrices 10791 . n - number of local columns (or `PETSC_DECIDE`) 10792 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10793 10794 Output Parameter: 10795 . mpimat - the parallel matrix generated 10796 10797 Level: developer 10798 10799 Note: 10800 The number of columns of the matrix in EACH processor MUST be the same. 10801 10802 .seealso: [](chapter_matrices), `Mat` 10803 @*/ 10804 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat) 10805 { 10806 PetscMPIInt size; 10807 10808 PetscFunctionBegin; 10809 PetscCallMPI(MPI_Comm_size(comm, &size)); 10810 if (size == 1) { 10811 if (reuse == MAT_INITIAL_MATRIX) { 10812 PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat)); 10813 } else { 10814 PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN)); 10815 } 10816 PetscFunctionReturn(PETSC_SUCCESS); 10817 } 10818 10819 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"); 10820 10821 PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0)); 10822 PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat)); 10823 PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0)); 10824 PetscFunctionReturn(PETSC_SUCCESS); 10825 } 10826 10827 /*@ 10828 MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent ranks' ownership ranges. 10829 10830 Collective 10831 10832 Input Parameters: 10833 + A - the matrix to create subdomains from 10834 - N - requested number of subdomains 10835 10836 Output Parameters: 10837 + n - number of subdomains resulting on this rank 10838 - iss - `IS` list with indices of subdomains on this rank 10839 10840 Level: advanced 10841 10842 Note: 10843 The number of subdomains must be smaller than the communicator size 10844 10845 .seealso: [](chapter_matrices), `Mat`, `IS` 10846 @*/ 10847 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[]) 10848 { 10849 MPI_Comm comm, subcomm; 10850 PetscMPIInt size, rank, color; 10851 PetscInt rstart, rend, k; 10852 10853 PetscFunctionBegin; 10854 PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 10855 PetscCallMPI(MPI_Comm_size(comm, &size)); 10856 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 10857 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); 10858 *n = 1; 10859 k = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */ 10860 color = rank / k; 10861 PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm)); 10862 PetscCall(PetscMalloc1(1, iss)); 10863 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 10864 PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0])); 10865 PetscCallMPI(MPI_Comm_free(&subcomm)); 10866 PetscFunctionReturn(PETSC_SUCCESS); 10867 } 10868 10869 /*@ 10870 MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection. 10871 10872 If the interpolation and restriction operators are the same, uses `MatPtAP()`. 10873 If they are not the same, uses `MatMatMatMult()`. 10874 10875 Once the coarse grid problem is constructed, correct for interpolation operators 10876 that are not of full rank, which can legitimately happen in the case of non-nested 10877 geometric multigrid. 10878 10879 Input Parameters: 10880 + restrct - restriction operator 10881 . dA - fine grid matrix 10882 . interpolate - interpolation operator 10883 . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10884 - fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate 10885 10886 Output Parameter: 10887 . A - the Galerkin coarse matrix 10888 10889 Options Database Key: 10890 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used 10891 10892 Level: developer 10893 10894 .seealso: [](chapter_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()` 10895 @*/ 10896 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A) 10897 { 10898 IS zerorows; 10899 Vec diag; 10900 10901 PetscFunctionBegin; 10902 PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10903 /* Construct the coarse grid matrix */ 10904 if (interpolate == restrct) { 10905 PetscCall(MatPtAP(dA, interpolate, reuse, fill, A)); 10906 } else { 10907 PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A)); 10908 } 10909 10910 /* If the interpolation matrix is not of full rank, A will have zero rows. 10911 This can legitimately happen in the case of non-nested geometric multigrid. 10912 In that event, we set the rows of the matrix to the rows of the identity, 10913 ignoring the equations (as the RHS will also be zero). */ 10914 10915 PetscCall(MatFindZeroRows(*A, &zerorows)); 10916 10917 if (zerorows != NULL) { /* if there are any zero rows */ 10918 PetscCall(MatCreateVecs(*A, &diag, NULL)); 10919 PetscCall(MatGetDiagonal(*A, diag)); 10920 PetscCall(VecISSet(diag, zerorows, 1.0)); 10921 PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES)); 10922 PetscCall(VecDestroy(&diag)); 10923 PetscCall(ISDestroy(&zerorows)); 10924 } 10925 PetscFunctionReturn(PETSC_SUCCESS); 10926 } 10927 10928 /*@C 10929 MatSetOperation - Allows user to set a matrix operation for any matrix type 10930 10931 Logically Collective 10932 10933 Input Parameters: 10934 + mat - the matrix 10935 . op - the name of the operation 10936 - f - the function that provides the operation 10937 10938 Level: developer 10939 10940 Usage: 10941 .vb 10942 extern PetscErrorCode usermult(Mat, Vec, Vec); 10943 10944 PetscCall(MatCreateXXX(comm, ..., &A)); 10945 PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFunction)usermult)); 10946 .ve 10947 10948 Notes: 10949 See the file `include/petscmat.h` for a complete list of matrix 10950 operations, which all have the form MATOP_<OPERATION>, where 10951 <OPERATION> is the name (in all capital letters) of the 10952 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 10953 10954 All user-provided functions (except for `MATOP_DESTROY`) should have the same calling 10955 sequence as the usual matrix interface routines, since they 10956 are intended to be accessed via the usual matrix interface 10957 routines, e.g., 10958 .vb 10959 MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec) 10960 .ve 10961 10962 In particular each function MUST return `PETSC_SUCCESS` on success and 10963 nonzero on failure. 10964 10965 This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type. 10966 10967 .seealso: [](chapter_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()` 10968 @*/ 10969 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void)) 10970 { 10971 PetscFunctionBegin; 10972 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10973 if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view; 10974 (((void (**)(void))mat->ops)[op]) = f; 10975 PetscFunctionReturn(PETSC_SUCCESS); 10976 } 10977 10978 /*@C 10979 MatGetOperation - Gets a matrix operation for any matrix type. 10980 10981 Not Collective 10982 10983 Input Parameters: 10984 + mat - the matrix 10985 - op - the name of the operation 10986 10987 Output Parameter: 10988 . f - the function that provides the operation 10989 10990 Level: developer 10991 10992 Usage: 10993 .vb 10994 PetscErrorCode (*usermult)(Mat, Vec, Vec); 10995 MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult); 10996 .ve 10997 10998 Notes: 10999 See the file include/petscmat.h for a complete list of matrix 11000 operations, which all have the form MATOP_<OPERATION>, where 11001 <OPERATION> is the name (in all capital letters) of the 11002 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11003 11004 This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type. 11005 11006 .seealso: [](chapter_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()` 11007 @*/ 11008 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void)) 11009 { 11010 PetscFunctionBegin; 11011 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11012 *f = (((void (**)(void))mat->ops)[op]); 11013 PetscFunctionReturn(PETSC_SUCCESS); 11014 } 11015 11016 /*@ 11017 MatHasOperation - Determines whether the given matrix supports the particular operation. 11018 11019 Not Collective 11020 11021 Input Parameters: 11022 + mat - the matrix 11023 - op - the operation, for example, `MATOP_GET_DIAGONAL` 11024 11025 Output Parameter: 11026 . has - either `PETSC_TRUE` or `PETSC_FALSE` 11027 11028 Level: advanced 11029 11030 Note: 11031 See `MatSetOperation()` for additional discussion on naming convention and usage of `op`. 11032 11033 .seealso: [](chapter_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()` 11034 @*/ 11035 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has) 11036 { 11037 PetscFunctionBegin; 11038 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11039 PetscValidBoolPointer(has, 3); 11040 if (mat->ops->hasoperation) { 11041 PetscUseTypeMethod(mat, hasoperation, op, has); 11042 } else { 11043 if (((void **)mat->ops)[op]) *has = PETSC_TRUE; 11044 else { 11045 *has = PETSC_FALSE; 11046 if (op == MATOP_CREATE_SUBMATRIX) { 11047 PetscMPIInt size; 11048 11049 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 11050 if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has)); 11051 } 11052 } 11053 } 11054 PetscFunctionReturn(PETSC_SUCCESS); 11055 } 11056 11057 /*@ 11058 MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent 11059 11060 Collective 11061 11062 Input Parameter: 11063 . mat - the matrix 11064 11065 Output Parameter: 11066 . cong - either `PETSC_TRUE` or `PETSC_FALSE` 11067 11068 Level: beginner 11069 11070 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout` 11071 @*/ 11072 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong) 11073 { 11074 PetscFunctionBegin; 11075 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11076 PetscValidType(mat, 1); 11077 PetscValidBoolPointer(cong, 2); 11078 if (!mat->rmap || !mat->cmap) { 11079 *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE; 11080 PetscFunctionReturn(PETSC_SUCCESS); 11081 } 11082 if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */ 11083 PetscCall(PetscLayoutSetUp(mat->rmap)); 11084 PetscCall(PetscLayoutSetUp(mat->cmap)); 11085 PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong)); 11086 if (*cong) mat->congruentlayouts = 1; 11087 else mat->congruentlayouts = 0; 11088 } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE; 11089 PetscFunctionReturn(PETSC_SUCCESS); 11090 } 11091 11092 PetscErrorCode MatSetInf(Mat A) 11093 { 11094 PetscFunctionBegin; 11095 PetscUseTypeMethod(A, setinf); 11096 PetscFunctionReturn(PETSC_SUCCESS); 11097 } 11098 11099 /*@C 11100 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 11101 and possibly removes small values from the graph structure. 11102 11103 Collective 11104 11105 Input Parameters: 11106 + A - the matrix 11107 . sym - `PETSC_TRUE` indicates that the graph should be symmetrized 11108 . scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry 11109 - filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value 11110 11111 Output Parameter: 11112 . graph - the resulting graph 11113 11114 Level: advanced 11115 11116 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `PCGAMG` 11117 @*/ 11118 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph) 11119 { 11120 PetscFunctionBegin; 11121 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11122 PetscValidType(A, 1); 11123 PetscValidLogicalCollectiveBool(A, scale, 3); 11124 PetscValidPointer(graph, 5); 11125 PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph); 11126 PetscFunctionReturn(PETSC_SUCCESS); 11127 } 11128 11129 /*@ 11130 MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place, 11131 meaning the same memory is used for the matrix, and no new memory is allocated. 11132 11133 Collective 11134 11135 Input Parameter: 11136 . A - the matrix 11137 11138 Level: intermediate 11139 11140 Developer Note: 11141 The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end 11142 of the arrays in the data structure are unneeded. 11143 11144 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatChop()` 11145 @*/ 11146 PetscErrorCode MatEliminateZeros(Mat A) 11147 { 11148 PetscFunctionBegin; 11149 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11150 PetscUseTypeMethod(A, eliminatezeros); 11151 PetscFunctionReturn(PETSC_SUCCESS); 11152 } 11153