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