1 /* 2 This is where the abstract matrix operations are defined 3 Portions of this code are under: 4 Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved. 5 */ 6 7 #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/ 8 #include <petsc/private/isimpl.h> 9 #include <petsc/private/vecimpl.h> 10 11 /* Logging support */ 12 PetscClassId MAT_CLASSID; 13 PetscClassId MAT_COLORING_CLASSID; 14 PetscClassId MAT_FDCOLORING_CLASSID; 15 PetscClassId MAT_TRANSPOSECOLORING_CLASSID; 16 17 PetscLogEvent MAT_Mult, MAT_MultAdd, MAT_MultTranspose; 18 PetscLogEvent MAT_MultTransposeAdd, MAT_Solve, MAT_Solves, MAT_SolveAdd, MAT_SolveTranspose, MAT_MatSolve, MAT_MatTrSolve; 19 PetscLogEvent MAT_SolveTransposeAdd, MAT_SOR, MAT_ForwardSolve, MAT_BackwardSolve, MAT_LUFactor, MAT_LUFactorSymbolic; 20 PetscLogEvent MAT_LUFactorNumeric, MAT_CholeskyFactor, MAT_CholeskyFactorSymbolic, MAT_CholeskyFactorNumeric, MAT_ILUFactor; 21 PetscLogEvent MAT_ILUFactorSymbolic, MAT_ICCFactorSymbolic, MAT_Copy, MAT_Convert, MAT_Scale, MAT_AssemblyBegin; 22 PetscLogEvent MAT_QRFactorNumeric, MAT_QRFactorSymbolic, MAT_QRFactor; 23 PetscLogEvent MAT_AssemblyEnd, MAT_SetValues, MAT_GetValues, MAT_GetRow, MAT_GetRowIJ, MAT_CreateSubMats, MAT_GetOrdering, MAT_RedundantMat, MAT_GetSeqNonzeroStructure; 24 PetscLogEvent MAT_IncreaseOverlap, MAT_Partitioning, MAT_PartitioningND, MAT_Coarsen, MAT_ZeroEntries, MAT_Load, MAT_View, MAT_AXPY, MAT_FDColoringCreate; 25 PetscLogEvent MAT_FDColoringSetUp, MAT_FDColoringApply, MAT_Transpose, MAT_FDColoringFunction, MAT_CreateSubMat; 26 PetscLogEvent MAT_TransposeColoringCreate; 27 PetscLogEvent MAT_MatMult, MAT_MatMultSymbolic, MAT_MatMultNumeric; 28 PetscLogEvent MAT_PtAP, MAT_PtAPSymbolic, MAT_PtAPNumeric, MAT_RARt, MAT_RARtSymbolic, MAT_RARtNumeric; 29 PetscLogEvent MAT_MatTransposeMult, MAT_MatTransposeMultSymbolic, MAT_MatTransposeMultNumeric; 30 PetscLogEvent MAT_TransposeMatMult, MAT_TransposeMatMultSymbolic, MAT_TransposeMatMultNumeric; 31 PetscLogEvent MAT_MatMatMult, MAT_MatMatMultSymbolic, MAT_MatMatMultNumeric; 32 PetscLogEvent MAT_MultHermitianTranspose, MAT_MultHermitianTransposeAdd; 33 PetscLogEvent MAT_Getsymtransreduced, MAT_GetBrowsOfAcols; 34 PetscLogEvent MAT_GetBrowsOfAocols, MAT_Getlocalmat, MAT_Getlocalmatcondensed, MAT_Seqstompi, MAT_Seqstompinum, MAT_Seqstompisym; 35 PetscLogEvent MAT_GetMultiProcBlock; 36 PetscLogEvent MAT_CUSPARSECopyToGPU, MAT_CUSPARSECopyFromGPU, MAT_CUSPARSEGenerateTranspose, MAT_CUSPARSESolveAnalysis; 37 PetscLogEvent MAT_HIPSPARSECopyToGPU, MAT_HIPSPARSECopyFromGPU, MAT_HIPSPARSEGenerateTranspose, MAT_HIPSPARSESolveAnalysis; 38 PetscLogEvent MAT_PreallCOO, MAT_SetVCOO; 39 PetscLogEvent MAT_SetValuesBatch; 40 PetscLogEvent MAT_ViennaCLCopyToGPU; 41 PetscLogEvent MAT_CUDACopyToGPU; 42 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU; 43 PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom; 44 PetscLogEvent MAT_FactorFactS, MAT_FactorInvS; 45 PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights; 46 PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR; 47 48 const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL}; 49 50 /*@ 51 MatSetRandom - Sets all components of a matrix to random numbers. 52 53 Logically Collective 54 55 Input Parameters: 56 + x - the matrix 57 - rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or `NULL` and 58 it will create one internally. 59 60 Example: 61 .vb 62 PetscRandomCreate(PETSC_COMM_WORLD,&rctx); 63 MatSetRandom(x,rctx); 64 PetscRandomDestroy(rctx); 65 .ve 66 67 Level: intermediate 68 69 Notes: 70 For sparse matrices that have been preallocated but not been assembled it randomly selects appropriate locations, 71 72 for sparse matrices that already have locations it fills the locations with random numbers. 73 74 It generates an error if used on sparse matrices that have not been preallocated. 75 76 .seealso: [](chapter_matrices), `Mat`, `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomCreate()`, `PetscRandomDestroy()` 77 @*/ 78 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx) 79 { 80 PetscRandom randObj = NULL; 81 82 PetscFunctionBegin; 83 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 84 if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2); 85 PetscValidType(x, 1); 86 MatCheckPreallocated(x, 1); 87 88 if (!rctx) { 89 MPI_Comm comm; 90 PetscCall(PetscObjectGetComm((PetscObject)x, &comm)); 91 PetscCall(PetscRandomCreate(comm, &randObj)); 92 PetscCall(PetscRandomSetType(randObj, x->defaultrandtype)); 93 PetscCall(PetscRandomSetFromOptions(randObj)); 94 rctx = randObj; 95 } 96 PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0)); 97 PetscUseTypeMethod(x, setrandom, rctx); 98 PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0)); 99 100 PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY)); 101 PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY)); 102 PetscCall(PetscRandomDestroy(&randObj)); 103 PetscFunctionReturn(PETSC_SUCCESS); 104 } 105 106 /*@ 107 MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in 108 109 Logically Collective 110 111 Input Parameter: 112 . mat - the factored matrix 113 114 Output Parameters: 115 + pivot - the pivot value computed 116 - row - the row that the zero pivot occurred. This row value must be interpreted carefully due to row reorderings and which processes 117 the share the matrix 118 119 Level: advanced 120 121 Notes: 122 This routine does not work for factorizations done with external packages. 123 124 This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT` 125 126 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 127 128 .seealso: [](chapter_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, 129 `MAT_FACTOR_NUMERIC_ZEROPIVOT` 130 @*/ 131 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row) 132 { 133 PetscFunctionBegin; 134 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 135 PetscValidRealPointer(pivot, 2); 136 PetscValidIntPointer(row, 3); 137 *pivot = mat->factorerror_zeropivot_value; 138 *row = mat->factorerror_zeropivot_row; 139 PetscFunctionReturn(PETSC_SUCCESS); 140 } 141 142 /*@ 143 MatFactorGetError - gets the error code from a factorization 144 145 Logically Collective 146 147 Input Parameter: 148 . mat - the factored matrix 149 150 Output Parameter: 151 . err - the error code 152 153 Level: advanced 154 155 Note: 156 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 157 158 .seealso: [](chapter_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, 159 `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, `MatFactorError` 160 @*/ 161 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err) 162 { 163 PetscFunctionBegin; 164 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 165 PetscValidPointer(err, 2); 166 *err = mat->factorerrortype; 167 PetscFunctionReturn(PETSC_SUCCESS); 168 } 169 170 /*@ 171 MatFactorClearError - clears the error code in a factorization 172 173 Logically Collective 174 175 Input Parameter: 176 . mat - the factored matrix 177 178 Level: developer 179 180 Note: 181 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 182 183 .seealso: [](chapter_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`, 184 `MatGetErrorCode()`, `MatFactorError` 185 @*/ 186 PetscErrorCode MatFactorClearError(Mat mat) 187 { 188 PetscFunctionBegin; 189 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 190 mat->factorerrortype = MAT_FACTOR_NOERROR; 191 mat->factorerror_zeropivot_value = 0.0; 192 mat->factorerror_zeropivot_row = 0; 193 PetscFunctionReturn(PETSC_SUCCESS); 194 } 195 196 PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero) 197 { 198 Vec r, l; 199 const PetscScalar *al; 200 PetscInt i, nz, gnz, N, n; 201 202 PetscFunctionBegin; 203 PetscCall(MatCreateVecs(mat, &r, &l)); 204 if (!cols) { /* nonzero rows */ 205 PetscCall(MatGetSize(mat, &N, NULL)); 206 PetscCall(MatGetLocalSize(mat, &n, NULL)); 207 PetscCall(VecSet(l, 0.0)); 208 PetscCall(VecSetRandom(r, NULL)); 209 PetscCall(MatMult(mat, r, l)); 210 PetscCall(VecGetArrayRead(l, &al)); 211 } else { /* nonzero columns */ 212 PetscCall(MatGetSize(mat, NULL, &N)); 213 PetscCall(MatGetLocalSize(mat, NULL, &n)); 214 PetscCall(VecSet(r, 0.0)); 215 PetscCall(VecSetRandom(l, NULL)); 216 PetscCall(MatMultTranspose(mat, l, r)); 217 PetscCall(VecGetArrayRead(r, &al)); 218 } 219 if (tol <= 0.0) { 220 for (i = 0, nz = 0; i < n; i++) 221 if (al[i] != 0.0) nz++; 222 } else { 223 for (i = 0, nz = 0; i < n; i++) 224 if (PetscAbsScalar(al[i]) > tol) nz++; 225 } 226 PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 227 if (gnz != N) { 228 PetscInt *nzr; 229 PetscCall(PetscMalloc1(nz, &nzr)); 230 if (nz) { 231 if (tol < 0) { 232 for (i = 0, nz = 0; i < n; i++) 233 if (al[i] != 0.0) nzr[nz++] = i; 234 } else { 235 for (i = 0, nz = 0; i < n; i++) 236 if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i; 237 } 238 } 239 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero)); 240 } else *nonzero = NULL; 241 if (!cols) { /* nonzero rows */ 242 PetscCall(VecRestoreArrayRead(l, &al)); 243 } else { 244 PetscCall(VecRestoreArrayRead(r, &al)); 245 } 246 PetscCall(VecDestroy(&l)); 247 PetscCall(VecDestroy(&r)); 248 PetscFunctionReturn(PETSC_SUCCESS); 249 } 250 251 /*@ 252 MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix 253 254 Input Parameter: 255 . A - the matrix 256 257 Output Parameter: 258 . keptrows - the rows that are not completely zero 259 260 Level: intermediate 261 262 Note: 263 `keptrows` is set to `NULL` if all rows are nonzero. 264 265 .seealso: [](chapter_matrices), `Mat`, `MatFindZeroRows()` 266 @*/ 267 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows) 268 { 269 PetscFunctionBegin; 270 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 271 PetscValidType(mat, 1); 272 PetscValidPointer(keptrows, 2); 273 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 274 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 275 if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows); 276 else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows)); 277 PetscFunctionReturn(PETSC_SUCCESS); 278 } 279 280 /*@ 281 MatFindZeroRows - Locate all rows that are completely zero in the matrix 282 283 Input Parameter: 284 . A - the matrix 285 286 Output Parameter: 287 . zerorows - the rows that are completely zero 288 289 Level: intermediate 290 291 Note: 292 `zerorows` is set to `NULL` if no rows are zero. 293 294 .seealso: [](chapter_matrices), `Mat`, `MatFindNonzeroRows()` 295 @*/ 296 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows) 297 { 298 IS keptrows; 299 PetscInt m, n; 300 301 PetscFunctionBegin; 302 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 303 PetscValidType(mat, 1); 304 PetscValidPointer(zerorows, 2); 305 PetscCall(MatFindNonzeroRows(mat, &keptrows)); 306 /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows. 307 In keeping with this convention, we set zerorows to NULL if there are no zero 308 rows. */ 309 if (keptrows == NULL) { 310 *zerorows = NULL; 311 } else { 312 PetscCall(MatGetOwnershipRange(mat, &m, &n)); 313 PetscCall(ISComplement(keptrows, m, n, zerorows)); 314 PetscCall(ISDestroy(&keptrows)); 315 } 316 PetscFunctionReturn(PETSC_SUCCESS); 317 } 318 319 /*@ 320 MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling 321 322 Not Collective 323 324 Input Parameter: 325 . A - the matrix 326 327 Output Parameter: 328 . a - the diagonal part (which is a SEQUENTIAL matrix) 329 330 Level: advanced 331 332 Notes: 333 See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix. 334 335 Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation. 336 337 .seealso: [](chapter_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ` 338 @*/ 339 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a) 340 { 341 PetscFunctionBegin; 342 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 343 PetscValidType(A, 1); 344 PetscValidPointer(a, 2); 345 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 346 if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a); 347 else { 348 PetscMPIInt size; 349 350 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 351 PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name); 352 *a = A; 353 } 354 PetscFunctionReturn(PETSC_SUCCESS); 355 } 356 357 /*@ 358 MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries. 359 360 Collective 361 362 Input Parameter: 363 . mat - the matrix 364 365 Output Parameter: 366 . trace - the sum of the diagonal entries 367 368 Level: advanced 369 370 .seealso: [](chapter_matrices), `Mat` 371 @*/ 372 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace) 373 { 374 Vec diag; 375 376 PetscFunctionBegin; 377 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 378 PetscValidScalarPointer(trace, 2); 379 PetscCall(MatCreateVecs(mat, &diag, NULL)); 380 PetscCall(MatGetDiagonal(mat, diag)); 381 PetscCall(VecSum(diag, trace)); 382 PetscCall(VecDestroy(&diag)); 383 PetscFunctionReturn(PETSC_SUCCESS); 384 } 385 386 /*@ 387 MatRealPart - Zeros out the imaginary part of the matrix 388 389 Logically Collective 390 391 Input Parameter: 392 . mat - the matrix 393 394 Level: advanced 395 396 .seealso: [](chapter_matrices), `Mat`, `MatImaginaryPart()` 397 @*/ 398 PetscErrorCode MatRealPart(Mat mat) 399 { 400 PetscFunctionBegin; 401 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 402 PetscValidType(mat, 1); 403 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 404 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 405 MatCheckPreallocated(mat, 1); 406 PetscUseTypeMethod(mat, realpart); 407 PetscFunctionReturn(PETSC_SUCCESS); 408 } 409 410 /*@C 411 MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix 412 413 Collective 414 415 Input Parameter: 416 . mat - the matrix 417 418 Output Parameters: 419 + nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each block) 420 - ghosts - the global indices of the ghost points 421 422 Level: advanced 423 424 Note: 425 `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()` 426 427 .seealso: [](chapter_matrices), `Mat`, `VecCreateGhost()` 428 @*/ 429 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[]) 430 { 431 PetscFunctionBegin; 432 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 433 PetscValidType(mat, 1); 434 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 435 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 436 if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts); 437 else { 438 if (nghosts) *nghosts = 0; 439 if (ghosts) *ghosts = NULL; 440 } 441 PetscFunctionReturn(PETSC_SUCCESS); 442 } 443 444 /*@ 445 MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part 446 447 Logically Collective 448 449 Input Parameter: 450 . mat - the matrix 451 452 Level: advanced 453 454 .seealso: [](chapter_matrices), `Mat`, `MatRealPart()` 455 @*/ 456 PetscErrorCode MatImaginaryPart(Mat mat) 457 { 458 PetscFunctionBegin; 459 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 460 PetscValidType(mat, 1); 461 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 462 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 463 MatCheckPreallocated(mat, 1); 464 PetscUseTypeMethod(mat, imaginarypart); 465 PetscFunctionReturn(PETSC_SUCCESS); 466 } 467 468 /*@ 469 MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices) 470 471 Not Collective 472 473 Input Parameter: 474 . mat - the matrix 475 476 Output Parameters: 477 + missing - is any diagonal missing 478 - dd - first diagonal entry that is missing (optional) on this process 479 480 Level: advanced 481 482 .seealso: [](chapter_matrices), `Mat` 483 @*/ 484 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd) 485 { 486 PetscFunctionBegin; 487 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 488 PetscValidType(mat, 1); 489 PetscValidBoolPointer(missing, 2); 490 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name); 491 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 492 PetscUseTypeMethod(mat, missingdiagonal, missing, dd); 493 PetscFunctionReturn(PETSC_SUCCESS); 494 } 495 496 /*@C 497 MatGetRow - Gets a row of a matrix. You MUST call `MatRestoreRow()` 498 for each row that you get to ensure that your application does 499 not bleed memory. 500 501 Not Collective 502 503 Input Parameters: 504 + mat - the matrix 505 - row - the row to get 506 507 Output Parameters: 508 + ncols - if not `NULL`, the number of nonzeros in the row 509 . cols - if not `NULL`, the column numbers 510 - vals - if not `NULL`, the values 511 512 Level: advanced 513 514 Notes: 515 This routine is provided for people who need to have direct access 516 to the structure of a matrix. We hope that we provide enough 517 high-level matrix routines that few users will need it. 518 519 `MatGetRow()` always returns 0-based column indices, regardless of 520 whether the internal representation is 0-based (default) or 1-based. 521 522 For better efficiency, set cols and/or vals to `NULL` if you do 523 not wish to extract these quantities. 524 525 The user can only examine the values extracted with `MatGetRow()`; 526 the values cannot be altered. To change the matrix entries, one 527 must use `MatSetValues()`. 528 529 You can only have one call to `MatGetRow()` outstanding for a particular 530 matrix at a time, per processor. `MatGetRow()` can only obtain rows 531 associated with the given processor, it cannot get rows from the 532 other processors; for that we suggest using `MatCreateSubMatrices()`, then 533 MatGetRow() on the submatrix. The row index passed to `MatGetRow()` 534 is in the global number of rows. 535 536 Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix. 537 538 Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly. 539 540 Fortran Note: 541 The calling sequence is 542 .vb 543 MatGetRow(matrix,row,ncols,cols,values,ierr) 544 Mat matrix (input) 545 integer row (input) 546 integer ncols (output) 547 integer cols(maxcols) (output) 548 double precision (or double complex) values(maxcols) output 549 .ve 550 where maxcols >= maximum nonzeros in any row of the matrix. 551 552 Caution: 553 Do not try to change the contents of the output arrays (`cols` and `vals`). 554 In some cases, this may corrupt the matrix. 555 556 .seealso: [](chapter_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()` 557 @*/ 558 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 559 { 560 PetscInt incols; 561 562 PetscFunctionBegin; 563 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 564 PetscValidType(mat, 1); 565 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 566 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 567 MatCheckPreallocated(mat, 1); 568 PetscCheck(row >= mat->rmap->rstart && row < mat->rmap->rend, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Only for local rows, %" PetscInt_FMT " not in [%" PetscInt_FMT ",%" PetscInt_FMT ")", row, mat->rmap->rstart, mat->rmap->rend); 569 PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0)); 570 PetscUseTypeMethod(mat, getrow, row, &incols, (PetscInt **)cols, (PetscScalar **)vals); 571 if (ncols) *ncols = incols; 572 PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0)); 573 PetscFunctionReturn(PETSC_SUCCESS); 574 } 575 576 /*@ 577 MatConjugate - replaces the matrix values with their complex conjugates 578 579 Logically Collective 580 581 Input Parameter: 582 . mat - the matrix 583 584 Level: advanced 585 586 .seealso: [](chapter_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()` 587 @*/ 588 PetscErrorCode MatConjugate(Mat mat) 589 { 590 PetscFunctionBegin; 591 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 592 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 593 if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) { 594 PetscUseTypeMethod(mat, conjugate); 595 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 596 } 597 PetscFunctionReturn(PETSC_SUCCESS); 598 } 599 600 /*@C 601 MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`. 602 603 Not Collective 604 605 Input Parameters: 606 + mat - the matrix 607 . row - the row to get 608 . ncols - the number of nonzeros 609 . cols - the columns of the nonzeros 610 - vals - if nonzero the column values 611 612 Level: advanced 613 614 Notes: 615 This routine should be called after you have finished examining the entries. 616 617 This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental 618 us of the array after it has been restored. If you pass `NULL`, it will 619 not zero the pointers. Use of `cols` or `vals` after `MatRestoreRow()` is invalid. 620 621 Fortran Notes: 622 The calling sequence is 623 .vb 624 MatRestoreRow(matrix,row,ncols,cols,values,ierr) 625 Mat matrix (input) 626 integer row (input) 627 integer ncols (output) 628 integer cols(maxcols) (output) 629 double precision (or double complex) values(maxcols) output 630 .ve 631 Where maxcols >= maximum nonzeros in any row of the matrix. 632 633 In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()` 634 before another call to `MatGetRow()` can be made. 635 636 .seealso: [](chapter_matrices), `Mat`, `MatGetRow()` 637 @*/ 638 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 639 { 640 PetscFunctionBegin; 641 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 642 if (ncols) PetscValidIntPointer(ncols, 3); 643 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 644 if (!mat->ops->restorerow) PetscFunctionReturn(PETSC_SUCCESS); 645 PetscUseTypeMethod(mat, restorerow, row, ncols, (PetscInt **)cols, (PetscScalar **)vals); 646 if (ncols) *ncols = 0; 647 if (cols) *cols = NULL; 648 if (vals) *vals = NULL; 649 PetscFunctionReturn(PETSC_SUCCESS); 650 } 651 652 /*@ 653 MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 654 You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag. 655 656 Not Collective 657 658 Input Parameter: 659 . mat - the matrix 660 661 Level: advanced 662 663 Note: 664 The flag is to ensure that users are aware that `MatGetRow()` only provides the upper triangular part of the row for the matrices in `MATSBAIJ` format. 665 666 .seealso: [](chapter_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()` 667 @*/ 668 PetscErrorCode MatGetRowUpperTriangular(Mat mat) 669 { 670 PetscFunctionBegin; 671 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 672 PetscValidType(mat, 1); 673 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 674 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 675 MatCheckPreallocated(mat, 1); 676 if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS); 677 PetscUseTypeMethod(mat, getrowuppertriangular); 678 PetscFunctionReturn(PETSC_SUCCESS); 679 } 680 681 /*@ 682 MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 683 684 Not Collective 685 686 Input Parameter: 687 . mat - the matrix 688 689 Level: advanced 690 691 Note: 692 This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`. 693 694 .seealso: [](chapter_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()` 695 @*/ 696 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat) 697 { 698 PetscFunctionBegin; 699 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 700 PetscValidType(mat, 1); 701 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 702 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 703 MatCheckPreallocated(mat, 1); 704 if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS); 705 PetscUseTypeMethod(mat, restorerowuppertriangular); 706 PetscFunctionReturn(PETSC_SUCCESS); 707 } 708 709 /*@C 710 MatSetOptionsPrefix - Sets the prefix used for searching for all 711 `Mat` options in the database. 712 713 Logically Collective 714 715 Input Parameters: 716 + A - the matrix 717 - prefix - the prefix to prepend to all option names 718 719 Level: advanced 720 721 Notes: 722 A hyphen (-) must NOT be given at the beginning of the prefix name. 723 The first character of all runtime options is AUTOMATICALLY the hyphen. 724 725 This is NOT used for options for the factorization of the matrix. Normally the 726 prefix is automatically passed in from the PC calling the factorization. To set 727 it directly use `MatSetOptionsPrefixFactor()` 728 729 .seealso: [](chapter_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()` 730 @*/ 731 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[]) 732 { 733 PetscFunctionBegin; 734 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 735 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix)); 736 PetscFunctionReturn(PETSC_SUCCESS); 737 } 738 739 /*@C 740 MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for 741 for matrices created with `MatGetFactor()` 742 743 Logically Collective 744 745 Input Parameters: 746 + A - the matrix 747 - prefix - the prefix to prepend to all option names for the factored matrix 748 749 Level: developer 750 751 Notes: 752 A hyphen (-) must NOT be given at the beginning of the prefix name. 753 The first character of all runtime options is AUTOMATICALLY the hyphen. 754 755 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 756 it directly when not using `KSP`/`PC` use `MatSetOptionsPrefixFactor()` 757 758 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()` 759 @*/ 760 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[]) 761 { 762 PetscFunctionBegin; 763 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 764 if (prefix) { 765 PetscValidCharPointer(prefix, 2); 766 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 767 if (prefix != A->factorprefix) { 768 PetscCall(PetscFree(A->factorprefix)); 769 PetscCall(PetscStrallocpy(prefix, &A->factorprefix)); 770 } 771 } else PetscCall(PetscFree(A->factorprefix)); 772 PetscFunctionReturn(PETSC_SUCCESS); 773 } 774 775 /*@C 776 MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for 777 for matrices created with `MatGetFactor()` 778 779 Logically Collective 780 781 Input Parameters: 782 + A - the matrix 783 - prefix - the prefix to prepend to all option names for the factored matrix 784 785 Level: developer 786 787 Notes: 788 A hyphen (-) must NOT be given at the beginning of the prefix name. 789 The first character of all runtime options is AUTOMATICALLY the hyphen. 790 791 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 792 it directly when not using `KSP`/`PC` use `MatAppendOptionsPrefixFactor()` 793 794 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`, 795 `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`, 796 `MatSetOptionsPrefix()` 797 @*/ 798 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[]) 799 { 800 size_t len1, len2, new_len; 801 802 PetscFunctionBegin; 803 PetscValidHeader(A, 1); 804 if (!prefix) PetscFunctionReturn(PETSC_SUCCESS); 805 if (!A->factorprefix) { 806 PetscCall(MatSetOptionsPrefixFactor(A, prefix)); 807 PetscFunctionReturn(PETSC_SUCCESS); 808 } 809 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 810 811 PetscCall(PetscStrlen(A->factorprefix, &len1)); 812 PetscCall(PetscStrlen(prefix, &len2)); 813 new_len = len1 + len2 + 1; 814 PetscCall(PetscRealloc(new_len * sizeof(*(A->factorprefix)), &A->factorprefix)); 815 PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1)); 816 PetscFunctionReturn(PETSC_SUCCESS); 817 } 818 819 /*@C 820 MatAppendOptionsPrefix - Appends to the prefix used for searching for all 821 matrix options in the database. 822 823 Logically Collective 824 825 Input Parameters: 826 + A - the matrix 827 - prefix - the prefix to prepend to all option names 828 829 Level: advanced 830 831 Note: 832 A hyphen (-) must NOT be given at the beginning of the prefix name. 833 The first character of all runtime options is AUTOMATICALLY the hyphen. 834 835 .seealso: [](chapter_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()` 836 @*/ 837 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[]) 838 { 839 PetscFunctionBegin; 840 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 841 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix)); 842 PetscFunctionReturn(PETSC_SUCCESS); 843 } 844 845 /*@C 846 MatGetOptionsPrefix - Gets the prefix used for searching for all 847 matrix options in the database. 848 849 Not Collective 850 851 Input Parameter: 852 . A - the matrix 853 854 Output Parameter: 855 . prefix - pointer to the prefix string used 856 857 Level: advanced 858 859 Fortran Note: 860 The user should pass in a string `prefix` of 861 sufficient length to hold the prefix. 862 863 .seealso: [](chapter_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()` 864 @*/ 865 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[]) 866 { 867 PetscFunctionBegin; 868 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 869 PetscValidPointer(prefix, 2); 870 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix)); 871 PetscFunctionReturn(PETSC_SUCCESS); 872 } 873 874 /*@ 875 MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by users. 876 877 Collective 878 879 Input Parameter: 880 . A - the matrix 881 882 Level: beginner 883 884 Notes: 885 The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`. 886 887 Users can reset the preallocation to access the original memory. 888 889 Currently only supported for `MATAIJ` matrices. 890 891 .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()` 892 @*/ 893 PetscErrorCode MatResetPreallocation(Mat A) 894 { 895 PetscFunctionBegin; 896 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 897 PetscValidType(A, 1); 898 PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A)); 899 PetscFunctionReturn(PETSC_SUCCESS); 900 } 901 902 /*@ 903 MatSetUp - Sets up the internal matrix data structures for later use. 904 905 Collective 906 907 Input Parameter: 908 . A - the matrix 909 910 Level: intermediate 911 912 Notes: 913 If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of 914 setting values in the matrix. 915 916 If a suitable preallocation routine is used, this function does not need to be called. 917 918 This routine is called internally by other matrix functions when needed so rarely needs to be called by users 919 920 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()` 921 @*/ 922 PetscErrorCode MatSetUp(Mat A) 923 { 924 PetscFunctionBegin; 925 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 926 if (!((PetscObject)A)->type_name) { 927 PetscMPIInt size; 928 929 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 930 PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ)); 931 } 932 if (!A->preallocated) PetscTryTypeMethod(A, setup); 933 PetscCall(PetscLayoutSetUp(A->rmap)); 934 PetscCall(PetscLayoutSetUp(A->cmap)); 935 A->preallocated = PETSC_TRUE; 936 PetscFunctionReturn(PETSC_SUCCESS); 937 } 938 939 #if defined(PETSC_HAVE_SAWS) 940 #include <petscviewersaws.h> 941 #endif 942 943 /*@C 944 MatViewFromOptions - View properties of the matrix based on options set in the options database 945 946 Collective 947 948 Input Parameters: 949 + A - the matrix 950 . obj - optional additional object that provides the options prefix to use 951 - name - command line option 952 953 Options Database Key: 954 . -mat_view [viewertype]:... - the viewer and its options 955 956 Level: intermediate 957 958 Notes: 959 .vb 960 If no value is provided ascii:stdout is used 961 ascii[:[filename][:[format][:append]]] defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab, 962 for example ascii::ascii_info prints just the information about the object not all details 963 unless :append is given filename opens in write mode, overwriting what was already there 964 binary[:[filename][:[format][:append]]] defaults to the file binaryoutput 965 draw[:drawtype[:filename]] for example, draw:tikz, draw:tikz:figure.tex or draw:x 966 socket[:port] defaults to the standard output port 967 saws[:communicatorname] publishes object to the Scientific Application Webserver (SAWs) 968 .ve 969 970 .seealso: [](chapter_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()` 971 @*/ 972 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[]) 973 { 974 PetscFunctionBegin; 975 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 976 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 977 PetscFunctionReturn(PETSC_SUCCESS); 978 } 979 980 /*@C 981 MatView - display information about a matrix in a variety ways 982 983 Collective 984 985 Input Parameters: 986 + mat - the matrix 987 - viewer - visualization context 988 989 Options Database Keys: 990 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 991 . -mat_view ::ascii_info_detail - Prints more detailed info 992 . -mat_view - Prints matrix in ASCII format 993 . -mat_view ::ascii_matlab - Prints matrix in Matlab format 994 . -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 995 . -display <name> - Sets display name (default is host) 996 . -draw_pause <sec> - Sets number of seconds to pause after display 997 . -mat_view socket - Sends matrix to socket, can be accessed from Matlab (see Users-Manual: ch_matlab for details) 998 . -viewer_socket_machine <machine> - 999 . -viewer_socket_port <port> - 1000 . -mat_view binary - save matrix to file in binary format 1001 - -viewer_binary_filename <name> - 1002 1003 Level: beginner 1004 1005 Notes: 1006 The available visualization contexts include 1007 + `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices 1008 . `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD` 1009 . `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm 1010 - `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure 1011 1012 The user can open alternative visualization contexts with 1013 + `PetscViewerASCIIOpen()` - Outputs matrix to a specified file 1014 . `PetscViewerBinaryOpen()` - Outputs matrix in binary to a 1015 specified file; corresponding input uses MatLoad() 1016 . `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to 1017 an X window display 1018 - `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer. 1019 Currently only the sequential dense and AIJ 1020 matrix types support the Socket viewer. 1021 1022 The user can call `PetscViewerPushFormat()` to specify the output 1023 format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`, 1024 `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`). Available formats include 1025 + `PETSC_VIEWER_DEFAULT` - default, prints matrix contents 1026 . `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in Matlab format 1027 . `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros 1028 . `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse 1029 format common among all matrix types 1030 . `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific 1031 format (which is in many cases the same as the default) 1032 . `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix 1033 size and structure (not the matrix entries) 1034 - `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about 1035 the matrix structure 1036 1037 The ASCII viewers are only recommended for small matrices on at most a moderate number of processes, 1038 the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format. 1039 1040 In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer). 1041 1042 See the manual page for `MatLoad()` for the exact format of the binary file when the binary 1043 viewer is used. 1044 1045 See share/petsc/matlab/PetscBinaryRead.m for a Matlab code that can read in the binary file when the binary 1046 viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python. 1047 1048 One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure, 1049 and then use the following mouse functions. 1050 .vb 1051 left mouse: zoom in 1052 middle mouse: zoom out 1053 right mouse: continue with the simulation 1054 .ve 1055 1056 .seealso: [](chapter_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`, 1057 `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()` 1058 @*/ 1059 PetscErrorCode MatView(Mat mat, PetscViewer viewer) 1060 { 1061 PetscInt rows, cols, rbs, cbs; 1062 PetscBool isascii, isstring, issaws; 1063 PetscViewerFormat format; 1064 PetscMPIInt size; 1065 1066 PetscFunctionBegin; 1067 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1068 PetscValidType(mat, 1); 1069 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer)); 1070 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1071 PetscCheckSameComm(mat, 1, viewer, 2); 1072 1073 PetscCall(PetscViewerGetFormat(viewer, &format)); 1074 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 1075 if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS); 1076 1077 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 1078 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 1079 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws)); 1080 PetscCheck((isascii && (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL)) || !mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "No viewers for factored matrix except ASCII, info, or info_detail"); 1081 1082 PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0)); 1083 if (isascii) { 1084 if (!mat->preallocated) { 1085 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n")); 1086 PetscFunctionReturn(PETSC_SUCCESS); 1087 } 1088 if (!mat->assembled) { 1089 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n")); 1090 PetscFunctionReturn(PETSC_SUCCESS); 1091 } 1092 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer)); 1093 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1094 MatNullSpace nullsp, transnullsp; 1095 1096 PetscCall(PetscViewerASCIIPushTab(viewer)); 1097 PetscCall(MatGetSize(mat, &rows, &cols)); 1098 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1099 if (rbs != 1 || cbs != 1) { 1100 if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs)); 1101 else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs)); 1102 } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols)); 1103 if (mat->factortype) { 1104 MatSolverType solver; 1105 PetscCall(MatFactorGetSolverType(mat, &solver)); 1106 PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver)); 1107 } 1108 if (mat->ops->getinfo) { 1109 MatInfo info; 1110 PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info)); 1111 PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated)); 1112 if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs)); 1113 } 1114 PetscCall(MatGetNullSpace(mat, &nullsp)); 1115 PetscCall(MatGetTransposeNullSpace(mat, &transnullsp)); 1116 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached null space\n")); 1117 if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached transposed null space\n")); 1118 PetscCall(MatGetNearNullSpace(mat, &nullsp)); 1119 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached near null space\n")); 1120 PetscCall(PetscViewerASCIIPushTab(viewer)); 1121 PetscCall(MatProductView(mat, viewer)); 1122 PetscCall(PetscViewerASCIIPopTab(viewer)); 1123 } 1124 } else if (issaws) { 1125 #if defined(PETSC_HAVE_SAWS) 1126 PetscMPIInt rank; 1127 1128 PetscCall(PetscObjectName((PetscObject)mat)); 1129 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 1130 if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer)); 1131 #endif 1132 } else if (isstring) { 1133 const char *type; 1134 PetscCall(MatGetType(mat, &type)); 1135 PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type)); 1136 PetscTryTypeMethod(mat, view, viewer); 1137 } 1138 if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) { 1139 PetscCall(PetscViewerASCIIPushTab(viewer)); 1140 PetscUseTypeMethod(mat, viewnative, viewer); 1141 PetscCall(PetscViewerASCIIPopTab(viewer)); 1142 } else if (mat->ops->view) { 1143 PetscCall(PetscViewerASCIIPushTab(viewer)); 1144 PetscUseTypeMethod(mat, view, viewer); 1145 PetscCall(PetscViewerASCIIPopTab(viewer)); 1146 } 1147 if (isascii) { 1148 PetscCall(PetscViewerGetFormat(viewer, &format)); 1149 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer)); 1150 } 1151 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1152 PetscFunctionReturn(PETSC_SUCCESS); 1153 } 1154 1155 #if defined(PETSC_USE_DEBUG) 1156 #include <../src/sys/totalview/tv_data_display.h> 1157 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat) 1158 { 1159 TV_add_row("Local rows", "int", &mat->rmap->n); 1160 TV_add_row("Local columns", "int", &mat->cmap->n); 1161 TV_add_row("Global rows", "int", &mat->rmap->N); 1162 TV_add_row("Global columns", "int", &mat->cmap->N); 1163 TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name); 1164 return TV_format_OK; 1165 } 1166 #endif 1167 1168 /*@C 1169 MatLoad - Loads a matrix that has been stored in binary/HDF5 format 1170 with `MatView()`. The matrix format is determined from the options database. 1171 Generates a parallel MPI matrix if the communicator has more than one 1172 processor. The default matrix type is `MATAIJ`. 1173 1174 Collective 1175 1176 Input Parameters: 1177 + mat - the newly loaded matrix, this needs to have been created with `MatCreate()` 1178 or some related function before a call to `MatLoad()` 1179 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer 1180 1181 Options Database Keys: 1182 Used with block matrix formats (`MATSEQBAIJ`, ...) to specify 1183 block size 1184 . -matload_block_size <bs> - set block size 1185 1186 Level: beginner 1187 1188 Notes: 1189 If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the 1190 `Mat` before calling this routine if you wish to set it from the options database. 1191 1192 `MatLoad()` automatically loads into the options database any options 1193 given in the file filename.info where filename is the name of the file 1194 that was passed to the `PetscViewerBinaryOpen()`. The options in the info 1195 file will be ignored if you use the -viewer_binary_skip_info option. 1196 1197 If the type or size of mat is not set before a call to `MatLoad()`, PETSc 1198 sets the default matrix type AIJ and sets the local and global sizes. 1199 If type and/or size is already set, then the same are used. 1200 1201 In parallel, each processor can load a subset of rows (or the 1202 entire matrix). This routine is especially useful when a large 1203 matrix is stored on disk and only part of it is desired on each 1204 processor. For example, a parallel solver may access only some of 1205 the rows from each processor. The algorithm used here reads 1206 relatively small blocks of data rather than reading the entire 1207 matrix and then subsetting it. 1208 1209 Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`. 1210 Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`, 1211 or the sequence like 1212 .vb 1213 `PetscViewer` v; 1214 `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v); 1215 `PetscViewerSetType`(v,`PETSCVIEWERBINARY`); 1216 `PetscViewerSetFromOptions`(v); 1217 `PetscViewerFileSetMode`(v,`FILE_MODE_READ`); 1218 `PetscViewerFileSetName`(v,"datafile"); 1219 .ve 1220 The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option 1221 $ -viewer_type {binary, hdf5} 1222 1223 See the example src/ksp/ksp/tutorials/ex27.c with the first approach, 1224 and src/mat/tutorials/ex10.c with the second approach. 1225 1226 In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks 1227 is read onto rank 0 and then shipped to its destination rank, one after another. 1228 Multiple objects, both matrices and vectors, can be stored within the same file. 1229 Their PetscObject name is ignored; they are loaded in the order of their storage. 1230 1231 Most users should not need to know the details of the binary storage 1232 format, since `MatLoad()` and `MatView()` completely hide these details. 1233 But for anyone who's interested, the standard binary matrix storage 1234 format is 1235 1236 .vb 1237 PetscInt MAT_FILE_CLASSID 1238 PetscInt number of rows 1239 PetscInt number of columns 1240 PetscInt total number of nonzeros 1241 PetscInt *number nonzeros in each row 1242 PetscInt *column indices of all nonzeros (starting index is zero) 1243 PetscScalar *values of all nonzeros 1244 .ve 1245 1246 PETSc automatically does the byte swapping for 1247 machines that store the bytes reversed. Thus if you write your own binary 1248 read/write routines you have to swap the bytes; see `PetscBinaryRead()` 1249 and `PetscBinaryWrite()` to see how this may be done. 1250 1251 In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used. 1252 Each processor's chunk is loaded independently by its owning rank. 1253 Multiple objects, both matrices and vectors, can be stored within the same file. 1254 They are looked up by their PetscObject name. 1255 1256 As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use 1257 by default the same structure and naming of the AIJ arrays and column count 1258 within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g. 1259 $ save example.mat A b -v7.3 1260 can be directly read by this routine (see Reference 1 for details). 1261 1262 Depending on your MATLAB version, this format might be a default, 1263 otherwise you can set it as default in Preferences. 1264 1265 Unless -nocompression flag is used to save the file in MATLAB, 1266 PETSc must be configured with ZLIB package. 1267 1268 See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c 1269 1270 This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5` 1271 1272 Corresponding `MatView()` is not yet implemented. 1273 1274 The loaded matrix is actually a transpose of the original one in MATLAB, 1275 unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above). 1276 With this format, matrix is automatically transposed by PETSc, 1277 unless the matrix is marked as SPD or symmetric 1278 (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`). 1279 1280 References: 1281 . * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version 1282 1283 .seealso: [](chapter_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()` 1284 @*/ 1285 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer) 1286 { 1287 PetscBool flg; 1288 1289 PetscFunctionBegin; 1290 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1291 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1292 1293 if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ)); 1294 1295 flg = PETSC_FALSE; 1296 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL)); 1297 if (flg) { 1298 PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE)); 1299 PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE)); 1300 } 1301 flg = PETSC_FALSE; 1302 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL)); 1303 if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE)); 1304 1305 PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0)); 1306 PetscUseTypeMethod(mat, load, viewer); 1307 PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0)); 1308 PetscFunctionReturn(PETSC_SUCCESS); 1309 } 1310 1311 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant) 1312 { 1313 Mat_Redundant *redund = *redundant; 1314 1315 PetscFunctionBegin; 1316 if (redund) { 1317 if (redund->matseq) { /* via MatCreateSubMatrices() */ 1318 PetscCall(ISDestroy(&redund->isrow)); 1319 PetscCall(ISDestroy(&redund->iscol)); 1320 PetscCall(MatDestroySubMatrices(1, &redund->matseq)); 1321 } else { 1322 PetscCall(PetscFree2(redund->send_rank, redund->recv_rank)); 1323 PetscCall(PetscFree(redund->sbuf_j)); 1324 PetscCall(PetscFree(redund->sbuf_a)); 1325 for (PetscInt i = 0; i < redund->nrecvs; i++) { 1326 PetscCall(PetscFree(redund->rbuf_j[i])); 1327 PetscCall(PetscFree(redund->rbuf_a[i])); 1328 } 1329 PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a)); 1330 } 1331 1332 if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm)); 1333 PetscCall(PetscFree(redund)); 1334 } 1335 PetscFunctionReturn(PETSC_SUCCESS); 1336 } 1337 1338 /*@C 1339 MatDestroy - Frees space taken by a matrix. 1340 1341 Collective 1342 1343 Input Parameter: 1344 . A - the matrix 1345 1346 Level: beginner 1347 1348 Developer Note: 1349 Some special arrays of matrices are not destroyed in this routine but instead by the routines called by 1350 `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines. 1351 `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes 1352 if changes are needed here. 1353 1354 .seealso: [](chapter_matrices), `Mat`, `MatCreate()` 1355 @*/ 1356 PetscErrorCode MatDestroy(Mat *A) 1357 { 1358 PetscFunctionBegin; 1359 if (!*A) PetscFunctionReturn(PETSC_SUCCESS); 1360 PetscValidHeaderSpecific(*A, MAT_CLASSID, 1); 1361 if (--((PetscObject)(*A))->refct > 0) { 1362 *A = NULL; 1363 PetscFunctionReturn(PETSC_SUCCESS); 1364 } 1365 1366 /* if memory was published with SAWs then destroy it */ 1367 PetscCall(PetscObjectSAWsViewOff((PetscObject)*A)); 1368 PetscTryTypeMethod((*A), destroy); 1369 1370 PetscCall(PetscFree((*A)->factorprefix)); 1371 PetscCall(PetscFree((*A)->defaultvectype)); 1372 PetscCall(PetscFree((*A)->defaultrandtype)); 1373 PetscCall(PetscFree((*A)->bsizes)); 1374 PetscCall(PetscFree((*A)->solvertype)); 1375 for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i])); 1376 if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL; 1377 PetscCall(MatDestroy_Redundant(&(*A)->redundant)); 1378 PetscCall(MatProductClear(*A)); 1379 PetscCall(MatNullSpaceDestroy(&(*A)->nullsp)); 1380 PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp)); 1381 PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp)); 1382 PetscCall(MatDestroy(&(*A)->schur)); 1383 PetscCall(PetscLayoutDestroy(&(*A)->rmap)); 1384 PetscCall(PetscLayoutDestroy(&(*A)->cmap)); 1385 PetscCall(PetscHeaderDestroy(A)); 1386 PetscFunctionReturn(PETSC_SUCCESS); 1387 } 1388 1389 /*@C 1390 MatSetValues - Inserts or adds a block of values into a matrix. 1391 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1392 MUST be called after all calls to `MatSetValues()` have been completed. 1393 1394 Not Collective 1395 1396 Input Parameters: 1397 + mat - the matrix 1398 . v - a logically two-dimensional array of values 1399 . m - the number of rows 1400 . idxm - the global indices of the rows 1401 . n - the number of columns 1402 . idxn - the global indices of the columns 1403 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1404 1405 Level: beginner 1406 1407 Notes: 1408 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1409 1410 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1411 options cannot be mixed without intervening calls to the assembly 1412 routines. 1413 1414 `MatSetValues()` uses 0-based row and column numbers in Fortran 1415 as well as in C. 1416 1417 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1418 simply ignored. This allows easily inserting element stiffness matrices 1419 with homogeneous Dirchlet boundary conditions that you don't want represented 1420 in the matrix. 1421 1422 Efficiency Alert: 1423 The routine `MatSetValuesBlocked()` may offer much better efficiency 1424 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1425 1426 Developer Note: 1427 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1428 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1429 1430 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1431 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1432 @*/ 1433 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1434 { 1435 PetscFunctionBeginHot; 1436 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1437 PetscValidType(mat, 1); 1438 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1439 PetscValidIntPointer(idxm, 3); 1440 PetscValidIntPointer(idxn, 5); 1441 MatCheckPreallocated(mat, 1); 1442 1443 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1444 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1445 1446 if (PetscDefined(USE_DEBUG)) { 1447 PetscInt i, j; 1448 1449 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1450 for (i = 0; i < m; i++) { 1451 for (j = 0; j < n; j++) { 1452 if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j])) 1453 #if defined(PETSC_USE_COMPLEX) 1454 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Inserting %g+i%g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")", (double)PetscRealPart(v[i * n + j]), (double)PetscImaginaryPart(v[i * n + j]), idxm[i], idxn[j]); 1455 #else 1456 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Inserting %g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")", (double)v[i * n + j], idxm[i], idxn[j]); 1457 #endif 1458 } 1459 } 1460 for (i = 0; i < m; i++) PetscCheck(idxm[i] < mat->rmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot insert in row %" PetscInt_FMT ", maximum is %" PetscInt_FMT, idxm[i], mat->rmap->N - 1); 1461 for (i = 0; i < n; i++) PetscCheck(idxn[i] < mat->cmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot insert in column %" PetscInt_FMT ", maximum is %" PetscInt_FMT, idxn[i], mat->cmap->N - 1); 1462 } 1463 1464 if (mat->assembled) { 1465 mat->was_assembled = PETSC_TRUE; 1466 mat->assembled = PETSC_FALSE; 1467 } 1468 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1469 PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv); 1470 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1471 PetscFunctionReturn(PETSC_SUCCESS); 1472 } 1473 1474 /*@C 1475 MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns 1476 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1477 MUST be called after all calls to `MatSetValues()` have been completed. 1478 1479 Not Collective 1480 1481 Input Parameters: 1482 + mat - the matrix 1483 . v - a logically two-dimensional array of values 1484 . ism - the rows to provide 1485 . isn - the columns to provide 1486 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1487 1488 Level: beginner 1489 1490 Notes: 1491 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1492 1493 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1494 options cannot be mixed without intervening calls to the assembly 1495 routines. 1496 1497 `MatSetValues()` uses 0-based row and column numbers in Fortran 1498 as well as in C. 1499 1500 Negative indices may be passed in `ism` and `isn`, these rows and columns are 1501 simply ignored. This allows easily inserting element stiffness matrices 1502 with homogeneous Dirchlet boundary conditions that you don't want represented 1503 in the matrix. 1504 1505 Efficiency Alert: 1506 The routine `MatSetValuesBlocked()` may offer much better efficiency 1507 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1508 1509 This is currently not optimized for any particular `ISType` 1510 1511 Developer Notes: 1512 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1513 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1514 1515 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1516 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()` 1517 @*/ 1518 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv) 1519 { 1520 PetscInt m, n; 1521 const PetscInt *rows, *cols; 1522 1523 PetscFunctionBeginHot; 1524 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1525 PetscCall(ISGetIndices(ism, &rows)); 1526 PetscCall(ISGetIndices(isn, &cols)); 1527 PetscCall(ISGetLocalSize(ism, &m)); 1528 PetscCall(ISGetLocalSize(isn, &n)); 1529 PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv)); 1530 PetscCall(ISRestoreIndices(ism, &rows)); 1531 PetscCall(ISRestoreIndices(isn, &cols)); 1532 PetscFunctionReturn(PETSC_SUCCESS); 1533 } 1534 1535 /*@ 1536 MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1537 values into a matrix 1538 1539 Not Collective 1540 1541 Input Parameters: 1542 + mat - the matrix 1543 . row - the (block) row to set 1544 - v - a logically two-dimensional array of values 1545 1546 Level: intermediate 1547 1548 Notes: 1549 The values, `v`, are column-oriented (for the block version) and sorted 1550 1551 All the nonzeros in the row must be provided 1552 1553 The matrix must have previously had its column indices set, likely by having been assembled. 1554 1555 The row must belong to this process 1556 1557 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1558 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()` 1559 @*/ 1560 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[]) 1561 { 1562 PetscInt globalrow; 1563 1564 PetscFunctionBegin; 1565 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1566 PetscValidType(mat, 1); 1567 PetscValidScalarPointer(v, 3); 1568 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow)); 1569 PetscCall(MatSetValuesRow(mat, globalrow, v)); 1570 PetscFunctionReturn(PETSC_SUCCESS); 1571 } 1572 1573 /*@ 1574 MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1575 values into a matrix 1576 1577 Not Collective 1578 1579 Input Parameters: 1580 + mat - the matrix 1581 . row - the (block) row to set 1582 - v - a logically two-dimensional (column major) array of values for block matrices with blocksize larger than one, otherwise a one dimensional array of values 1583 1584 Level: advanced 1585 1586 Notes: 1587 The values, `v`, are column-oriented for the block version. 1588 1589 All the nonzeros in the row must be provided 1590 1591 THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used. 1592 1593 The row must belong to this process 1594 1595 .seealso: [](chapter_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1596 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()` 1597 @*/ 1598 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[]) 1599 { 1600 PetscFunctionBeginHot; 1601 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1602 PetscValidType(mat, 1); 1603 MatCheckPreallocated(mat, 1); 1604 PetscValidScalarPointer(v, 3); 1605 PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values"); 1606 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1607 mat->insertmode = INSERT_VALUES; 1608 1609 if (mat->assembled) { 1610 mat->was_assembled = PETSC_TRUE; 1611 mat->assembled = PETSC_FALSE; 1612 } 1613 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1614 PetscUseTypeMethod(mat, setvaluesrow, row, v); 1615 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1616 PetscFunctionReturn(PETSC_SUCCESS); 1617 } 1618 1619 /*@ 1620 MatSetValuesStencil - Inserts or adds a block of values into a matrix. 1621 Using structured grid indexing 1622 1623 Not Collective 1624 1625 Input Parameters: 1626 + mat - the matrix 1627 . m - number of rows being entered 1628 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered 1629 . n - number of columns being entered 1630 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered 1631 . v - a logically two-dimensional array of values 1632 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values 1633 1634 Level: beginner 1635 1636 Notes: 1637 By default the values, `v`, are row-oriented. See `MatSetOption()` for other options. 1638 1639 Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1640 options cannot be mixed without intervening calls to the assembly 1641 routines. 1642 1643 The grid coordinates are across the entire grid, not just the local portion 1644 1645 `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran 1646 as well as in C. 1647 1648 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1649 1650 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1651 or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1652 1653 The columns and rows in the stencil passed in MUST be contained within the 1654 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1655 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1656 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1657 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1658 1659 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 1660 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 1661 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 1662 `DM_BOUNDARY_PERIODIC` boundary type. 1663 1664 For indices that don't mean anything for your case (like the k index when working in 2d) or the c index when you have 1665 a single value per point) you can skip filling those indices. 1666 1667 Inspired by the structured grid interface to the HYPRE package 1668 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1669 1670 Efficiency Alert: 1671 The routine `MatSetValuesBlockedStencil()` may offer much better efficiency 1672 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1673 1674 Fortran Note: 1675 `idxm` and `idxn` should be declared as 1676 $ MatStencil idxm(4,m),idxn(4,n) 1677 and the values inserted using 1678 .vb 1679 idxm(MatStencil_i,1) = i 1680 idxm(MatStencil_j,1) = j 1681 idxm(MatStencil_k,1) = k 1682 idxm(MatStencil_c,1) = c 1683 etc 1684 .ve 1685 1686 .seealso: [](chapter_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1687 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil` 1688 @*/ 1689 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1690 { 1691 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1692 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1693 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1694 1695 PetscFunctionBegin; 1696 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1697 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1698 PetscValidType(mat, 1); 1699 PetscValidPointer(idxm, 3); 1700 PetscValidPointer(idxn, 5); 1701 1702 if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 1703 jdxm = buf; 1704 jdxn = buf + m; 1705 } else { 1706 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1707 jdxm = bufm; 1708 jdxn = bufn; 1709 } 1710 for (i = 0; i < m; i++) { 1711 for (j = 0; j < 3 - sdim; j++) dxm++; 1712 tmp = *dxm++ - starts[0]; 1713 for (j = 0; j < dim - 1; j++) { 1714 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1715 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1716 } 1717 if (mat->stencil.noc) dxm++; 1718 jdxm[i] = tmp; 1719 } 1720 for (i = 0; i < n; i++) { 1721 for (j = 0; j < 3 - sdim; j++) dxn++; 1722 tmp = *dxn++ - starts[0]; 1723 for (j = 0; j < dim - 1; j++) { 1724 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1725 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1726 } 1727 if (mat->stencil.noc) dxn++; 1728 jdxn[i] = tmp; 1729 } 1730 PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv)); 1731 PetscCall(PetscFree2(bufm, bufn)); 1732 PetscFunctionReturn(PETSC_SUCCESS); 1733 } 1734 1735 /*@ 1736 MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix. 1737 Using structured grid indexing 1738 1739 Not Collective 1740 1741 Input Parameters: 1742 + mat - the matrix 1743 . m - number of rows being entered 1744 . idxm - grid coordinates for matrix rows being entered 1745 . n - number of columns being entered 1746 . idxn - grid coordinates for matrix columns being entered 1747 . v - a logically two-dimensional array of values 1748 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values 1749 1750 Level: beginner 1751 1752 Notes: 1753 By default the values, `v`, are row-oriented and unsorted. 1754 See `MatSetOption()` for other options. 1755 1756 Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1757 options cannot be mixed without intervening calls to the assembly 1758 routines. 1759 1760 The grid coordinates are across the entire grid, not just the local portion 1761 1762 `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran 1763 as well as in C. 1764 1765 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1766 1767 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1768 or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1769 1770 The columns and rows in the stencil passed in MUST be contained within the 1771 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1772 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1773 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1774 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1775 1776 Negative indices may be passed in idxm and idxn, these rows and columns are 1777 simply ignored. This allows easily inserting element stiffness matrices 1778 with homogeneous Dirchlet boundary conditions that you don't want represented 1779 in the matrix. 1780 1781 Inspired by the structured grid interface to the HYPRE package 1782 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1783 1784 Fortran Note: 1785 `idxm` and `idxn` should be declared as 1786 $ MatStencil idxm(4,m),idxn(4,n) 1787 and the values inserted using 1788 .vb 1789 idxm(MatStencil_i,1) = i 1790 idxm(MatStencil_j,1) = j 1791 idxm(MatStencil_k,1) = k 1792 etc 1793 .ve 1794 1795 .seealso: [](chapter_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1796 `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`, 1797 `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` 1798 @*/ 1799 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1800 { 1801 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1802 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1803 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1804 1805 PetscFunctionBegin; 1806 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1807 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1808 PetscValidType(mat, 1); 1809 PetscValidPointer(idxm, 3); 1810 PetscValidPointer(idxn, 5); 1811 PetscValidScalarPointer(v, 6); 1812 1813 if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 1814 jdxm = buf; 1815 jdxn = buf + m; 1816 } else { 1817 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1818 jdxm = bufm; 1819 jdxn = bufn; 1820 } 1821 for (i = 0; i < m; i++) { 1822 for (j = 0; j < 3 - sdim; j++) dxm++; 1823 tmp = *dxm++ - starts[0]; 1824 for (j = 0; j < sdim - 1; j++) { 1825 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1826 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1827 } 1828 dxm++; 1829 jdxm[i] = tmp; 1830 } 1831 for (i = 0; i < n; i++) { 1832 for (j = 0; j < 3 - sdim; j++) dxn++; 1833 tmp = *dxn++ - starts[0]; 1834 for (j = 0; j < sdim - 1; j++) { 1835 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1836 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1837 } 1838 dxn++; 1839 jdxn[i] = tmp; 1840 } 1841 PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv)); 1842 PetscCall(PetscFree2(bufm, bufn)); 1843 PetscFunctionReturn(PETSC_SUCCESS); 1844 } 1845 1846 /*@ 1847 MatSetStencil - Sets the grid information for setting values into a matrix via 1848 `MatSetValuesStencil()` 1849 1850 Not Collective 1851 1852 Input Parameters: 1853 + mat - the matrix 1854 . dim - dimension of the grid 1, 2, or 3 1855 . dims - number of grid points in x, y, and z direction, including ghost points on your processor 1856 . starts - starting point of ghost nodes on your processor in x, y, and z direction 1857 - dof - number of degrees of freedom per node 1858 1859 Level: beginner 1860 1861 Notes: 1862 Inspired by the structured grid interface to the HYPRE package 1863 (www.llnl.gov/CASC/hyper) 1864 1865 For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the 1866 user. 1867 1868 .seealso: [](chapter_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1869 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()` 1870 @*/ 1871 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof) 1872 { 1873 PetscFunctionBegin; 1874 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1875 PetscValidIntPointer(dims, 3); 1876 PetscValidIntPointer(starts, 4); 1877 1878 mat->stencil.dim = dim + (dof > 1); 1879 for (PetscInt i = 0; i < dim; i++) { 1880 mat->stencil.dims[i] = dims[dim - i - 1]; /* copy the values in backwards */ 1881 mat->stencil.starts[i] = starts[dim - i - 1]; 1882 } 1883 mat->stencil.dims[dim] = dof; 1884 mat->stencil.starts[dim] = 0; 1885 mat->stencil.noc = (PetscBool)(dof == 1); 1886 PetscFunctionReturn(PETSC_SUCCESS); 1887 } 1888 1889 /*@C 1890 MatSetValuesBlocked - Inserts or adds a block of values into a matrix. 1891 1892 Not Collective 1893 1894 Input Parameters: 1895 + mat - the matrix 1896 . v - a logically two-dimensional array of values 1897 . m - the number of block rows 1898 . idxm - the global block indices 1899 . n - the number of block columns 1900 . idxn - the global block indices 1901 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values 1902 1903 Level: intermediate 1904 1905 Notes: 1906 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call 1907 MatXXXXSetPreallocation() or `MatSetUp()` before using this routine. 1908 1909 The `m` and `n` count the NUMBER of blocks in the row direction and column direction, 1910 NOT the total number of rows/columns; for example, if the block size is 2 and 1911 you are passing in values for rows 2,3,4,5 then m would be 2 (not 4). 1912 The values in idxm would be 1 2; that is the first index for each block divided by 1913 the block size. 1914 1915 You must call `MatSetBlockSize()` when constructing this matrix (before 1916 preallocating it). 1917 1918 By default the values, `v`, are row-oriented, so the layout of 1919 `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options. 1920 1921 Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES` 1922 options cannot be mixed without intervening calls to the assembly 1923 routines. 1924 1925 `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran 1926 as well as in C. 1927 1928 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1929 simply ignored. This allows easily inserting element stiffness matrices 1930 with homogeneous Dirchlet boundary conditions that you don't want represented 1931 in the matrix. 1932 1933 Each time an entry is set within a sparse matrix via `MatSetValues()`, 1934 internal searching must be done to determine where to place the 1935 data in the matrix storage space. By instead inserting blocks of 1936 entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is 1937 reduced. 1938 1939 Example: 1940 .vb 1941 Suppose m=n=2 and block size(bs) = 2 The array is 1942 1943 1 2 | 3 4 1944 5 6 | 7 8 1945 - - - | - - - 1946 9 10 | 11 12 1947 13 14 | 15 16 1948 1949 v[] should be passed in like 1950 v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] 1951 1952 If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then 1953 v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16] 1954 .ve 1955 1956 .seealso: [](chapter_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()` 1957 @*/ 1958 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1959 { 1960 PetscFunctionBeginHot; 1961 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1962 PetscValidType(mat, 1); 1963 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1964 PetscValidIntPointer(idxm, 3); 1965 PetscValidIntPointer(idxn, 5); 1966 MatCheckPreallocated(mat, 1); 1967 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1968 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1969 if (PetscDefined(USE_DEBUG)) { 1970 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1971 PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 1972 } 1973 if (PetscDefined(USE_DEBUG)) { 1974 PetscInt rbs, cbs, M, N, i; 1975 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1976 PetscCall(MatGetSize(mat, &M, &N)); 1977 for (i = 0; i < m; i++) PetscCheck(idxm[i] * rbs < M, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row block index %" PetscInt_FMT " (index %" PetscInt_FMT ") greater than row length %" PetscInt_FMT, i, idxm[i], M); 1978 for (i = 0; i < n; i++) PetscCheck(idxn[i] * cbs < N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column block index %" PetscInt_FMT " (index %" PetscInt_FMT ") great than column length %" PetscInt_FMT, i, idxn[i], N); 1979 } 1980 if (mat->assembled) { 1981 mat->was_assembled = PETSC_TRUE; 1982 mat->assembled = PETSC_FALSE; 1983 } 1984 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1985 if (mat->ops->setvaluesblocked) { 1986 PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv); 1987 } else { 1988 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn; 1989 PetscInt i, j, bs, cbs; 1990 1991 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 1992 if (m * bs + n * cbs <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 1993 iidxm = buf; 1994 iidxn = buf + m * bs; 1995 } else { 1996 PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc)); 1997 iidxm = bufr; 1998 iidxn = bufc; 1999 } 2000 for (i = 0; i < m; i++) { 2001 for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j; 2002 } 2003 if (m != n || bs != cbs || idxm != idxn) { 2004 for (i = 0; i < n; i++) { 2005 for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j; 2006 } 2007 } else iidxn = iidxm; 2008 PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv)); 2009 PetscCall(PetscFree2(bufr, bufc)); 2010 } 2011 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2012 PetscFunctionReturn(PETSC_SUCCESS); 2013 } 2014 2015 /*@C 2016 MatGetValues - Gets a block of local values from a matrix. 2017 2018 Not Collective; can only return values that are owned by the give process 2019 2020 Input Parameters: 2021 + mat - the matrix 2022 . v - a logically two-dimensional array for storing the values 2023 . m - the number of rows 2024 . idxm - the global indices of the rows 2025 . n - the number of columns 2026 - idxn - the global indices of the columns 2027 2028 Level: advanced 2029 2030 Notes: 2031 The user must allocate space (m*n `PetscScalar`s) for the values, `v`. 2032 The values, `v`, are then returned in a row-oriented format, 2033 analogous to that used by default in `MatSetValues()`. 2034 2035 `MatGetValues()` uses 0-based row and column numbers in 2036 Fortran as well as in C. 2037 2038 `MatGetValues()` requires that the matrix has been assembled 2039 with `MatAssemblyBegin()`/`MatAssemblyEnd()`. Thus, calls to 2040 `MatSetValues()` and `MatGetValues()` CANNOT be made in succession 2041 without intermediate matrix assembly. 2042 2043 Negative row or column indices will be ignored and those locations in `v` will be 2044 left unchanged. 2045 2046 For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI rank. 2047 That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable 2048 from `MatGetOwnershipRange`(mat,&rstart,&rend). 2049 2050 .seealso: [](chapter_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()` 2051 @*/ 2052 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) 2053 { 2054 PetscFunctionBegin; 2055 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2056 PetscValidType(mat, 1); 2057 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); 2058 PetscValidIntPointer(idxm, 3); 2059 PetscValidIntPointer(idxn, 5); 2060 PetscValidScalarPointer(v, 6); 2061 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2062 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2063 MatCheckPreallocated(mat, 1); 2064 2065 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2066 PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v); 2067 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2068 PetscFunctionReturn(PETSC_SUCCESS); 2069 } 2070 2071 /*@C 2072 MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices 2073 defined previously by `MatSetLocalToGlobalMapping()` 2074 2075 Not Collective 2076 2077 Input Parameters: 2078 + mat - the matrix 2079 . nrow - number of rows 2080 . irow - the row local indices 2081 . ncol - number of columns 2082 - icol - the column local indices 2083 2084 Output Parameter: 2085 . y - a logically two-dimensional array of values 2086 2087 Level: advanced 2088 2089 Notes: 2090 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine. 2091 2092 This routine can only return values that are owned by the requesting MPI rank. That is, for standard matrix formats, rows that, in the global numbering, 2093 are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can 2094 determine if the resulting global row associated with the local row r is owned by the requesting MPI rank by applying the `ISLocalToGlobalMapping` set 2095 with `MatSetLocalToGlobalMapping()`. 2096 2097 Developer Note: 2098 This is labelled with C so does not automatically generate Fortran stubs and interfaces 2099 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2100 2101 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2102 `MatSetValuesLocal()`, `MatGetValues()` 2103 @*/ 2104 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[]) 2105 { 2106 PetscFunctionBeginHot; 2107 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2108 PetscValidType(mat, 1); 2109 MatCheckPreallocated(mat, 1); 2110 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */ 2111 PetscValidIntPointer(irow, 3); 2112 PetscValidIntPointer(icol, 5); 2113 if (PetscDefined(USE_DEBUG)) { 2114 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2115 PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2116 } 2117 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2118 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2119 if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y); 2120 else { 2121 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm; 2122 if ((nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2123 irowm = buf; 2124 icolm = buf + nrow; 2125 } else { 2126 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2127 irowm = bufr; 2128 icolm = bufc; 2129 } 2130 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping())."); 2131 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping())."); 2132 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm)); 2133 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm)); 2134 PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y)); 2135 PetscCall(PetscFree2(bufr, bufc)); 2136 } 2137 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2138 PetscFunctionReturn(PETSC_SUCCESS); 2139 } 2140 2141 /*@ 2142 MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and 2143 the same size. Currently, this can only be called once and creates the given matrix. 2144 2145 Not Collective 2146 2147 Input Parameters: 2148 + mat - the matrix 2149 . nb - the number of blocks 2150 . bs - the number of rows (and columns) in each block 2151 . rows - a concatenation of the rows for each block 2152 - v - a concatenation of logically two-dimensional arrays of values 2153 2154 Level: advanced 2155 2156 Note: 2157 `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values 2158 2159 In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix. 2160 2161 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 2162 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()` 2163 @*/ 2164 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[]) 2165 { 2166 PetscFunctionBegin; 2167 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2168 PetscValidType(mat, 1); 2169 PetscValidIntPointer(rows, 4); 2170 PetscValidScalarPointer(v, 5); 2171 PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2172 2173 PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0)); 2174 if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v); 2175 else { 2176 for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES)); 2177 } 2178 PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0)); 2179 PetscFunctionReturn(PETSC_SUCCESS); 2180 } 2181 2182 /*@ 2183 MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by 2184 the routine `MatSetValuesLocal()` to allow users to insert matrix entries 2185 using a local (per-processor) numbering. 2186 2187 Not Collective 2188 2189 Input Parameters: 2190 + x - the matrix 2191 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()` 2192 - cmapping - column mapping 2193 2194 Level: intermediate 2195 2196 Note: 2197 If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix 2198 2199 .seealso: [](chapter_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()` 2200 @*/ 2201 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping) 2202 { 2203 PetscFunctionBegin; 2204 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 2205 PetscValidType(x, 1); 2206 if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2); 2207 if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3); 2208 if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping); 2209 else { 2210 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping)); 2211 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping)); 2212 } 2213 PetscFunctionReturn(PETSC_SUCCESS); 2214 } 2215 2216 /*@ 2217 MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()` 2218 2219 Not Collective 2220 2221 Input Parameter: 2222 . A - the matrix 2223 2224 Output Parameters: 2225 + rmapping - row mapping 2226 - cmapping - column mapping 2227 2228 Level: advanced 2229 2230 .seealso: [](chapter_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()` 2231 @*/ 2232 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping) 2233 { 2234 PetscFunctionBegin; 2235 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2236 PetscValidType(A, 1); 2237 if (rmapping) { 2238 PetscValidPointer(rmapping, 2); 2239 *rmapping = A->rmap->mapping; 2240 } 2241 if (cmapping) { 2242 PetscValidPointer(cmapping, 3); 2243 *cmapping = A->cmap->mapping; 2244 } 2245 PetscFunctionReturn(PETSC_SUCCESS); 2246 } 2247 2248 /*@ 2249 MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix 2250 2251 Logically Collective 2252 2253 Input Parameters: 2254 + A - the matrix 2255 . rmap - row layout 2256 - cmap - column layout 2257 2258 Level: advanced 2259 2260 Note: 2261 The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called. 2262 2263 .seealso: [](chapter_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()` 2264 @*/ 2265 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap) 2266 { 2267 PetscFunctionBegin; 2268 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2269 PetscCall(PetscLayoutReference(rmap, &A->rmap)); 2270 PetscCall(PetscLayoutReference(cmap, &A->cmap)); 2271 PetscFunctionReturn(PETSC_SUCCESS); 2272 } 2273 2274 /*@ 2275 MatGetLayouts - Gets the `PetscLayout` objects for rows and columns 2276 2277 Not Collective 2278 2279 Input Parameter: 2280 . A - the matrix 2281 2282 Output Parameters: 2283 + rmap - row layout 2284 - cmap - column layout 2285 2286 Level: advanced 2287 2288 .seealso: [](chapter_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()` 2289 @*/ 2290 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap) 2291 { 2292 PetscFunctionBegin; 2293 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2294 PetscValidType(A, 1); 2295 if (rmap) { 2296 PetscValidPointer(rmap, 2); 2297 *rmap = A->rmap; 2298 } 2299 if (cmap) { 2300 PetscValidPointer(cmap, 3); 2301 *cmap = A->cmap; 2302 } 2303 PetscFunctionReturn(PETSC_SUCCESS); 2304 } 2305 2306 /*@C 2307 MatSetValuesLocal - Inserts or adds values into certain locations of a matrix, 2308 using a local numbering of the nodes. 2309 2310 Not Collective 2311 2312 Input Parameters: 2313 + mat - the matrix 2314 . nrow - number of rows 2315 . irow - the row local indices 2316 . ncol - number of columns 2317 . icol - the column local indices 2318 . y - a logically two-dimensional array of values 2319 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2320 2321 Level: intermediate 2322 2323 Notes: 2324 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 2325 `MatSetUp()` before using this routine 2326 2327 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine 2328 2329 Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2330 options cannot be mixed without intervening calls to the assembly 2331 routines. 2332 2333 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2334 MUST be called after all calls to `MatSetValuesLocal()` have been completed. 2335 2336 Developer Note: 2337 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2338 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2339 2340 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2341 `MatGetValuesLocal()` 2342 @*/ 2343 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2344 { 2345 PetscFunctionBeginHot; 2346 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2347 PetscValidType(mat, 1); 2348 MatCheckPreallocated(mat, 1); 2349 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2350 PetscValidIntPointer(irow, 3); 2351 PetscValidIntPointer(icol, 5); 2352 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2353 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2354 if (PetscDefined(USE_DEBUG)) { 2355 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2356 PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2357 } 2358 2359 if (mat->assembled) { 2360 mat->was_assembled = PETSC_TRUE; 2361 mat->assembled = PETSC_FALSE; 2362 } 2363 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2364 if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv); 2365 else { 2366 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2367 const PetscInt *irowm, *icolm; 2368 2369 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2370 bufr = buf; 2371 bufc = buf + nrow; 2372 irowm = bufr; 2373 icolm = bufc; 2374 } else { 2375 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2376 irowm = bufr; 2377 icolm = bufc; 2378 } 2379 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr)); 2380 else irowm = irow; 2381 if (mat->cmap->mapping) { 2382 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2383 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc)); 2384 } else icolm = irowm; 2385 } else icolm = icol; 2386 PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv)); 2387 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2388 } 2389 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2390 PetscFunctionReturn(PETSC_SUCCESS); 2391 } 2392 2393 /*@C 2394 MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix, 2395 using a local ordering of the nodes a block at a time. 2396 2397 Not Collective 2398 2399 Input Parameters: 2400 + x - the matrix 2401 . nrow - number of rows 2402 . irow - the row local indices 2403 . ncol - number of columns 2404 . icol - the column local indices 2405 . y - a logically two-dimensional array of values 2406 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2407 2408 Level: intermediate 2409 2410 Notes: 2411 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 2412 `MatSetUp()` before using this routine 2413 2414 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()` 2415 before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the 2416 2417 Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2418 options cannot be mixed without intervening calls to the assembly 2419 routines. 2420 2421 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2422 MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed. 2423 2424 Developer Note: 2425 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2426 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2427 2428 .seealso: [](chapter_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, 2429 `MatSetValuesLocal()`, `MatSetValuesBlocked()` 2430 @*/ 2431 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2432 { 2433 PetscFunctionBeginHot; 2434 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2435 PetscValidType(mat, 1); 2436 MatCheckPreallocated(mat, 1); 2437 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2438 PetscValidIntPointer(irow, 3); 2439 PetscValidIntPointer(icol, 5); 2440 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2441 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2442 if (PetscDefined(USE_DEBUG)) { 2443 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2444 PetscCheck(mat->ops->setvaluesblockedlocal || mat->ops->setvaluesblocked || mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2445 } 2446 2447 if (mat->assembled) { 2448 mat->was_assembled = PETSC_TRUE; 2449 mat->assembled = PETSC_FALSE; 2450 } 2451 if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */ 2452 PetscInt irbs, rbs; 2453 PetscCall(MatGetBlockSizes(mat, &rbs, NULL)); 2454 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs)); 2455 PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs); 2456 } 2457 if (PetscUnlikelyDebug(mat->cmap->mapping)) { 2458 PetscInt icbs, cbs; 2459 PetscCall(MatGetBlockSizes(mat, NULL, &cbs)); 2460 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs)); 2461 PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs); 2462 } 2463 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2464 if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv); 2465 else { 2466 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2467 const PetscInt *irowm, *icolm; 2468 2469 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2470 bufr = buf; 2471 bufc = buf + nrow; 2472 irowm = bufr; 2473 icolm = bufc; 2474 } else { 2475 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2476 irowm = bufr; 2477 icolm = bufc; 2478 } 2479 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr)); 2480 else irowm = irow; 2481 if (mat->cmap->mapping) { 2482 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2483 PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc)); 2484 } else icolm = irowm; 2485 } else icolm = icol; 2486 PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv)); 2487 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2488 } 2489 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2490 PetscFunctionReturn(PETSC_SUCCESS); 2491 } 2492 2493 /*@ 2494 MatMultDiagonalBlock - Computes the matrix-vector product, y = Dx. Where D is defined by the inode or block structure of the diagonal 2495 2496 Collective 2497 2498 Input Parameters: 2499 + mat - the matrix 2500 - x - the vector to be multiplied 2501 2502 Output Parameter: 2503 . y - the result 2504 2505 Level: developer 2506 2507 Note: 2508 The vectors `x` and `y` cannot be the same. I.e., one cannot 2509 call `MatMultDiagonalBlock`(A,y,y). 2510 2511 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2512 @*/ 2513 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y) 2514 { 2515 PetscFunctionBegin; 2516 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2517 PetscValidType(mat, 1); 2518 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2519 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2520 2521 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2522 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2523 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2524 MatCheckPreallocated(mat, 1); 2525 2526 PetscUseTypeMethod(mat, multdiagonalblock, x, y); 2527 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2528 PetscFunctionReturn(PETSC_SUCCESS); 2529 } 2530 2531 /*@ 2532 MatMult - Computes the matrix-vector product, y = Ax. 2533 2534 Neighbor-wise Collective 2535 2536 Input Parameters: 2537 + mat - the matrix 2538 - x - the vector to be multiplied 2539 2540 Output Parameter: 2541 . y - the result 2542 2543 Level: beginner 2544 2545 Note: 2546 The vectors `x` and `y` cannot be the same. I.e., one cannot 2547 call `MatMult`(A,y,y). 2548 2549 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2550 @*/ 2551 PetscErrorCode MatMult(Mat mat, Vec x, Vec y) 2552 { 2553 PetscFunctionBegin; 2554 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2555 PetscValidType(mat, 1); 2556 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2557 VecCheckAssembled(x); 2558 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2559 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2560 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2561 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2562 PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N); 2563 PetscCheck(mat->rmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, y->map->N); 2564 PetscCheck(mat->cmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, x->map->n); 2565 PetscCheck(mat->rmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, y->map->n); 2566 PetscCall(VecSetErrorIfLocked(y, 3)); 2567 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2568 MatCheckPreallocated(mat, 1); 2569 2570 PetscCall(VecLockReadPush(x)); 2571 PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0)); 2572 PetscUseTypeMethod(mat, mult, x, y); 2573 PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0)); 2574 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2575 PetscCall(VecLockReadPop(x)); 2576 PetscFunctionReturn(PETSC_SUCCESS); 2577 } 2578 2579 /*@ 2580 MatMultTranspose - Computes matrix transpose times a vector y = A^T * x. 2581 2582 Neighbor-wise Collective 2583 2584 Input Parameters: 2585 + mat - the matrix 2586 - x - the vector to be multiplied 2587 2588 Output Parameter: 2589 . y - the result 2590 2591 Level: beginner 2592 2593 Notes: 2594 The vectors `x` and `y` cannot be the same. I.e., one cannot 2595 call `MatMultTranspose`(A,y,y). 2596 2597 For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple, 2598 use `MatMultHermitianTranspose()` 2599 2600 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()` 2601 @*/ 2602 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y) 2603 { 2604 PetscErrorCode (*op)(Mat, Vec, Vec) = NULL; 2605 2606 PetscFunctionBegin; 2607 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2608 PetscValidType(mat, 1); 2609 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2610 VecCheckAssembled(x); 2611 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2612 2613 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2614 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2615 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2616 PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N); 2617 PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N); 2618 PetscCheck(mat->cmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, y->map->n); 2619 PetscCheck(mat->rmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, x->map->n); 2620 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2621 MatCheckPreallocated(mat, 1); 2622 2623 if (!mat->ops->multtranspose) { 2624 if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult; 2625 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s does not have a multiply transpose defined or is symmetric and does not have a multiply defined", ((PetscObject)mat)->type_name); 2626 } else op = mat->ops->multtranspose; 2627 PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0)); 2628 PetscCall(VecLockReadPush(x)); 2629 PetscCall((*op)(mat, x, y)); 2630 PetscCall(VecLockReadPop(x)); 2631 PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0)); 2632 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2633 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2634 PetscFunctionReturn(PETSC_SUCCESS); 2635 } 2636 2637 /*@ 2638 MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector. 2639 2640 Neighbor-wise Collective 2641 2642 Input Parameters: 2643 + mat - the matrix 2644 - x - the vector to be multilplied 2645 2646 Output Parameter: 2647 . y - the result 2648 2649 Level: beginner 2650 2651 Notes: 2652 The vectors `x` and `y` cannot be the same. I.e., one cannot 2653 call `MatMultHermitianTranspose`(A,y,y). 2654 2655 Also called the conjugate transpose, complex conjugate transpose, or adjoint. 2656 2657 For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical. 2658 2659 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()` 2660 @*/ 2661 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y) 2662 { 2663 PetscFunctionBegin; 2664 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2665 PetscValidType(mat, 1); 2666 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2667 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2668 2669 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2670 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2671 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2672 PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N); 2673 PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N); 2674 PetscCheck(mat->cmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, y->map->n); 2675 PetscCheck(mat->rmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, x->map->n); 2676 MatCheckPreallocated(mat, 1); 2677 2678 PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0)); 2679 #if defined(PETSC_USE_COMPLEX) 2680 if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) { 2681 PetscCall(VecLockReadPush(x)); 2682 if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y); 2683 else PetscUseTypeMethod(mat, mult, x, y); 2684 PetscCall(VecLockReadPop(x)); 2685 } else { 2686 Vec w; 2687 PetscCall(VecDuplicate(x, &w)); 2688 PetscCall(VecCopy(x, w)); 2689 PetscCall(VecConjugate(w)); 2690 PetscCall(MatMultTranspose(mat, w, y)); 2691 PetscCall(VecDestroy(&w)); 2692 PetscCall(VecConjugate(y)); 2693 } 2694 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2695 #else 2696 PetscCall(MatMultTranspose(mat, x, y)); 2697 #endif 2698 PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0)); 2699 PetscFunctionReturn(PETSC_SUCCESS); 2700 } 2701 2702 /*@ 2703 MatMultAdd - Computes v3 = v2 + A * v1. 2704 2705 Neighbor-wise Collective 2706 2707 Input Parameters: 2708 + mat - the matrix 2709 . v1 - the vector to be multiplied by `mat` 2710 - v2 - the vector to be added to the result 2711 2712 Output Parameter: 2713 . v3 - the result 2714 2715 Level: beginner 2716 2717 Note: 2718 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2719 call `MatMultAdd`(A,v1,v2,v1). 2720 2721 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()` 2722 @*/ 2723 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2724 { 2725 PetscFunctionBegin; 2726 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2727 PetscValidType(mat, 1); 2728 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2729 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2730 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2731 2732 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2733 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2734 PetscCheck(mat->cmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v1->map->N); 2735 /* PetscCheck(mat->rmap->N == v2->map->N,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v2->map->N); 2736 PetscCheck(mat->rmap->N == v3->map->N,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v3->map->N); */ 2737 PetscCheck(mat->rmap->n == v3->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, v3->map->n); 2738 PetscCheck(mat->rmap->n == v2->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, v2->map->n); 2739 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2740 MatCheckPreallocated(mat, 1); 2741 2742 PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3)); 2743 PetscCall(VecLockReadPush(v1)); 2744 PetscUseTypeMethod(mat, multadd, v1, v2, v3); 2745 PetscCall(VecLockReadPop(v1)); 2746 PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3)); 2747 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2748 PetscFunctionReturn(PETSC_SUCCESS); 2749 } 2750 2751 /*@ 2752 MatMultTransposeAdd - Computes v3 = v2 + A' * v1. 2753 2754 Neighbor-wise Collective 2755 2756 Input Parameters: 2757 + mat - the matrix 2758 . v1 - the vector to be multiplied by the transpose of the matrix 2759 - v2 - the vector to be added to the result 2760 2761 Output Parameter: 2762 . v3 - the result 2763 2764 Level: beginner 2765 2766 Note: 2767 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2768 call `MatMultTransposeAdd`(A,v1,v2,v1). 2769 2770 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2771 @*/ 2772 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2773 { 2774 PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd; 2775 2776 PetscFunctionBegin; 2777 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2778 PetscValidType(mat, 1); 2779 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2780 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2781 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2782 2783 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2784 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2785 PetscCheck(mat->rmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, v1->map->N); 2786 PetscCheck(mat->cmap->N == v2->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v2->map->N); 2787 PetscCheck(mat->cmap->N == v3->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v3->map->N); 2788 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2789 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2790 MatCheckPreallocated(mat, 1); 2791 2792 PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2793 PetscCall(VecLockReadPush(v1)); 2794 PetscCall((*op)(mat, v1, v2, v3)); 2795 PetscCall(VecLockReadPop(v1)); 2796 PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2797 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2798 PetscFunctionReturn(PETSC_SUCCESS); 2799 } 2800 2801 /*@ 2802 MatMultHermitianTransposeAdd - Computes v3 = v2 + A^H * v1. 2803 2804 Neighbor-wise Collective 2805 2806 Input Parameters: 2807 + mat - the matrix 2808 . v1 - the vector to be multiplied by the Hermitian transpose 2809 - v2 - the vector to be added to the result 2810 2811 Output Parameter: 2812 . v3 - the result 2813 2814 Level: beginner 2815 2816 Note: 2817 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2818 call `MatMultHermitianTransposeAdd`(A,v1,v2,v1). 2819 2820 .seealso: [](chapter_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2821 @*/ 2822 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2823 { 2824 PetscFunctionBegin; 2825 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2826 PetscValidType(mat, 1); 2827 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2828 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2829 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2830 2831 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2832 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2833 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2834 PetscCheck(mat->rmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, v1->map->N); 2835 PetscCheck(mat->cmap->N == v2->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v2->map->N); 2836 PetscCheck(mat->cmap->N == v3->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v3->map->N); 2837 MatCheckPreallocated(mat, 1); 2838 2839 PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2840 PetscCall(VecLockReadPush(v1)); 2841 if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3); 2842 else { 2843 Vec w, z; 2844 PetscCall(VecDuplicate(v1, &w)); 2845 PetscCall(VecCopy(v1, w)); 2846 PetscCall(VecConjugate(w)); 2847 PetscCall(VecDuplicate(v3, &z)); 2848 PetscCall(MatMultTranspose(mat, w, z)); 2849 PetscCall(VecDestroy(&w)); 2850 PetscCall(VecConjugate(z)); 2851 if (v2 != v3) { 2852 PetscCall(VecWAXPY(v3, 1.0, v2, z)); 2853 } else { 2854 PetscCall(VecAXPY(v3, 1.0, z)); 2855 } 2856 PetscCall(VecDestroy(&z)); 2857 } 2858 PetscCall(VecLockReadPop(v1)); 2859 PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2860 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2861 PetscFunctionReturn(PETSC_SUCCESS); 2862 } 2863 2864 /*@C 2865 MatGetFactorType - gets the type of factorization it is 2866 2867 Not Collective 2868 2869 Input Parameter: 2870 . mat - the matrix 2871 2872 Output Parameter: 2873 . t - the type, one of `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2874 2875 Level: intermediate 2876 2877 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2878 `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2879 @*/ 2880 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t) 2881 { 2882 PetscFunctionBegin; 2883 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2884 PetscValidType(mat, 1); 2885 PetscValidPointer(t, 2); 2886 *t = mat->factortype; 2887 PetscFunctionReturn(PETSC_SUCCESS); 2888 } 2889 2890 /*@C 2891 MatSetFactorType - sets the type of factorization it is 2892 2893 Logically Collective 2894 2895 Input Parameters: 2896 + mat - the matrix 2897 - t - the type, one of `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2898 2899 Level: intermediate 2900 2901 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2902 `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2903 @*/ 2904 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t) 2905 { 2906 PetscFunctionBegin; 2907 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2908 PetscValidType(mat, 1); 2909 mat->factortype = t; 2910 PetscFunctionReturn(PETSC_SUCCESS); 2911 } 2912 2913 /*@C 2914 MatGetInfo - Returns information about matrix storage (number of 2915 nonzeros, memory, etc.). 2916 2917 Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag 2918 2919 Input Parameters: 2920 + mat - the matrix 2921 - flag - flag indicating the type of parameters to be returned (`MAT_LOCAL` - local matrix, `MAT_GLOBAL_MAX` - maximum over all processors, `MAT_GLOBAL_SUM` - sum over all processors) 2922 2923 Output Parameter: 2924 . info - matrix information context 2925 2926 Options Database Key: 2927 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT` 2928 2929 Notes: 2930 The `MatInfo` context contains a variety of matrix data, including 2931 number of nonzeros allocated and used, number of mallocs during 2932 matrix assembly, etc. Additional information for factored matrices 2933 is provided (such as the fill ratio, number of mallocs during 2934 factorization, etc.). 2935 2936 Example: 2937 See the file ${PETSC_DIR}/include/petscmat.h for a complete list of 2938 data within the MatInfo context. For example, 2939 .vb 2940 MatInfo info; 2941 Mat A; 2942 double mal, nz_a, nz_u; 2943 2944 MatGetInfo(A, MAT_LOCAL, &info); 2945 mal = info.mallocs; 2946 nz_a = info.nz_allocated; 2947 .ve 2948 2949 Fortran users should declare info as a double precision 2950 array of dimension `MAT_INFO_SIZE`, and then extract the parameters 2951 of interest. See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h 2952 a complete list of parameter names. 2953 .vb 2954 double precision info(MAT_INFO_SIZE) 2955 double precision mal, nz_a 2956 Mat A 2957 integer ierr 2958 2959 call MatGetInfo(A, MAT_LOCAL, info, ierr) 2960 mal = info(MAT_INFO_MALLOCS) 2961 nz_a = info(MAT_INFO_NZ_ALLOCATED) 2962 .ve 2963 2964 Level: intermediate 2965 2966 Developer Note: 2967 The Fortran interface is not autogenerated as the 2968 interface definition cannot be generated correctly [due to `MatInfo` argument] 2969 2970 .seealso: [](chapter_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()` 2971 @*/ 2972 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info) 2973 { 2974 PetscFunctionBegin; 2975 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2976 PetscValidType(mat, 1); 2977 PetscValidPointer(info, 3); 2978 MatCheckPreallocated(mat, 1); 2979 PetscUseTypeMethod(mat, getinfo, flag, info); 2980 PetscFunctionReturn(PETSC_SUCCESS); 2981 } 2982 2983 /* 2984 This is used by external packages where it is not easy to get the info from the actual 2985 matrix factorization. 2986 */ 2987 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info) 2988 { 2989 PetscFunctionBegin; 2990 PetscCall(PetscMemzero(info, sizeof(MatInfo))); 2991 PetscFunctionReturn(PETSC_SUCCESS); 2992 } 2993 2994 /*@C 2995 MatLUFactor - Performs in-place LU factorization of matrix. 2996 2997 Collective 2998 2999 Input Parameters: 3000 + mat - the matrix 3001 . row - row permutation 3002 . col - column permutation 3003 - info - options for factorization, includes 3004 .vb 3005 fill - expected fill as ratio of original fill. 3006 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3007 Run with the option -info to determine an optimal value to use 3008 .ve 3009 Level: developer 3010 3011 Notes: 3012 Most users should employ the `KSP` interface for linear solvers 3013 instead of working directly with matrix algebra routines such as this. 3014 See, e.g., `KSPCreate()`. 3015 3016 This changes the state of the matrix to a factored matrix; it cannot be used 3017 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3018 3019 This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()` 3020 when not using `KSP`. 3021 3022 Developer Note: 3023 The Fortran interface is not autogenerated as the 3024 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3025 3026 .seealso: [](chapter_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, 3027 `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3028 @*/ 3029 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3030 { 3031 MatFactorInfo tinfo; 3032 3033 PetscFunctionBegin; 3034 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3035 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3036 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3037 if (info) PetscValidPointer(info, 4); 3038 PetscValidType(mat, 1); 3039 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3040 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3041 MatCheckPreallocated(mat, 1); 3042 if (!info) { 3043 PetscCall(MatFactorInfoInitialize(&tinfo)); 3044 info = &tinfo; 3045 } 3046 3047 PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0)); 3048 PetscUseTypeMethod(mat, lufactor, row, col, info); 3049 PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0)); 3050 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3051 PetscFunctionReturn(PETSC_SUCCESS); 3052 } 3053 3054 /*@C 3055 MatILUFactor - Performs in-place ILU factorization of matrix. 3056 3057 Collective 3058 3059 Input Parameters: 3060 + mat - the matrix 3061 . row - row permutation 3062 . col - column permutation 3063 - info - structure containing 3064 .vb 3065 levels - number of levels of fill. 3066 expected fill - as ratio of original fill. 3067 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 3068 missing diagonal entries) 3069 .ve 3070 3071 Level: developer 3072 3073 Notes: 3074 Most users should employ the `KSP` interface for linear solvers 3075 instead of working directly with matrix algebra routines such as this. 3076 See, e.g., `KSPCreate()`. 3077 3078 Probably really in-place only when level of fill is zero, otherwise allocates 3079 new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()` 3080 when not using `KSP`. 3081 3082 Developer Note: 3083 The Fortran interface is not autogenerated as the 3084 interface definition cannot be generated correctly [due to MatFactorInfo] 3085 3086 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 3087 @*/ 3088 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3089 { 3090 PetscFunctionBegin; 3091 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3092 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3093 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3094 PetscValidPointer(info, 4); 3095 PetscValidType(mat, 1); 3096 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 3097 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3098 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3099 MatCheckPreallocated(mat, 1); 3100 3101 PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0)); 3102 PetscUseTypeMethod(mat, ilufactor, row, col, info); 3103 PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0)); 3104 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3105 PetscFunctionReturn(PETSC_SUCCESS); 3106 } 3107 3108 /*@C 3109 MatLUFactorSymbolic - Performs symbolic LU factorization of matrix. 3110 Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`. 3111 3112 Collective 3113 3114 Input Parameters: 3115 + fact - the factor matrix obtained with `MatGetFactor()` 3116 . mat - the matrix 3117 . row - the row permutation 3118 . col - the column permutation 3119 - info - options for factorization, includes 3120 .vb 3121 fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use 3122 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3123 .ve 3124 3125 Level: developer 3126 3127 Notes: 3128 See [Matrix Factorization](sec_matfactor) for additional information about factorizations 3129 3130 Most users should employ the simplified `KSP` interface for linear solvers 3131 instead of working directly with matrix algebra routines such as this. 3132 See, e.g., `KSPCreate()`. 3133 3134 Developer Note: 3135 The Fortran interface is not autogenerated as the 3136 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3137 3138 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3139 @*/ 3140 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 3141 { 3142 MatFactorInfo tinfo; 3143 3144 PetscFunctionBegin; 3145 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3146 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3147 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 3148 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 3149 if (info) PetscValidPointer(info, 5); 3150 PetscValidType(fact, 1); 3151 PetscValidType(mat, 2); 3152 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3153 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3154 MatCheckPreallocated(mat, 2); 3155 if (!info) { 3156 PetscCall(MatFactorInfoInitialize(&tinfo)); 3157 info = &tinfo; 3158 } 3159 3160 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0)); 3161 PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info); 3162 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0)); 3163 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3164 PetscFunctionReturn(PETSC_SUCCESS); 3165 } 3166 3167 /*@C 3168 MatLUFactorNumeric - Performs numeric LU factorization of a matrix. 3169 Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`. 3170 3171 Collective 3172 3173 Input Parameters: 3174 + fact - the factor matrix obtained with `MatGetFactor()` 3175 . mat - the matrix 3176 - info - options for factorization 3177 3178 Level: developer 3179 3180 Notes: 3181 See `MatLUFactor()` for in-place factorization. See 3182 `MatCholeskyFactorNumeric()` for the symmetric, positive definite case. 3183 3184 Most users should employ the `KSP` interface for linear solvers 3185 instead of working directly with matrix algebra routines such as this. 3186 See, e.g., `KSPCreate()`. 3187 3188 Developer Note: 3189 The Fortran interface is not autogenerated as the 3190 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3191 3192 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()` 3193 @*/ 3194 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3195 { 3196 MatFactorInfo tinfo; 3197 3198 PetscFunctionBegin; 3199 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3200 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3201 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3202 PetscValidType(fact, 1); 3203 PetscValidType(mat, 2); 3204 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3205 PetscCheck(mat->rmap->N == (fact)->rmap->N && mat->cmap->N == (fact)->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Mat fact: global dimensions are different %" PetscInt_FMT " should = %" PetscInt_FMT " %" PetscInt_FMT " should = %" PetscInt_FMT, 3206 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3207 3208 MatCheckPreallocated(mat, 2); 3209 if (!info) { 3210 PetscCall(MatFactorInfoInitialize(&tinfo)); 3211 info = &tinfo; 3212 } 3213 3214 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3215 else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0)); 3216 PetscUseTypeMethod(fact, lufactornumeric, mat, info); 3217 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3218 else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0)); 3219 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3220 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3221 PetscFunctionReturn(PETSC_SUCCESS); 3222 } 3223 3224 /*@C 3225 MatCholeskyFactor - Performs in-place Cholesky factorization of a 3226 symmetric matrix. 3227 3228 Collective 3229 3230 Input Parameters: 3231 + mat - the matrix 3232 . perm - row and column permutations 3233 - f - expected fill as ratio of original fill 3234 3235 Level: developer 3236 3237 Notes: 3238 See `MatLUFactor()` for the nonsymmetric case. See also `MatGetFactor()`, 3239 `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`. 3240 3241 Most users should employ the `KSP` interface for linear solvers 3242 instead of working directly with matrix algebra routines such as this. 3243 See, e.g., `KSPCreate()`. 3244 3245 Developer Note: 3246 The Fortran interface is not autogenerated as the 3247 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3248 3249 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()` 3250 `MatGetOrdering()` 3251 @*/ 3252 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info) 3253 { 3254 MatFactorInfo tinfo; 3255 3256 PetscFunctionBegin; 3257 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3258 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2); 3259 if (info) PetscValidPointer(info, 3); 3260 PetscValidType(mat, 1); 3261 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3262 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3263 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3264 MatCheckPreallocated(mat, 1); 3265 if (!info) { 3266 PetscCall(MatFactorInfoInitialize(&tinfo)); 3267 info = &tinfo; 3268 } 3269 3270 PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0)); 3271 PetscUseTypeMethod(mat, choleskyfactor, perm, info); 3272 PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0)); 3273 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3274 PetscFunctionReturn(PETSC_SUCCESS); 3275 } 3276 3277 /*@C 3278 MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization 3279 of a symmetric matrix. 3280 3281 Collective 3282 3283 Input Parameters: 3284 + fact - the factor matrix obtained with `MatGetFactor()` 3285 . mat - the matrix 3286 . perm - row and column permutations 3287 - info - options for factorization, includes 3288 .vb 3289 fill - expected fill as ratio of original fill. 3290 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3291 Run with the option -info to determine an optimal value to use 3292 .ve 3293 3294 Level: developer 3295 3296 Notes: 3297 See `MatLUFactorSymbolic()` for the nonsymmetric case. See also 3298 `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`. 3299 3300 Most users should employ the `KSP` interface for linear solvers 3301 instead of working directly with matrix algebra routines such as this. 3302 See, e.g., `KSPCreate()`. 3303 3304 Developer Note: 3305 The Fortran interface is not autogenerated as the 3306 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3307 3308 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()` 3309 `MatGetOrdering()` 3310 @*/ 3311 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 3312 { 3313 MatFactorInfo tinfo; 3314 3315 PetscFunctionBegin; 3316 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3317 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3318 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 3319 if (info) PetscValidPointer(info, 4); 3320 PetscValidType(fact, 1); 3321 PetscValidType(mat, 2); 3322 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3323 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3324 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3325 MatCheckPreallocated(mat, 2); 3326 if (!info) { 3327 PetscCall(MatFactorInfoInitialize(&tinfo)); 3328 info = &tinfo; 3329 } 3330 3331 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3332 PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info); 3333 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3334 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3335 PetscFunctionReturn(PETSC_SUCCESS); 3336 } 3337 3338 /*@C 3339 MatCholeskyFactorNumeric - Performs numeric Cholesky factorization 3340 of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and 3341 `MatCholeskyFactorSymbolic()`. 3342 3343 Collective 3344 3345 Input Parameters: 3346 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored 3347 . mat - the initial matrix that is to be factored 3348 - info - options for factorization 3349 3350 Level: developer 3351 3352 Note: 3353 Most users should employ the `KSP` interface for linear solvers 3354 instead of working directly with matrix algebra routines such as this. 3355 See, e.g., `KSPCreate()`. 3356 3357 Developer Note: 3358 The Fortran interface is not autogenerated as the 3359 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3360 3361 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()` 3362 @*/ 3363 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3364 { 3365 MatFactorInfo tinfo; 3366 3367 PetscFunctionBegin; 3368 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3369 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3370 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3371 PetscValidType(fact, 1); 3372 PetscValidType(mat, 2); 3373 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3374 PetscCheck(mat->rmap->N == (fact)->rmap->N && mat->cmap->N == (fact)->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Mat fact: global dim %" PetscInt_FMT " should = %" PetscInt_FMT " %" PetscInt_FMT " should = %" PetscInt_FMT, 3375 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3376 MatCheckPreallocated(mat, 2); 3377 if (!info) { 3378 PetscCall(MatFactorInfoInitialize(&tinfo)); 3379 info = &tinfo; 3380 } 3381 3382 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3383 else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0)); 3384 PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info); 3385 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3386 else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0)); 3387 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3388 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3389 PetscFunctionReturn(PETSC_SUCCESS); 3390 } 3391 3392 /*@ 3393 MatQRFactor - Performs in-place QR factorization of matrix. 3394 3395 Collective 3396 3397 Input Parameters: 3398 + mat - the matrix 3399 . col - column permutation 3400 - info - options for factorization, includes 3401 .vb 3402 fill - expected fill as ratio of original fill. 3403 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3404 Run with the option -info to determine an optimal value to use 3405 .ve 3406 3407 Level: developer 3408 3409 Notes: 3410 Most users should employ the `KSP` interface for linear solvers 3411 instead of working directly with matrix algebra routines such as this. 3412 See, e.g., `KSPCreate()`. 3413 3414 This changes the state of the matrix to a factored matrix; it cannot be used 3415 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3416 3417 Developer Note: 3418 The Fortran interface is not autogenerated as the 3419 interface definition cannot be generated correctly [due to MatFactorInfo] 3420 3421 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`, 3422 `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3423 @*/ 3424 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info) 3425 { 3426 PetscFunctionBegin; 3427 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3428 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2); 3429 if (info) PetscValidPointer(info, 3); 3430 PetscValidType(mat, 1); 3431 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3432 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3433 MatCheckPreallocated(mat, 1); 3434 PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0)); 3435 PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info)); 3436 PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0)); 3437 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3438 PetscFunctionReturn(PETSC_SUCCESS); 3439 } 3440 3441 /*@ 3442 MatQRFactorSymbolic - Performs symbolic QR factorization of matrix. 3443 Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`. 3444 3445 Collective 3446 3447 Input Parameters: 3448 + fact - the factor matrix obtained with `MatGetFactor()` 3449 . mat - the matrix 3450 . col - column permutation 3451 - info - options for factorization, includes 3452 .vb 3453 fill - expected fill as ratio of original fill. 3454 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3455 Run with the option -info to determine an optimal value to use 3456 .ve 3457 3458 Level: developer 3459 3460 Note: 3461 Most users should employ the `KSP` interface for linear solvers 3462 instead of working directly with matrix algebra routines such as this. 3463 See, e.g., `KSPCreate()`. 3464 3465 Developer Note: 3466 The Fortran interface is not autogenerated as the 3467 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3468 3469 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3470 @*/ 3471 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info) 3472 { 3473 MatFactorInfo tinfo; 3474 3475 PetscFunctionBegin; 3476 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3477 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3478 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3479 if (info) PetscValidPointer(info, 4); 3480 PetscValidType(fact, 1); 3481 PetscValidType(mat, 2); 3482 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3483 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3484 MatCheckPreallocated(mat, 2); 3485 if (!info) { 3486 PetscCall(MatFactorInfoInitialize(&tinfo)); 3487 info = &tinfo; 3488 } 3489 3490 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3491 PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info)); 3492 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3493 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3494 PetscFunctionReturn(PETSC_SUCCESS); 3495 } 3496 3497 /*@ 3498 MatQRFactorNumeric - Performs numeric QR factorization of a matrix. 3499 Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`. 3500 3501 Collective 3502 3503 Input Parameters: 3504 + fact - the factor matrix obtained with `MatGetFactor()` 3505 . mat - the matrix 3506 - info - options for factorization 3507 3508 Level: developer 3509 3510 Notes: 3511 See `MatQRFactor()` for in-place factorization. 3512 3513 Most users should employ the `KSP` interface for linear solvers 3514 instead of working directly with matrix algebra routines such as this. 3515 See, e.g., `KSPCreate()`. 3516 3517 Developer Note: 3518 The Fortran interface is not autogenerated as the 3519 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3520 3521 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()` 3522 @*/ 3523 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3524 { 3525 MatFactorInfo tinfo; 3526 3527 PetscFunctionBegin; 3528 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3529 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3530 PetscValidType(fact, 1); 3531 PetscValidType(mat, 2); 3532 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3533 PetscCheck(mat->rmap->N == fact->rmap->N && mat->cmap->N == fact->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Mat fact: global dimensions are different %" PetscInt_FMT " should = %" PetscInt_FMT " %" PetscInt_FMT " should = %" PetscInt_FMT, 3534 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3535 3536 MatCheckPreallocated(mat, 2); 3537 if (!info) { 3538 PetscCall(MatFactorInfoInitialize(&tinfo)); 3539 info = &tinfo; 3540 } 3541 3542 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3543 else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0)); 3544 PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info)); 3545 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3546 else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0)); 3547 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3548 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3549 PetscFunctionReturn(PETSC_SUCCESS); 3550 } 3551 3552 /*@ 3553 MatSolve - Solves A x = b, given a factored matrix. 3554 3555 Neighbor-wise Collective 3556 3557 Input Parameters: 3558 + mat - the factored matrix 3559 - b - the right-hand-side vector 3560 3561 Output Parameter: 3562 . x - the result vector 3563 3564 Level: developer 3565 3566 Notes: 3567 The vectors `b` and `x` cannot be the same. I.e., one cannot 3568 call `MatSolve`(A,x,x). 3569 3570 Most users should employ the `KSP` interface for linear solvers 3571 instead of working directly with matrix algebra routines such as this. 3572 See, e.g., `KSPCreate()`. 3573 3574 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3575 @*/ 3576 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x) 3577 { 3578 PetscFunctionBegin; 3579 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3580 PetscValidType(mat, 1); 3581 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3582 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3583 PetscCheckSameComm(mat, 1, b, 2); 3584 PetscCheckSameComm(mat, 1, x, 3); 3585 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3586 PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N); 3587 PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N); 3588 PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n); 3589 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3590 MatCheckPreallocated(mat, 1); 3591 3592 PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0)); 3593 if (mat->factorerrortype) { 3594 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3595 PetscCall(VecSetInf(x)); 3596 } else PetscUseTypeMethod(mat, solve, b, x); 3597 PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0)); 3598 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3599 PetscFunctionReturn(PETSC_SUCCESS); 3600 } 3601 3602 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans) 3603 { 3604 Vec b, x; 3605 PetscInt N, i; 3606 PetscErrorCode (*f)(Mat, Vec, Vec); 3607 PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE; 3608 3609 PetscFunctionBegin; 3610 if (A->factorerrortype) { 3611 PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype)); 3612 PetscCall(MatSetInf(X)); 3613 PetscFunctionReturn(PETSC_SUCCESS); 3614 } 3615 f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose; 3616 PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 3617 PetscCall(MatBoundToCPU(A, &Abound)); 3618 if (!Abound) { 3619 PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3620 PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3621 } 3622 #if PetscDefined(HAVE_CUDA) 3623 if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B)); 3624 if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X)); 3625 #elif PetscDefined(HAVE_HIP) 3626 if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B)); 3627 if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X)); 3628 #endif 3629 PetscCall(MatGetSize(B, NULL, &N)); 3630 for (i = 0; i < N; i++) { 3631 PetscCall(MatDenseGetColumnVecRead(B, i, &b)); 3632 PetscCall(MatDenseGetColumnVecWrite(X, i, &x)); 3633 PetscCall((*f)(A, b, x)); 3634 PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x)); 3635 PetscCall(MatDenseRestoreColumnVecRead(B, i, &b)); 3636 } 3637 if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B)); 3638 if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X)); 3639 PetscFunctionReturn(PETSC_SUCCESS); 3640 } 3641 3642 /*@ 3643 MatMatSolve - Solves A X = B, given a factored matrix. 3644 3645 Neighbor-wise Collective 3646 3647 Input Parameters: 3648 + A - the factored matrix 3649 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS) 3650 3651 Output Parameter: 3652 . X - the result matrix (dense matrix) 3653 3654 Level: developer 3655 3656 Note: 3657 If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`; 3658 otherwise, `B` and `X` cannot be the same. 3659 3660 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3661 @*/ 3662 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X) 3663 { 3664 PetscFunctionBegin; 3665 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3666 PetscValidType(A, 1); 3667 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3668 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3669 PetscCheckSameComm(A, 1, B, 2); 3670 PetscCheckSameComm(A, 1, X, 3); 3671 PetscCheck(A->cmap->N == X->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat X: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->cmap->N, X->rmap->N); 3672 PetscCheck(A->rmap->N == B->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat B: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->N, B->rmap->N); 3673 PetscCheck(X->cmap->N == B->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Solution matrix must have same number of columns as rhs matrix"); 3674 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3675 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3676 MatCheckPreallocated(A, 1); 3677 3678 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3679 if (!A->ops->matsolve) { 3680 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name)); 3681 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE)); 3682 } else PetscUseTypeMethod(A, matsolve, B, X); 3683 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3684 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3685 PetscFunctionReturn(PETSC_SUCCESS); 3686 } 3687 3688 /*@ 3689 MatMatSolveTranspose - Solves A^T X = B, given a factored matrix. 3690 3691 Neighbor-wise Collective 3692 3693 Input Parameters: 3694 + A - the factored matrix 3695 - B - the right-hand-side matrix (`MATDENSE` matrix) 3696 3697 Output Parameter: 3698 . X - the result matrix (dense matrix) 3699 3700 Level: developer 3701 3702 Note: 3703 The matrices `B` and `X` cannot be the same. I.e., one cannot 3704 call `MatMatSolveTranspose`(A,X,X). 3705 3706 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()` 3707 @*/ 3708 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X) 3709 { 3710 PetscFunctionBegin; 3711 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3712 PetscValidType(A, 1); 3713 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3714 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3715 PetscCheckSameComm(A, 1, B, 2); 3716 PetscCheckSameComm(A, 1, X, 3); 3717 PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3718 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); 3719 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); 3720 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); 3721 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"); 3722 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3723 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3724 MatCheckPreallocated(A, 1); 3725 3726 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3727 if (!A->ops->matsolvetranspose) { 3728 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name)); 3729 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE)); 3730 } else PetscUseTypeMethod(A, matsolvetranspose, B, X); 3731 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3732 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3733 PetscFunctionReturn(PETSC_SUCCESS); 3734 } 3735 3736 /*@ 3737 MatMatTransposeSolve - Solves A X = B^T, given a factored matrix. 3738 3739 Neighbor-wise Collective 3740 3741 Input Parameters: 3742 + A - the factored matrix 3743 - Bt - the transpose of right-hand-side matrix as a `MATDENSE` 3744 3745 Output Parameter: 3746 . X - the result matrix (dense matrix) 3747 3748 Level: developer 3749 3750 Note: 3751 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 3752 format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`. 3753 3754 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3755 @*/ 3756 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X) 3757 { 3758 PetscFunctionBegin; 3759 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3760 PetscValidType(A, 1); 3761 PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2); 3762 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3763 PetscCheckSameComm(A, 1, Bt, 2); 3764 PetscCheckSameComm(A, 1, X, 3); 3765 3766 PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3767 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); 3768 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); 3769 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"); 3770 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3771 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3772 MatCheckPreallocated(A, 1); 3773 3774 PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0)); 3775 PetscUseTypeMethod(A, mattransposesolve, Bt, X); 3776 PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0)); 3777 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3778 PetscFunctionReturn(PETSC_SUCCESS); 3779 } 3780 3781 /*@ 3782 MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or 3783 U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U, 3784 3785 Neighbor-wise Collective 3786 3787 Input Parameters: 3788 + mat - the factored matrix 3789 - b - the right-hand-side vector 3790 3791 Output Parameter: 3792 . x - the result vector 3793 3794 Level: developer 3795 3796 Notes: 3797 `MatSolve()` should be used for most applications, as it performs 3798 a forward solve followed by a backward solve. 3799 3800 The vectors `b` and `x` cannot be the same, i.e., one cannot 3801 call `MatForwardSolve`(A,x,x). 3802 3803 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3804 the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet. 3805 `MatForwardSolve()` solves U^T*D y = b, and 3806 `MatBackwardSolve()` solves U x = y. 3807 Thus they do not provide a symmetric preconditioner. 3808 3809 .seealso: [](chapter_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatBackwardSolve()` 3810 @*/ 3811 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x) 3812 { 3813 PetscFunctionBegin; 3814 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3815 PetscValidType(mat, 1); 3816 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3817 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3818 PetscCheckSameComm(mat, 1, b, 2); 3819 PetscCheckSameComm(mat, 1, x, 3); 3820 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3821 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); 3822 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); 3823 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); 3824 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3825 MatCheckPreallocated(mat, 1); 3826 3827 PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0)); 3828 PetscUseTypeMethod(mat, forwardsolve, b, x); 3829 PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0)); 3830 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3831 PetscFunctionReturn(PETSC_SUCCESS); 3832 } 3833 3834 /*@ 3835 MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU. 3836 D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U, 3837 3838 Neighbor-wise Collective 3839 3840 Input Parameters: 3841 + mat - the factored matrix 3842 - b - the right-hand-side vector 3843 3844 Output Parameter: 3845 . x - the result vector 3846 3847 Level: developer 3848 3849 Notes: 3850 `MatSolve()` should be used for most applications, as it performs 3851 a forward solve followed by a backward solve. 3852 3853 The vectors `b` and `x` cannot be the same. I.e., one cannot 3854 call `MatBackwardSolve`(A,x,x). 3855 3856 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3857 the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet. 3858 `MatForwardSolve()` solves U^T*D y = b, and 3859 `MatBackwardSolve()` solves U x = y. 3860 Thus they do not provide a symmetric preconditioner. 3861 3862 .seealso: [](chapter_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatForwardSolve()` 3863 @*/ 3864 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x) 3865 { 3866 PetscFunctionBegin; 3867 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3868 PetscValidType(mat, 1); 3869 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3870 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3871 PetscCheckSameComm(mat, 1, b, 2); 3872 PetscCheckSameComm(mat, 1, x, 3); 3873 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3874 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); 3875 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); 3876 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); 3877 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3878 MatCheckPreallocated(mat, 1); 3879 3880 PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0)); 3881 PetscUseTypeMethod(mat, backwardsolve, b, x); 3882 PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0)); 3883 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3884 PetscFunctionReturn(PETSC_SUCCESS); 3885 } 3886 3887 /*@ 3888 MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix. 3889 3890 Neighbor-wise Collective 3891 3892 Input Parameters: 3893 + mat - the factored matrix 3894 . b - the right-hand-side vector 3895 - y - the vector to be added to 3896 3897 Output Parameter: 3898 . x - the result vector 3899 3900 Level: developer 3901 3902 Note: 3903 The vectors `b` and `x` cannot be the same. I.e., one cannot 3904 call `MatSolveAdd`(A,x,y,x). 3905 3906 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3907 @*/ 3908 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x) 3909 { 3910 PetscScalar one = 1.0; 3911 Vec tmp; 3912 3913 PetscFunctionBegin; 3914 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3915 PetscValidType(mat, 1); 3916 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 3917 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3918 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 3919 PetscCheckSameComm(mat, 1, b, 2); 3920 PetscCheckSameComm(mat, 1, y, 3); 3921 PetscCheckSameComm(mat, 1, x, 4); 3922 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3923 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); 3924 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); 3925 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); 3926 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); 3927 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); 3928 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3929 MatCheckPreallocated(mat, 1); 3930 3931 PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y)); 3932 if (mat->factorerrortype) { 3933 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3934 PetscCall(VecSetInf(x)); 3935 } else if (mat->ops->solveadd) { 3936 PetscUseTypeMethod(mat, solveadd, b, y, x); 3937 } else { 3938 /* do the solve then the add manually */ 3939 if (x != y) { 3940 PetscCall(MatSolve(mat, b, x)); 3941 PetscCall(VecAXPY(x, one, y)); 3942 } else { 3943 PetscCall(VecDuplicate(x, &tmp)); 3944 PetscCall(VecCopy(x, tmp)); 3945 PetscCall(MatSolve(mat, b, x)); 3946 PetscCall(VecAXPY(x, one, tmp)); 3947 PetscCall(VecDestroy(&tmp)); 3948 } 3949 } 3950 PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y)); 3951 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3952 PetscFunctionReturn(PETSC_SUCCESS); 3953 } 3954 3955 /*@ 3956 MatSolveTranspose - Solves A' x = b, given a factored matrix. 3957 3958 Neighbor-wise Collective 3959 3960 Input Parameters: 3961 + mat - the factored matrix 3962 - b - the right-hand-side vector 3963 3964 Output Parameter: 3965 . x - the result vector 3966 3967 Level: developer 3968 3969 Notes: 3970 The vectors `b` and `x` cannot be the same. I.e., one cannot 3971 call `MatSolveTranspose`(A,x,x). 3972 3973 Most users should employ the `KSP` interface for linear solvers 3974 instead of working directly with matrix algebra routines such as this. 3975 See, e.g., `KSPCreate()`. 3976 3977 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()` 3978 @*/ 3979 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x) 3980 { 3981 PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose; 3982 3983 PetscFunctionBegin; 3984 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3985 PetscValidType(mat, 1); 3986 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3987 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3988 PetscCheckSameComm(mat, 1, b, 2); 3989 PetscCheckSameComm(mat, 1, x, 3); 3990 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3991 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); 3992 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); 3993 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3994 MatCheckPreallocated(mat, 1); 3995 PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0)); 3996 if (mat->factorerrortype) { 3997 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3998 PetscCall(VecSetInf(x)); 3999 } else { 4000 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name); 4001 PetscCall((*f)(mat, b, x)); 4002 } 4003 PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0)); 4004 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4005 PetscFunctionReturn(PETSC_SUCCESS); 4006 } 4007 4008 /*@ 4009 MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a 4010 factored matrix. 4011 4012 Neighbor-wise Collective 4013 4014 Input Parameters: 4015 + mat - the factored matrix 4016 . b - the right-hand-side vector 4017 - y - the vector to be added to 4018 4019 Output Parameter: 4020 . x - the result vector 4021 4022 Level: developer 4023 4024 Note: 4025 The vectors `b` and `x` cannot be the same. I.e., one cannot 4026 call `MatSolveTransposeAdd`(A,x,y,x). 4027 4028 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()` 4029 @*/ 4030 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x) 4031 { 4032 PetscScalar one = 1.0; 4033 Vec tmp; 4034 PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd; 4035 4036 PetscFunctionBegin; 4037 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4038 PetscValidType(mat, 1); 4039 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4040 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4041 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4042 PetscCheckSameComm(mat, 1, b, 2); 4043 PetscCheckSameComm(mat, 1, y, 3); 4044 PetscCheckSameComm(mat, 1, x, 4); 4045 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4046 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); 4047 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); 4048 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); 4049 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); 4050 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4051 MatCheckPreallocated(mat, 1); 4052 4053 PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y)); 4054 if (mat->factorerrortype) { 4055 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4056 PetscCall(VecSetInf(x)); 4057 } else if (f) { 4058 PetscCall((*f)(mat, b, y, x)); 4059 } else { 4060 /* do the solve then the add manually */ 4061 if (x != y) { 4062 PetscCall(MatSolveTranspose(mat, b, x)); 4063 PetscCall(VecAXPY(x, one, y)); 4064 } else { 4065 PetscCall(VecDuplicate(x, &tmp)); 4066 PetscCall(VecCopy(x, tmp)); 4067 PetscCall(MatSolveTranspose(mat, b, x)); 4068 PetscCall(VecAXPY(x, one, tmp)); 4069 PetscCall(VecDestroy(&tmp)); 4070 } 4071 } 4072 PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y)); 4073 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4074 PetscFunctionReturn(PETSC_SUCCESS); 4075 } 4076 4077 /*@ 4078 MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps. 4079 4080 Neighbor-wise Collective 4081 4082 Input Parameters: 4083 + mat - the matrix 4084 . b - the right hand side 4085 . omega - the relaxation factor 4086 . flag - flag indicating the type of SOR (see below) 4087 . shift - diagonal shift 4088 . its - the number of iterations 4089 - lits - the number of local iterations 4090 4091 Output Parameter: 4092 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess) 4093 4094 SOR Flags: 4095 + `SOR_FORWARD_SWEEP` - forward SOR 4096 . `SOR_BACKWARD_SWEEP` - backward SOR 4097 . `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR) 4098 . `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR 4099 . `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR 4100 . `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR 4101 . `SOR_EISENSTAT` - SOR with Eisenstat trick 4102 . `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies 4103 upper/lower triangular part of matrix to 4104 vector (with omega) 4105 - `SOR_ZERO_INITIAL_GUESS` - zero initial guess 4106 4107 Level: developer 4108 4109 Notes: 4110 `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and 4111 `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings 4112 on each processor. 4113 4114 Application programmers will not generally use `MatSOR()` directly, 4115 but instead will employ the `KSP`/`PC` interface. 4116 4117 For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing 4118 4119 Most users should employ the `KSP` interface for linear solvers 4120 instead of working directly with matrix algebra routines such as this. 4121 See, e.g., `KSPCreate()`. 4122 4123 Vectors `x` and `b` CANNOT be the same 4124 4125 The flags are implemented as bitwise inclusive or operations. 4126 For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`) 4127 to specify a zero initial guess for SSOR. 4128 4129 Developer Note: 4130 We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes 4131 4132 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()` 4133 @*/ 4134 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x) 4135 { 4136 PetscFunctionBegin; 4137 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4138 PetscValidType(mat, 1); 4139 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4140 PetscValidHeaderSpecific(x, VEC_CLASSID, 8); 4141 PetscCheckSameComm(mat, 1, b, 2); 4142 PetscCheckSameComm(mat, 1, x, 8); 4143 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4144 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4145 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); 4146 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); 4147 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); 4148 PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its); 4149 PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits); 4150 PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same"); 4151 4152 MatCheckPreallocated(mat, 1); 4153 PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0)); 4154 PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x); 4155 PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0)); 4156 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4157 PetscFunctionReturn(PETSC_SUCCESS); 4158 } 4159 4160 /* 4161 Default matrix copy routine. 4162 */ 4163 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str) 4164 { 4165 PetscInt i, rstart = 0, rend = 0, nz; 4166 const PetscInt *cwork; 4167 const PetscScalar *vwork; 4168 4169 PetscFunctionBegin; 4170 if (B->assembled) PetscCall(MatZeroEntries(B)); 4171 if (str == SAME_NONZERO_PATTERN) { 4172 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 4173 for (i = rstart; i < rend; i++) { 4174 PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork)); 4175 PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES)); 4176 PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork)); 4177 } 4178 } else { 4179 PetscCall(MatAYPX(B, 0.0, A, str)); 4180 } 4181 PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 4182 PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 4183 PetscFunctionReturn(PETSC_SUCCESS); 4184 } 4185 4186 /*@ 4187 MatCopy - Copies a matrix to another matrix. 4188 4189 Collective 4190 4191 Input Parameters: 4192 + A - the matrix 4193 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN` 4194 4195 Output Parameter: 4196 . B - where the copy is put 4197 4198 Level: intermediate 4199 4200 Notes: 4201 If you use `SAME_NONZERO_PATTERN` then the two matrices must have the same nonzero pattern or the routine will crash. 4202 4203 `MatCopy()` copies the matrix entries of a matrix to another existing 4204 matrix (after first zeroing the second matrix). A related routine is 4205 `MatConvert()`, which first creates a new matrix and then copies the data. 4206 4207 .seealso: [](chapter_matrices), `Mat`, `MatConvert()`, `MatDuplicate()` 4208 @*/ 4209 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str) 4210 { 4211 PetscInt i; 4212 4213 PetscFunctionBegin; 4214 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 4215 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 4216 PetscValidType(A, 1); 4217 PetscValidType(B, 2); 4218 PetscCheckSameComm(A, 1, B, 2); 4219 MatCheckPreallocated(B, 2); 4220 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4221 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4222 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, 4223 A->cmap->N, B->cmap->N); 4224 MatCheckPreallocated(A, 1); 4225 if (A == B) PetscFunctionReturn(PETSC_SUCCESS); 4226 4227 PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0)); 4228 if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str); 4229 else PetscCall(MatCopy_Basic(A, B, str)); 4230 4231 B->stencil.dim = A->stencil.dim; 4232 B->stencil.noc = A->stencil.noc; 4233 for (i = 0; i <= A->stencil.dim; i++) { 4234 B->stencil.dims[i] = A->stencil.dims[i]; 4235 B->stencil.starts[i] = A->stencil.starts[i]; 4236 } 4237 4238 PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0)); 4239 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4240 PetscFunctionReturn(PETSC_SUCCESS); 4241 } 4242 4243 /*@C 4244 MatConvert - Converts a matrix to another matrix, either of the same 4245 or different type. 4246 4247 Collective 4248 4249 Input Parameters: 4250 + mat - the matrix 4251 . newtype - new matrix type. Use `MATSAME` to create a new matrix of the 4252 same type as the original matrix. 4253 - reuse - denotes if the destination matrix is to be created or reused. 4254 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 4255 `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). 4256 4257 Output Parameter: 4258 . M - pointer to place new matrix 4259 4260 Level: intermediate 4261 4262 Notes: 4263 `MatConvert()` first creates a new matrix and then copies the data from 4264 the first matrix. A related routine is `MatCopy()`, which copies the matrix 4265 entries of one matrix to another already existing matrix context. 4266 4267 Cannot be used to convert a sequential matrix to parallel or parallel to sequential, 4268 the MPI communicator of the generated matrix is always the same as the communicator 4269 of the input matrix. 4270 4271 .seealso: [](chapter_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 4272 @*/ 4273 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M) 4274 { 4275 PetscBool sametype, issame, flg; 4276 PetscBool3 issymmetric, ishermitian; 4277 char convname[256], mtype[256]; 4278 Mat B; 4279 4280 PetscFunctionBegin; 4281 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4282 PetscValidType(mat, 1); 4283 PetscValidPointer(M, 4); 4284 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4285 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4286 MatCheckPreallocated(mat, 1); 4287 4288 PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg)); 4289 if (flg) newtype = mtype; 4290 4291 PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype)); 4292 PetscCall(PetscStrcmp(newtype, "same", &issame)); 4293 PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix"); 4294 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"); 4295 4296 if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) { 4297 PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4298 PetscFunctionReturn(PETSC_SUCCESS); 4299 } 4300 4301 /* Cache Mat options because some converters use MatHeaderReplace */ 4302 issymmetric = mat->symmetric; 4303 ishermitian = mat->hermitian; 4304 4305 if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) { 4306 PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4307 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4308 } else { 4309 PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL; 4310 const char *prefix[3] = {"seq", "mpi", ""}; 4311 PetscInt i; 4312 /* 4313 Order of precedence: 4314 0) See if newtype is a superclass of the current matrix. 4315 1) See if a specialized converter is known to the current matrix. 4316 2) See if a specialized converter is known to the desired matrix class. 4317 3) See if a good general converter is registered for the desired class 4318 (as of 6/27/03 only MATMPIADJ falls into this category). 4319 4) See if a good general converter is known for the current matrix. 4320 5) Use a really basic converter. 4321 */ 4322 4323 /* 0) See if newtype is a superclass of the current matrix. 4324 i.e mat is mpiaij and newtype is aij */ 4325 for (i = 0; i < 2; i++) { 4326 PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname))); 4327 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4328 PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg)); 4329 PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg)); 4330 if (flg) { 4331 if (reuse == MAT_INPLACE_MATRIX) { 4332 PetscCall(PetscInfo(mat, "Early return\n")); 4333 PetscFunctionReturn(PETSC_SUCCESS); 4334 } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) { 4335 PetscCall(PetscInfo(mat, "Calling MatDuplicate\n")); 4336 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4337 PetscFunctionReturn(PETSC_SUCCESS); 4338 } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) { 4339 PetscCall(PetscInfo(mat, "Calling MatCopy\n")); 4340 PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN)); 4341 PetscFunctionReturn(PETSC_SUCCESS); 4342 } 4343 } 4344 } 4345 /* 1) See if a specialized converter is known to the current matrix and the desired class */ 4346 for (i = 0; i < 3; i++) { 4347 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4348 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4349 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4350 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4351 PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname))); 4352 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4353 PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv)); 4354 PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv)); 4355 if (conv) goto foundconv; 4356 } 4357 4358 /* 2) See if a specialized converter is known to the desired matrix class. */ 4359 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B)); 4360 PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 4361 PetscCall(MatSetType(B, newtype)); 4362 for (i = 0; i < 3; i++) { 4363 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4364 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4365 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4366 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4367 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4368 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4369 PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv)); 4370 PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv)); 4371 if (conv) { 4372 PetscCall(MatDestroy(&B)); 4373 goto foundconv; 4374 } 4375 } 4376 4377 /* 3) See if a good general converter is registered for the desired class */ 4378 conv = B->ops->convertfrom; 4379 PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv)); 4380 PetscCall(MatDestroy(&B)); 4381 if (conv) goto foundconv; 4382 4383 /* 4) See if a good general converter is known for the current matrix */ 4384 if (mat->ops->convert) conv = mat->ops->convert; 4385 PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv)); 4386 if (conv) goto foundconv; 4387 4388 /* 5) Use a really basic converter. */ 4389 PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n")); 4390 conv = MatConvert_Basic; 4391 4392 foundconv: 4393 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4394 PetscCall((*conv)(mat, newtype, reuse, M)); 4395 if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) { 4396 /* the block sizes must be same if the mappings are copied over */ 4397 (*M)->rmap->bs = mat->rmap->bs; 4398 (*M)->cmap->bs = mat->cmap->bs; 4399 PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping)); 4400 PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping)); 4401 (*M)->rmap->mapping = mat->rmap->mapping; 4402 (*M)->cmap->mapping = mat->cmap->mapping; 4403 } 4404 (*M)->stencil.dim = mat->stencil.dim; 4405 (*M)->stencil.noc = mat->stencil.noc; 4406 for (i = 0; i <= mat->stencil.dim; i++) { 4407 (*M)->stencil.dims[i] = mat->stencil.dims[i]; 4408 (*M)->stencil.starts[i] = mat->stencil.starts[i]; 4409 } 4410 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4411 } 4412 PetscCall(PetscObjectStateIncrease((PetscObject)*M)); 4413 4414 /* Copy Mat options */ 4415 if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE)); 4416 else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE)); 4417 if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE)); 4418 else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE)); 4419 PetscFunctionReturn(PETSC_SUCCESS); 4420 } 4421 4422 /*@C 4423 MatFactorGetSolverType - Returns name of the package providing the factorization routines 4424 4425 Not Collective 4426 4427 Input Parameter: 4428 . mat - the matrix, must be a factored matrix 4429 4430 Output Parameter: 4431 . type - the string name of the package (do not free this string) 4432 4433 Level: intermediate 4434 4435 Fortran Note: 4436 Pass in an empty string and the package name will be copied into it. Make sure the string is long enough. 4437 4438 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()` 4439 @*/ 4440 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type) 4441 { 4442 PetscErrorCode (*conv)(Mat, MatSolverType *); 4443 4444 PetscFunctionBegin; 4445 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4446 PetscValidType(mat, 1); 4447 PetscValidPointer(type, 2); 4448 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 4449 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv)); 4450 if (conv) PetscCall((*conv)(mat, type)); 4451 else *type = MATSOLVERPETSC; 4452 PetscFunctionReturn(PETSC_SUCCESS); 4453 } 4454 4455 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType; 4456 struct _MatSolverTypeForSpecifcType { 4457 MatType mtype; 4458 /* no entry for MAT_FACTOR_NONE */ 4459 PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *); 4460 MatSolverTypeForSpecifcType next; 4461 }; 4462 4463 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder; 4464 struct _MatSolverTypeHolder { 4465 char *name; 4466 MatSolverTypeForSpecifcType handlers; 4467 MatSolverTypeHolder next; 4468 }; 4469 4470 static MatSolverTypeHolder MatSolverTypeHolders = NULL; 4471 4472 /*@C 4473 MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type 4474 4475 Input Parameters: 4476 + package - name of the package, for example petsc or superlu 4477 . mtype - the matrix type that works with this package 4478 . ftype - the type of factorization supported by the package 4479 - createfactor - routine that will create the factored matrix ready to be used 4480 4481 Level: developer 4482 4483 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()` 4484 @*/ 4485 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *)) 4486 { 4487 MatSolverTypeHolder next = MatSolverTypeHolders, prev = NULL; 4488 PetscBool flg; 4489 MatSolverTypeForSpecifcType inext, iprev = NULL; 4490 4491 PetscFunctionBegin; 4492 PetscCall(MatInitializePackage()); 4493 if (!next) { 4494 PetscCall(PetscNew(&MatSolverTypeHolders)); 4495 PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name)); 4496 PetscCall(PetscNew(&MatSolverTypeHolders->handlers)); 4497 PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype)); 4498 MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor; 4499 PetscFunctionReturn(PETSC_SUCCESS); 4500 } 4501 while (next) { 4502 PetscCall(PetscStrcasecmp(package, next->name, &flg)); 4503 if (flg) { 4504 PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers"); 4505 inext = next->handlers; 4506 while (inext) { 4507 PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg)); 4508 if (flg) { 4509 inext->createfactor[(int)ftype - 1] = createfactor; 4510 PetscFunctionReturn(PETSC_SUCCESS); 4511 } 4512 iprev = inext; 4513 inext = inext->next; 4514 } 4515 PetscCall(PetscNew(&iprev->next)); 4516 PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype)); 4517 iprev->next->createfactor[(int)ftype - 1] = createfactor; 4518 PetscFunctionReturn(PETSC_SUCCESS); 4519 } 4520 prev = next; 4521 next = next->next; 4522 } 4523 PetscCall(PetscNew(&prev->next)); 4524 PetscCall(PetscStrallocpy(package, &prev->next->name)); 4525 PetscCall(PetscNew(&prev->next->handlers)); 4526 PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype)); 4527 prev->next->handlers->createfactor[(int)ftype - 1] = createfactor; 4528 PetscFunctionReturn(PETSC_SUCCESS); 4529 } 4530 4531 /*@C 4532 MatSolverTypeGet - Gets the function that creates the factor matrix if it exist 4533 4534 Input Parameters: 4535 + type - name of the package, for example petsc or superlu 4536 . ftype - the type of factorization supported by the type 4537 - mtype - the matrix type that works with this type 4538 4539 Output Parameters: 4540 + foundtype - `PETSC_TRUE` if the type was registered 4541 . foundmtype - `PETSC_TRUE` if the type supports the requested mtype 4542 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found 4543 4544 Level: developer 4545 4546 .seealso: [](chapter_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()` 4547 @*/ 4548 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *)) 4549 { 4550 MatSolverTypeHolder next = MatSolverTypeHolders; 4551 PetscBool flg; 4552 MatSolverTypeForSpecifcType inext; 4553 4554 PetscFunctionBegin; 4555 if (foundtype) *foundtype = PETSC_FALSE; 4556 if (foundmtype) *foundmtype = PETSC_FALSE; 4557 if (createfactor) *createfactor = NULL; 4558 4559 if (type) { 4560 while (next) { 4561 PetscCall(PetscStrcasecmp(type, next->name, &flg)); 4562 if (flg) { 4563 if (foundtype) *foundtype = PETSC_TRUE; 4564 inext = next->handlers; 4565 while (inext) { 4566 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4567 if (flg) { 4568 if (foundmtype) *foundmtype = PETSC_TRUE; 4569 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4570 PetscFunctionReturn(PETSC_SUCCESS); 4571 } 4572 inext = inext->next; 4573 } 4574 } 4575 next = next->next; 4576 } 4577 } else { 4578 while (next) { 4579 inext = next->handlers; 4580 while (inext) { 4581 PetscCall(PetscStrcmp(mtype, inext->mtype, &flg)); 4582 if (flg && inext->createfactor[(int)ftype - 1]) { 4583 if (foundtype) *foundtype = PETSC_TRUE; 4584 if (foundmtype) *foundmtype = PETSC_TRUE; 4585 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4586 PetscFunctionReturn(PETSC_SUCCESS); 4587 } 4588 inext = inext->next; 4589 } 4590 next = next->next; 4591 } 4592 /* try with base classes inext->mtype */ 4593 next = MatSolverTypeHolders; 4594 while (next) { 4595 inext = next->handlers; 4596 while (inext) { 4597 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4598 if (flg && inext->createfactor[(int)ftype - 1]) { 4599 if (foundtype) *foundtype = PETSC_TRUE; 4600 if (foundmtype) *foundmtype = PETSC_TRUE; 4601 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4602 PetscFunctionReturn(PETSC_SUCCESS); 4603 } 4604 inext = inext->next; 4605 } 4606 next = next->next; 4607 } 4608 } 4609 PetscFunctionReturn(PETSC_SUCCESS); 4610 } 4611 4612 PetscErrorCode MatSolverTypeDestroy(void) 4613 { 4614 MatSolverTypeHolder next = MatSolverTypeHolders, prev; 4615 MatSolverTypeForSpecifcType inext, iprev; 4616 4617 PetscFunctionBegin; 4618 while (next) { 4619 PetscCall(PetscFree(next->name)); 4620 inext = next->handlers; 4621 while (inext) { 4622 PetscCall(PetscFree(inext->mtype)); 4623 iprev = inext; 4624 inext = inext->next; 4625 PetscCall(PetscFree(iprev)); 4626 } 4627 prev = next; 4628 next = next->next; 4629 PetscCall(PetscFree(prev)); 4630 } 4631 MatSolverTypeHolders = NULL; 4632 PetscFunctionReturn(PETSC_SUCCESS); 4633 } 4634 4635 /*@C 4636 MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4637 4638 Logically Collective 4639 4640 Input Parameter: 4641 . mat - the matrix 4642 4643 Output Parameter: 4644 . flg - `PETSC_TRUE` if uses the ordering 4645 4646 Level: developer 4647 4648 Note: 4649 Most internal PETSc factorizations use the ordering passed to the factorization routine but external 4650 packages do not, thus we want to skip generating the ordering when it is not needed or used. 4651 4652 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4653 @*/ 4654 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg) 4655 { 4656 PetscFunctionBegin; 4657 *flg = mat->canuseordering; 4658 PetscFunctionReturn(PETSC_SUCCESS); 4659 } 4660 4661 /*@C 4662 MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object 4663 4664 Logically Collective 4665 4666 Input Parameters: 4667 + mat - the matrix obtained with `MatGetFactor()` 4668 - ftype - the factorization type to be used 4669 4670 Output Parameter: 4671 . otype - the preferred ordering type 4672 4673 Level: developer 4674 4675 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4676 @*/ 4677 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype) 4678 { 4679 PetscFunctionBegin; 4680 *otype = mat->preferredordering[ftype]; 4681 PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering"); 4682 PetscFunctionReturn(PETSC_SUCCESS); 4683 } 4684 4685 /*@C 4686 MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic() 4687 4688 Collective 4689 4690 Input Parameters: 4691 + mat - the matrix 4692 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4693 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4694 4695 Output Parameter: 4696 . f - the factor matrix used with MatXXFactorSymbolic() calls. Can be `NULL` in some cases, see notes below. 4697 4698 Options Database Key: 4699 . -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory. 4700 One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices. 4701 4702 Level: intermediate 4703 4704 Notes: 4705 The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization 4706 types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime. 4707 4708 Users usually access the factorization solvers via `KSP` 4709 4710 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4711 such as pastix, superlu, mumps etc. 4712 4713 PETSc must have been ./configure to use the external solver, using the option --download-package 4714 4715 Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption 4716 where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set 4717 call `MatSetOptionsPrefixFactor()` on the originating matrix or `MatSetOptionsPrefix()` on the resulting factor matrix. 4718 4719 Developer Note: 4720 This should actually be called `MatCreateFactor()` since it creates a new factor object 4721 4722 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, 4723 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4724 @*/ 4725 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f) 4726 { 4727 PetscBool foundtype, foundmtype; 4728 PetscErrorCode (*conv)(Mat, MatFactorType, Mat *); 4729 4730 PetscFunctionBegin; 4731 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4732 PetscValidType(mat, 1); 4733 4734 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4735 MatCheckPreallocated(mat, 1); 4736 4737 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv)); 4738 if (!foundtype) { 4739 if (type) { 4740 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], 4741 ((PetscObject)mat)->type_name, type); 4742 } else { 4743 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); 4744 } 4745 } 4746 PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name); 4747 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); 4748 4749 PetscCall((*conv)(mat, ftype, f)); 4750 if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix)); 4751 PetscFunctionReturn(PETSC_SUCCESS); 4752 } 4753 4754 /*@C 4755 MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type 4756 4757 Not Collective 4758 4759 Input Parameters: 4760 + mat - the matrix 4761 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4762 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4763 4764 Output Parameter: 4765 . flg - PETSC_TRUE if the factorization is available 4766 4767 Level: intermediate 4768 4769 Notes: 4770 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4771 such as pastix, superlu, mumps etc. 4772 4773 PETSc must have been ./configure to use the external solver, using the option --download-package 4774 4775 Developer Note: 4776 This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object 4777 4778 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactor()`, `MatSolverTypeRegister()`, 4779 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4780 @*/ 4781 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg) 4782 { 4783 PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *); 4784 4785 PetscFunctionBegin; 4786 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4787 PetscValidType(mat, 1); 4788 PetscValidBoolPointer(flg, 4); 4789 4790 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4791 MatCheckPreallocated(mat, 1); 4792 4793 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv)); 4794 *flg = gconv ? PETSC_TRUE : PETSC_FALSE; 4795 PetscFunctionReturn(PETSC_SUCCESS); 4796 } 4797 4798 /*@ 4799 MatDuplicate - Duplicates a matrix including the non-zero structure. 4800 4801 Collective 4802 4803 Input Parameters: 4804 + mat - the matrix 4805 - op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`. 4806 See the manual page for `MatDuplicateOption()` for an explanation of these options. 4807 4808 Output Parameter: 4809 . M - pointer to place new matrix 4810 4811 Level: intermediate 4812 4813 Notes: 4814 You cannot change the nonzero pattern for the parent or child matrix if you use `MAT_SHARE_NONZERO_PATTERN`. 4815 4816 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. 4817 4818 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 4819 is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated. 4820 User should not use `MatDuplicate()` to create new matrix M if M is intended to be reused as the product of matrix operation. 4821 4822 .seealso: [](chapter_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption` 4823 @*/ 4824 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M) 4825 { 4826 Mat B; 4827 VecType vtype; 4828 PetscInt i; 4829 PetscObject dm, container_h, container_d; 4830 void (*viewf)(void); 4831 4832 PetscFunctionBegin; 4833 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4834 PetscValidType(mat, 1); 4835 PetscValidPointer(M, 3); 4836 PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix"); 4837 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4838 MatCheckPreallocated(mat, 1); 4839 4840 *M = NULL; 4841 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4842 PetscUseTypeMethod(mat, duplicate, op, M); 4843 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4844 B = *M; 4845 4846 PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf)); 4847 if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf)); 4848 PetscCall(MatGetVecType(mat, &vtype)); 4849 PetscCall(MatSetVecType(B, vtype)); 4850 4851 B->stencil.dim = mat->stencil.dim; 4852 B->stencil.noc = mat->stencil.noc; 4853 for (i = 0; i <= mat->stencil.dim; i++) { 4854 B->stencil.dims[i] = mat->stencil.dims[i]; 4855 B->stencil.starts[i] = mat->stencil.starts[i]; 4856 } 4857 4858 B->nooffproczerorows = mat->nooffproczerorows; 4859 B->nooffprocentries = mat->nooffprocentries; 4860 4861 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm)); 4862 if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm)); 4863 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h)); 4864 if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h)); 4865 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d)); 4866 if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d)); 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 Parameter: 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 Parameter: 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 Parameter: 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 PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0)); 5256 PetscUseTypeMethod(A, transposesymbolic, B); 5257 PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0)); 5258 5259 PetscCall(MatTransposeSetPrecursor(A, *B)); 5260 PetscFunctionReturn(PETSC_SUCCESS); 5261 } 5262 5263 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B) 5264 { 5265 PetscContainer rB; 5266 MatParentState *rb; 5267 5268 PetscFunctionBegin; 5269 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5270 PetscValidType(A, 1); 5271 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5272 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5273 PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB)); 5274 PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()"); 5275 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5276 PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5277 PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure"); 5278 PetscFunctionReturn(PETSC_SUCCESS); 5279 } 5280 5281 /*@ 5282 MatIsTranspose - Test whether a matrix is another one's transpose, 5283 or its own, in which case it tests symmetry. 5284 5285 Collective 5286 5287 Input Parameters: 5288 + A - the matrix to test 5289 . B - the matrix to test against, this can equal the first parameter 5290 - tol - tolerance, differences between entries smaller than this are counted as zero 5291 5292 Output Parameter: 5293 . flg - the result 5294 5295 Level: intermediate 5296 5297 Notes: 5298 Only available for `MATAIJ` matrices. 5299 5300 The sequential algorithm has a running time of the order of the number of nonzeros; the parallel 5301 test involves parallel copies of the block-offdiagonal parts of the matrix. 5302 5303 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()` 5304 @*/ 5305 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5306 { 5307 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5308 5309 PetscFunctionBegin; 5310 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5311 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5312 PetscValidBoolPointer(flg, 4); 5313 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f)); 5314 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g)); 5315 *flg = PETSC_FALSE; 5316 if (f && g) { 5317 PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test"); 5318 PetscCall((*f)(A, B, tol, flg)); 5319 } else { 5320 MatType mattype; 5321 5322 PetscCall(MatGetType(f ? B : A, &mattype)); 5323 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype); 5324 } 5325 PetscFunctionReturn(PETSC_SUCCESS); 5326 } 5327 5328 /*@ 5329 MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate. 5330 5331 Collective 5332 5333 Input Parameters: 5334 + mat - the matrix to transpose and complex conjugate 5335 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5336 5337 Output Parameter: 5338 . B - the Hermitian transpose 5339 5340 Level: intermediate 5341 5342 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse` 5343 @*/ 5344 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B) 5345 { 5346 PetscFunctionBegin; 5347 PetscCall(MatTranspose(mat, reuse, B)); 5348 #if defined(PETSC_USE_COMPLEX) 5349 PetscCall(MatConjugate(*B)); 5350 #endif 5351 PetscFunctionReturn(PETSC_SUCCESS); 5352 } 5353 5354 /*@ 5355 MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose, 5356 5357 Collective 5358 5359 Input Parameters: 5360 + A - the matrix to test 5361 . B - the matrix to test against, this can equal the first parameter 5362 - tol - tolerance, differences between entries smaller than this are counted as zero 5363 5364 Output Parameter: 5365 . flg - the result 5366 5367 Level: intermediate 5368 5369 Notes: 5370 Only available for `MATAIJ` matrices. 5371 5372 The sequential algorithm 5373 has a running time of the order of the number of nonzeros; the parallel 5374 test involves parallel copies of the block-offdiagonal parts of the matrix. 5375 5376 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()` 5377 @*/ 5378 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5379 { 5380 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5381 5382 PetscFunctionBegin; 5383 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5384 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5385 PetscValidBoolPointer(flg, 4); 5386 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f)); 5387 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g)); 5388 if (f && g) { 5389 PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test"); 5390 PetscCall((*f)(A, B, tol, flg)); 5391 } 5392 PetscFunctionReturn(PETSC_SUCCESS); 5393 } 5394 5395 /*@ 5396 MatPermute - Creates a new matrix with rows and columns permuted from the 5397 original. 5398 5399 Collective 5400 5401 Input Parameters: 5402 + mat - the matrix to permute 5403 . row - row permutation, each processor supplies only the permutation for its rows 5404 - col - column permutation, each processor supplies only the permutation for its columns 5405 5406 Output Parameter: 5407 . B - the permuted matrix 5408 5409 Level: advanced 5410 5411 Note: 5412 The index sets map from row/col of permuted matrix to row/col of original matrix. 5413 The index sets should be on the same communicator as mat and have the same local sizes. 5414 5415 Developer Note: 5416 If you want to implement `MatPermute()` for a matrix type, and your approach doesn't 5417 exploit the fact that row and col are permutations, consider implementing the 5418 more general `MatCreateSubMatrix()` instead. 5419 5420 .seealso: [](chapter_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()` 5421 @*/ 5422 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B) 5423 { 5424 PetscFunctionBegin; 5425 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5426 PetscValidType(mat, 1); 5427 PetscValidHeaderSpecific(row, IS_CLASSID, 2); 5428 PetscValidHeaderSpecific(col, IS_CLASSID, 3); 5429 PetscValidPointer(B, 4); 5430 PetscCheckSameComm(mat, 1, row, 2); 5431 if (row != col) PetscCheckSameComm(row, 2, col, 3); 5432 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5433 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5434 PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name); 5435 MatCheckPreallocated(mat, 1); 5436 5437 if (mat->ops->permute) { 5438 PetscUseTypeMethod(mat, permute, row, col, B); 5439 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5440 } else { 5441 PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B)); 5442 } 5443 PetscFunctionReturn(PETSC_SUCCESS); 5444 } 5445 5446 /*@ 5447 MatEqual - Compares two matrices. 5448 5449 Collective 5450 5451 Input Parameters: 5452 + A - the first matrix 5453 - B - the second matrix 5454 5455 Output Parameter: 5456 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise. 5457 5458 Level: intermediate 5459 5460 .seealso: [](chapter_matrices), `Mat` 5461 @*/ 5462 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg) 5463 { 5464 PetscFunctionBegin; 5465 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5466 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5467 PetscValidType(A, 1); 5468 PetscValidType(B, 2); 5469 PetscValidBoolPointer(flg, 3); 5470 PetscCheckSameComm(A, 1, B, 2); 5471 MatCheckPreallocated(A, 1); 5472 MatCheckPreallocated(B, 2); 5473 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5474 PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5475 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, 5476 B->cmap->N); 5477 if (A->ops->equal && A->ops->equal == B->ops->equal) { 5478 PetscUseTypeMethod(A, equal, B, flg); 5479 } else { 5480 PetscCall(MatMultEqual(A, B, 10, flg)); 5481 } 5482 PetscFunctionReturn(PETSC_SUCCESS); 5483 } 5484 5485 /*@ 5486 MatDiagonalScale - Scales a matrix on the left and right by diagonal 5487 matrices that are stored as vectors. Either of the two scaling 5488 matrices can be `NULL`. 5489 5490 Collective 5491 5492 Input Parameters: 5493 + mat - the matrix to be scaled 5494 . l - the left scaling vector (or `NULL`) 5495 - r - the right scaling vector (or `NULL`) 5496 5497 Level: intermediate 5498 5499 Note: 5500 `MatDiagonalScale()` computes A = LAR, where 5501 L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector) 5502 The L scales the rows of the matrix, the R scales the columns of the matrix. 5503 5504 .seealso: [](chapter_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()` 5505 @*/ 5506 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r) 5507 { 5508 PetscFunctionBegin; 5509 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5510 PetscValidType(mat, 1); 5511 if (l) { 5512 PetscValidHeaderSpecific(l, VEC_CLASSID, 2); 5513 PetscCheckSameComm(mat, 1, l, 2); 5514 } 5515 if (r) { 5516 PetscValidHeaderSpecific(r, VEC_CLASSID, 3); 5517 PetscCheckSameComm(mat, 1, r, 3); 5518 } 5519 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5520 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5521 MatCheckPreallocated(mat, 1); 5522 if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS); 5523 5524 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5525 PetscUseTypeMethod(mat, diagonalscale, l, r); 5526 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5527 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5528 if (l != r) mat->symmetric = PETSC_BOOL3_FALSE; 5529 PetscFunctionReturn(PETSC_SUCCESS); 5530 } 5531 5532 /*@ 5533 MatScale - Scales all elements of a matrix by a given number. 5534 5535 Logically Collective 5536 5537 Input Parameters: 5538 + mat - the matrix to be scaled 5539 - a - the scaling value 5540 5541 Level: intermediate 5542 5543 .seealso: [](chapter_matrices), `Mat`, `MatDiagonalScale()` 5544 @*/ 5545 PetscErrorCode MatScale(Mat mat, PetscScalar a) 5546 { 5547 PetscFunctionBegin; 5548 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5549 PetscValidType(mat, 1); 5550 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5551 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5552 PetscValidLogicalCollectiveScalar(mat, a, 2); 5553 MatCheckPreallocated(mat, 1); 5554 5555 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5556 if (a != (PetscScalar)1.0) { 5557 PetscUseTypeMethod(mat, scale, a); 5558 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5559 } 5560 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5561 PetscFunctionReturn(PETSC_SUCCESS); 5562 } 5563 5564 /*@ 5565 MatNorm - Calculates various norms of a matrix. 5566 5567 Collective 5568 5569 Input Parameters: 5570 + mat - the matrix 5571 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY` 5572 5573 Output Parameter: 5574 . nrm - the resulting norm 5575 5576 Level: intermediate 5577 5578 .seealso: [](chapter_matrices), `Mat` 5579 @*/ 5580 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm) 5581 { 5582 PetscFunctionBegin; 5583 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5584 PetscValidType(mat, 1); 5585 PetscValidRealPointer(nrm, 3); 5586 5587 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5588 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5589 MatCheckPreallocated(mat, 1); 5590 5591 PetscUseTypeMethod(mat, norm, type, nrm); 5592 PetscFunctionReturn(PETSC_SUCCESS); 5593 } 5594 5595 /* 5596 This variable is used to prevent counting of MatAssemblyBegin() that 5597 are called from within a MatAssemblyEnd(). 5598 */ 5599 static PetscInt MatAssemblyEnd_InUse = 0; 5600 /*@ 5601 MatAssemblyBegin - Begins assembling the matrix. This routine should 5602 be called after completing all calls to `MatSetValues()`. 5603 5604 Collective 5605 5606 Input Parameters: 5607 + mat - the matrix 5608 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5609 5610 Level: beginner 5611 5612 Notes: 5613 `MatSetValues()` generally caches the values that belong to other MPI ranks. The matrix is ready to 5614 use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called. 5615 5616 Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES` 5617 in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before 5618 using the matrix. 5619 5620 ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the 5621 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 5622 a global collective operation requiring all processes that share the matrix. 5623 5624 Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed 5625 out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros 5626 before `MAT_FINAL_ASSEMBLY` so the space is not compressed out. 5627 5628 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()` 5629 @*/ 5630 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type) 5631 { 5632 PetscFunctionBegin; 5633 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5634 PetscValidType(mat, 1); 5635 MatCheckPreallocated(mat, 1); 5636 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?"); 5637 if (mat->assembled) { 5638 mat->was_assembled = PETSC_TRUE; 5639 mat->assembled = PETSC_FALSE; 5640 } 5641 5642 if (!MatAssemblyEnd_InUse) { 5643 PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0)); 5644 PetscTryTypeMethod(mat, assemblybegin, type); 5645 PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0)); 5646 } else PetscTryTypeMethod(mat, assemblybegin, type); 5647 PetscFunctionReturn(PETSC_SUCCESS); 5648 } 5649 5650 /*@ 5651 MatAssembled - Indicates if a matrix has been assembled and is ready for 5652 use; for example, in matrix-vector product. 5653 5654 Not Collective 5655 5656 Input Parameter: 5657 . mat - the matrix 5658 5659 Output Parameter: 5660 . assembled - `PETSC_TRUE` or `PETSC_FALSE` 5661 5662 Level: advanced 5663 5664 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()` 5665 @*/ 5666 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled) 5667 { 5668 PetscFunctionBegin; 5669 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5670 PetscValidBoolPointer(assembled, 2); 5671 *assembled = mat->assembled; 5672 PetscFunctionReturn(PETSC_SUCCESS); 5673 } 5674 5675 /*@ 5676 MatAssemblyEnd - Completes assembling the matrix. This routine should 5677 be called after `MatAssemblyBegin()`. 5678 5679 Collective 5680 5681 Input Parameters: 5682 + mat - the matrix 5683 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5684 5685 Options Database Keys: 5686 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatEndAssembly()` 5687 . -mat_view ::ascii_info_detail - Prints more detailed info 5688 . -mat_view - Prints matrix in ASCII format 5689 . -mat_view ::ascii_matlab - Prints matrix in Matlab format 5690 . -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 5691 . -display <name> - Sets display name (default is host) 5692 . -draw_pause <sec> - Sets number of seconds to pause after display 5693 . -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See [Using MATLAB with PETSc](ch_matlab)) 5694 . -viewer_socket_machine <machine> - Machine to use for socket 5695 . -viewer_socket_port <port> - Port number to use for socket 5696 - -mat_view binary:filename[:append] - Save matrix to file in binary format 5697 5698 Level: beginner 5699 5700 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()` 5701 @*/ 5702 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type) 5703 { 5704 static PetscInt inassm = 0; 5705 PetscBool flg = PETSC_FALSE; 5706 5707 PetscFunctionBegin; 5708 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5709 PetscValidType(mat, 1); 5710 5711 inassm++; 5712 MatAssemblyEnd_InUse++; 5713 if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */ 5714 PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0)); 5715 PetscTryTypeMethod(mat, assemblyend, type); 5716 PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0)); 5717 } else PetscTryTypeMethod(mat, assemblyend, type); 5718 5719 /* Flush assembly is not a true assembly */ 5720 if (type != MAT_FLUSH_ASSEMBLY) { 5721 if (mat->num_ass) { 5722 if (!mat->symmetry_eternal) { 5723 mat->symmetric = PETSC_BOOL3_UNKNOWN; 5724 mat->hermitian = PETSC_BOOL3_UNKNOWN; 5725 } 5726 if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN; 5727 if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN; 5728 } 5729 mat->num_ass++; 5730 mat->assembled = PETSC_TRUE; 5731 mat->ass_nonzerostate = mat->nonzerostate; 5732 } 5733 5734 mat->insertmode = NOT_SET_VALUES; 5735 MatAssemblyEnd_InUse--; 5736 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5737 if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) { 5738 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 5739 5740 if (mat->checksymmetryonassembly) { 5741 PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg)); 5742 if (flg) { 5743 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5744 } else { 5745 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5746 } 5747 } 5748 if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL)); 5749 } 5750 inassm--; 5751 PetscFunctionReturn(PETSC_SUCCESS); 5752 } 5753 5754 /*@ 5755 MatSetOption - Sets a parameter option for a matrix. Some options 5756 may be specific to certain storage formats. Some options 5757 determine how values will be inserted (or added). Sorted, 5758 row-oriented input will generally assemble the fastest. The default 5759 is row-oriented. 5760 5761 Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption` 5762 5763 Input Parameters: 5764 + mat - the matrix 5765 . option - the option, one of those listed below (and possibly others), 5766 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5767 5768 Options Describing Matrix Structure: 5769 + `MAT_SPD` - symmetric positive definite 5770 . `MAT_SYMMETRIC` - symmetric in terms of both structure and value 5771 . `MAT_HERMITIAN` - transpose is the complex conjugation 5772 . `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure 5773 . `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix 5774 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix 5775 - `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix 5776 5777 These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they 5778 do not need to be computed (usually at a high cost) 5779 5780 Options For Use with `MatSetValues()`: 5781 Insert a logically dense subblock, which can be 5782 . `MAT_ROW_ORIENTED` - row-oriented (default) 5783 5784 These options reflect the data you pass in with `MatSetValues()`; it has 5785 nothing to do with how the data is stored internally in the matrix 5786 data structure. 5787 5788 When (re)assembling a matrix, we can restrict the input for 5789 efficiency/debugging purposes. These options include 5790 + `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow) 5791 . `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated 5792 . `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries 5793 . `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry 5794 . `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly 5795 . `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if 5796 any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves 5797 performance for very large process counts. 5798 - `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset 5799 of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly 5800 functions, instead sending only neighbor messages. 5801 5802 Level: intermediate 5803 5804 Notes: 5805 Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg! 5806 5807 Some options are relevant only for particular matrix types and 5808 are thus ignored by others. Other options are not supported by 5809 certain matrix types and will generate an error message if set. 5810 5811 If using Fortran to compute a matrix, one may need to 5812 use the column-oriented option (or convert to the row-oriented 5813 format). 5814 5815 `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion 5816 that would generate a new entry in the nonzero structure is instead 5817 ignored. Thus, if memory has not already been allocated for this particular 5818 data, then the insertion is ignored. For dense matrices, in which 5819 the entire array is allocated, no entries are ever ignored. 5820 Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction 5821 5822 `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion 5823 that would generate a new entry in the nonzero structure instead produces 5824 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 5825 5826 `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion 5827 that would generate a new entry that has not been preallocated will 5828 instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats 5829 only.) This is a useful flag when debugging matrix memory preallocation. 5830 If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 5831 5832 `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for 5833 other processors should be dropped, rather than stashed. 5834 This is useful if you know that the "owning" processor is also 5835 always generating the correct matrix entries, so that PETSc need 5836 not transfer duplicate entries generated on another processor. 5837 5838 `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the 5839 searches during matrix assembly. When this flag is set, the hash table 5840 is created during the first matrix assembly. This hash table is 5841 used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()` 5842 to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag 5843 should be used with `MAT_USE_HASH_TABLE` flag. This option is currently 5844 supported by `MATMPIBAIJ` format only. 5845 5846 `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries 5847 are kept in the nonzero structure 5848 5849 `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating 5850 a zero location in the matrix 5851 5852 `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types 5853 5854 `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the 5855 zero row routines and thus improves performance for very large process counts. 5856 5857 `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular 5858 part of the matrix (since they should match the upper triangular part). 5859 5860 `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a 5861 single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common 5862 with finite difference schemes with non-periodic boundary conditions. 5863 5864 Developer Note: 5865 `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other 5866 places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRIC` or `MAT_SPD` would need to be changed back 5867 to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had 5868 not changed. 5869 5870 .seealso: [](chapter_matrices), `MatOption`, `Mat`, `MatGetOption()` 5871 @*/ 5872 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg) 5873 { 5874 PetscFunctionBegin; 5875 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5876 if (op > 0) { 5877 PetscValidLogicalCollectiveEnum(mat, op, 2); 5878 PetscValidLogicalCollectiveBool(mat, flg, 3); 5879 } 5880 5881 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); 5882 5883 switch (op) { 5884 case MAT_FORCE_DIAGONAL_ENTRIES: 5885 mat->force_diagonals = flg; 5886 PetscFunctionReturn(PETSC_SUCCESS); 5887 case MAT_NO_OFF_PROC_ENTRIES: 5888 mat->nooffprocentries = flg; 5889 PetscFunctionReturn(PETSC_SUCCESS); 5890 case MAT_SUBSET_OFF_PROC_ENTRIES: 5891 mat->assembly_subset = flg; 5892 if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */ 5893 #if !defined(PETSC_HAVE_MPIUNI) 5894 PetscCall(MatStashScatterDestroy_BTS(&mat->stash)); 5895 #endif 5896 mat->stash.first_assembly_done = PETSC_FALSE; 5897 } 5898 PetscFunctionReturn(PETSC_SUCCESS); 5899 case MAT_NO_OFF_PROC_ZERO_ROWS: 5900 mat->nooffproczerorows = flg; 5901 PetscFunctionReturn(PETSC_SUCCESS); 5902 case MAT_SPD: 5903 if (flg) { 5904 mat->spd = PETSC_BOOL3_TRUE; 5905 mat->symmetric = PETSC_BOOL3_TRUE; 5906 mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5907 } else { 5908 mat->spd = PETSC_BOOL3_FALSE; 5909 } 5910 break; 5911 case MAT_SYMMETRIC: 5912 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5913 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5914 #if !defined(PETSC_USE_COMPLEX) 5915 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5916 #endif 5917 break; 5918 case MAT_HERMITIAN: 5919 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5920 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5921 #if !defined(PETSC_USE_COMPLEX) 5922 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5923 #endif 5924 break; 5925 case MAT_STRUCTURALLY_SYMMETRIC: 5926 mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5927 break; 5928 case MAT_SYMMETRY_ETERNAL: 5929 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"); 5930 mat->symmetry_eternal = flg; 5931 if (flg) mat->structural_symmetry_eternal = PETSC_TRUE; 5932 break; 5933 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 5934 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"); 5935 mat->structural_symmetry_eternal = flg; 5936 break; 5937 case MAT_SPD_ETERNAL: 5938 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"); 5939 mat->spd_eternal = flg; 5940 if (flg) { 5941 mat->structural_symmetry_eternal = PETSC_TRUE; 5942 mat->symmetry_eternal = PETSC_TRUE; 5943 } 5944 break; 5945 case MAT_STRUCTURE_ONLY: 5946 mat->structure_only = flg; 5947 break; 5948 case MAT_SORTED_FULL: 5949 mat->sortedfull = flg; 5950 break; 5951 default: 5952 break; 5953 } 5954 PetscTryTypeMethod(mat, setoption, op, flg); 5955 PetscFunctionReturn(PETSC_SUCCESS); 5956 } 5957 5958 /*@ 5959 MatGetOption - Gets a parameter option that has been set for a matrix. 5960 5961 Logically Collective 5962 5963 Input Parameters: 5964 + mat - the matrix 5965 - option - the option, this only responds to certain options, check the code for which ones 5966 5967 Output Parameter: 5968 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5969 5970 Level: intermediate 5971 5972 Notes: 5973 Can only be called after `MatSetSizes()` and `MatSetType()` have been set. 5974 5975 Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or 5976 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 5977 5978 .seealso: [](chapter_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, 5979 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 5980 @*/ 5981 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg) 5982 { 5983 PetscFunctionBegin; 5984 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5985 PetscValidType(mat, 1); 5986 5987 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); 5988 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()"); 5989 5990 switch (op) { 5991 case MAT_NO_OFF_PROC_ENTRIES: 5992 *flg = mat->nooffprocentries; 5993 break; 5994 case MAT_NO_OFF_PROC_ZERO_ROWS: 5995 *flg = mat->nooffproczerorows; 5996 break; 5997 case MAT_SYMMETRIC: 5998 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()"); 5999 break; 6000 case MAT_HERMITIAN: 6001 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()"); 6002 break; 6003 case MAT_STRUCTURALLY_SYMMETRIC: 6004 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()"); 6005 break; 6006 case MAT_SPD: 6007 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()"); 6008 break; 6009 case MAT_SYMMETRY_ETERNAL: 6010 *flg = mat->symmetry_eternal; 6011 break; 6012 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6013 *flg = mat->symmetry_eternal; 6014 break; 6015 default: 6016 break; 6017 } 6018 PetscFunctionReturn(PETSC_SUCCESS); 6019 } 6020 6021 /*@ 6022 MatZeroEntries - Zeros all entries of a matrix. For sparse matrices 6023 this routine retains the old nonzero structure. 6024 6025 Logically Collective 6026 6027 Input Parameter: 6028 . mat - the matrix 6029 6030 Level: intermediate 6031 6032 Note: 6033 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. 6034 See the Performance chapter of the users manual for information on preallocating matrices. 6035 6036 .seealso: [](chapter_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()` 6037 @*/ 6038 PetscErrorCode MatZeroEntries(Mat mat) 6039 { 6040 PetscFunctionBegin; 6041 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6042 PetscValidType(mat, 1); 6043 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6044 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"); 6045 MatCheckPreallocated(mat, 1); 6046 6047 PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0)); 6048 PetscUseTypeMethod(mat, zeroentries); 6049 PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0)); 6050 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6051 PetscFunctionReturn(PETSC_SUCCESS); 6052 } 6053 6054 /*@ 6055 MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal) 6056 of a set of rows and columns of a matrix. 6057 6058 Collective 6059 6060 Input Parameters: 6061 + mat - the matrix 6062 . numRows - the number of rows/columns to zero 6063 . rows - the global row indices 6064 . diag - value put in the diagonal of the eliminated rows 6065 . x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call 6066 - b - optional vector of the right hand side, that will be adjusted by provided solution entries 6067 6068 Level: intermediate 6069 6070 Notes: 6071 This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6072 6073 For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`. 6074 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 6075 6076 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6077 Krylov method to take advantage of the known solution on the zeroed rows. 6078 6079 For the parallel case, all processes that share the matrix (i.e., 6080 those in the communicator used for matrix creation) MUST call this 6081 routine, regardless of whether any rows being zeroed are owned by 6082 them. 6083 6084 Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix. 6085 6086 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6087 list only rows local to itself). 6088 6089 The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine. 6090 6091 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6092 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6093 @*/ 6094 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6095 { 6096 PetscFunctionBegin; 6097 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6098 PetscValidType(mat, 1); 6099 if (numRows) PetscValidIntPointer(rows, 3); 6100 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6101 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6102 MatCheckPreallocated(mat, 1); 6103 6104 PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b); 6105 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6106 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6107 PetscFunctionReturn(PETSC_SUCCESS); 6108 } 6109 6110 /*@ 6111 MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal) 6112 of a set of rows and columns of a matrix. 6113 6114 Collective 6115 6116 Input Parameters: 6117 + mat - the matrix 6118 . is - the rows to zero 6119 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6120 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6121 - b - optional vector of right hand side, that will be adjusted by provided solution 6122 6123 Level: intermediate 6124 6125 Note: 6126 See `MatZeroRowsColumns()` for details on how this routine operates. 6127 6128 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6129 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()` 6130 @*/ 6131 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6132 { 6133 PetscInt numRows; 6134 const PetscInt *rows; 6135 6136 PetscFunctionBegin; 6137 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6138 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6139 PetscValidType(mat, 1); 6140 PetscValidType(is, 2); 6141 PetscCall(ISGetLocalSize(is, &numRows)); 6142 PetscCall(ISGetIndices(is, &rows)); 6143 PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b)); 6144 PetscCall(ISRestoreIndices(is, &rows)); 6145 PetscFunctionReturn(PETSC_SUCCESS); 6146 } 6147 6148 /*@ 6149 MatZeroRows - Zeros all entries (except possibly the main diagonal) 6150 of a set of rows of a matrix. 6151 6152 Collective 6153 6154 Input Parameters: 6155 + mat - the matrix 6156 . numRows - the number of rows to zero 6157 . rows - the global row indices 6158 . diag - value put in the diagonal of the zeroed rows 6159 . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call 6160 - b - optional vector of right hand side, that will be adjusted by provided solution entries 6161 6162 Level: intermediate 6163 6164 Notes: 6165 This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6166 6167 For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`. 6168 6169 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6170 Krylov method to take advantage of the known solution on the zeroed rows. 6171 6172 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) 6173 from the matrix. 6174 6175 Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix 6176 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 6177 formats this does not alter the nonzero structure. 6178 6179 If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure 6180 of the matrix is not changed the values are 6181 merely zeroed. 6182 6183 The user can set a value in the diagonal entry (or for the `MATAIJ` format 6184 formats can optionally remove the main diagonal entry from the 6185 nonzero structure as well, by passing 0.0 as the final argument). 6186 6187 For the parallel case, all processes that share the matrix (i.e., 6188 those in the communicator used for matrix creation) MUST call this 6189 routine, regardless of whether any rows being zeroed are owned by 6190 them. 6191 6192 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6193 list only rows local to itself). 6194 6195 You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it 6196 owns that are to be zeroed. This saves a global synchronization in the implementation. 6197 6198 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6199 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE` 6200 @*/ 6201 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6202 { 6203 PetscFunctionBegin; 6204 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6205 PetscValidType(mat, 1); 6206 if (numRows) PetscValidIntPointer(rows, 3); 6207 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6208 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6209 MatCheckPreallocated(mat, 1); 6210 6211 PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b); 6212 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6213 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6214 PetscFunctionReturn(PETSC_SUCCESS); 6215 } 6216 6217 /*@ 6218 MatZeroRowsIS - Zeros all entries (except possibly the main diagonal) 6219 of a set of rows of a matrix. 6220 6221 Collective 6222 6223 Input Parameters: 6224 + mat - the matrix 6225 . is - index set of rows to remove (if `NULL` then no row is removed) 6226 . diag - value put in all diagonals of eliminated rows 6227 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6228 - b - optional vector of right hand side, that will be adjusted by provided solution 6229 6230 Level: intermediate 6231 6232 Note: 6233 See `MatZeroRows()` for details on how this routine operates. 6234 6235 .seealso: [](chapter_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6236 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6237 @*/ 6238 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6239 { 6240 PetscInt numRows = 0; 6241 const PetscInt *rows = NULL; 6242 6243 PetscFunctionBegin; 6244 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6245 PetscValidType(mat, 1); 6246 if (is) { 6247 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6248 PetscCall(ISGetLocalSize(is, &numRows)); 6249 PetscCall(ISGetIndices(is, &rows)); 6250 } 6251 PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b)); 6252 if (is) PetscCall(ISRestoreIndices(is, &rows)); 6253 PetscFunctionReturn(PETSC_SUCCESS); 6254 } 6255 6256 /*@ 6257 MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal) 6258 of a set of rows of a matrix. These rows must be local to the process. 6259 6260 Collective 6261 6262 Input Parameters: 6263 + mat - the matrix 6264 . numRows - the number of rows to remove 6265 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6266 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6267 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6268 - b - optional vector of right hand side, that will be adjusted by provided solution 6269 6270 Level: intermediate 6271 6272 Notes: 6273 See `MatZeroRows()` for details on how this routine operates. 6274 6275 The grid coordinates are across the entire grid, not just the local portion 6276 6277 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6278 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6279 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6280 `DM_BOUNDARY_PERIODIC` boundary type. 6281 6282 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 6283 a single value per point) you can skip filling those indices. 6284 6285 Fortran Note: 6286 `idxm` and `idxn` should be declared as 6287 $ MatStencil idxm(4, m) 6288 and the values inserted using 6289 .vb 6290 idxm(MatStencil_i, 1) = i 6291 idxm(MatStencil_j, 1) = j 6292 idxm(MatStencil_k, 1) = k 6293 idxm(MatStencil_c, 1) = c 6294 etc 6295 .ve 6296 6297 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6298 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6299 @*/ 6300 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6301 { 6302 PetscInt dim = mat->stencil.dim; 6303 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6304 PetscInt *dims = mat->stencil.dims + 1; 6305 PetscInt *starts = mat->stencil.starts; 6306 PetscInt *dxm = (PetscInt *)rows; 6307 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6308 6309 PetscFunctionBegin; 6310 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6311 PetscValidType(mat, 1); 6312 if (numRows) PetscValidPointer(rows, 3); 6313 6314 PetscCall(PetscMalloc1(numRows, &jdxm)); 6315 for (i = 0; i < numRows; ++i) { 6316 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6317 for (j = 0; j < 3 - sdim; ++j) dxm++; 6318 /* Local index in X dir */ 6319 tmp = *dxm++ - starts[0]; 6320 /* Loop over remaining dimensions */ 6321 for (j = 0; j < dim - 1; ++j) { 6322 /* If nonlocal, set index to be negative */ 6323 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6324 /* Update local index */ 6325 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6326 } 6327 /* Skip component slot if necessary */ 6328 if (mat->stencil.noc) dxm++; 6329 /* Local row number */ 6330 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6331 } 6332 PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b)); 6333 PetscCall(PetscFree(jdxm)); 6334 PetscFunctionReturn(PETSC_SUCCESS); 6335 } 6336 6337 /*@ 6338 MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal) 6339 of a set of rows and columns of a matrix. 6340 6341 Collective 6342 6343 Input Parameters: 6344 + mat - the matrix 6345 . numRows - the number of rows/columns to remove 6346 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6347 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6348 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6349 - b - optional vector of right hand side, that will be adjusted by provided solution 6350 6351 Level: intermediate 6352 6353 Notes: 6354 See `MatZeroRowsColumns()` for details on how this routine operates. 6355 6356 The grid coordinates are across the entire grid, not just the local portion 6357 6358 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6359 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6360 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6361 `DM_BOUNDARY_PERIODIC` boundary type. 6362 6363 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 6364 a single value per point) you can skip filling those indices. 6365 6366 Fortran Note: 6367 `idxm` and `idxn` should be declared as 6368 $ MatStencil idxm(4, m) 6369 and the values inserted using 6370 .vb 6371 idxm(MatStencil_i, 1) = i 6372 idxm(MatStencil_j, 1) = j 6373 idxm(MatStencil_k, 1) = k 6374 idxm(MatStencil_c, 1) = c 6375 etc 6376 .ve 6377 6378 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6379 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()` 6380 @*/ 6381 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6382 { 6383 PetscInt dim = mat->stencil.dim; 6384 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6385 PetscInt *dims = mat->stencil.dims + 1; 6386 PetscInt *starts = mat->stencil.starts; 6387 PetscInt *dxm = (PetscInt *)rows; 6388 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6389 6390 PetscFunctionBegin; 6391 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6392 PetscValidType(mat, 1); 6393 if (numRows) PetscValidPointer(rows, 3); 6394 6395 PetscCall(PetscMalloc1(numRows, &jdxm)); 6396 for (i = 0; i < numRows; ++i) { 6397 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6398 for (j = 0; j < 3 - sdim; ++j) dxm++; 6399 /* Local index in X dir */ 6400 tmp = *dxm++ - starts[0]; 6401 /* Loop over remaining dimensions */ 6402 for (j = 0; j < dim - 1; ++j) { 6403 /* If nonlocal, set index to be negative */ 6404 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6405 /* Update local index */ 6406 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6407 } 6408 /* Skip component slot if necessary */ 6409 if (mat->stencil.noc) dxm++; 6410 /* Local row number */ 6411 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6412 } 6413 PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b)); 6414 PetscCall(PetscFree(jdxm)); 6415 PetscFunctionReturn(PETSC_SUCCESS); 6416 } 6417 6418 /*@C 6419 MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal) 6420 of a set of rows of a matrix; using local numbering of rows. 6421 6422 Collective 6423 6424 Input Parameters: 6425 + mat - the matrix 6426 . numRows - the number of rows to remove 6427 . rows - the local row indices 6428 . diag - value put in all diagonals of eliminated rows 6429 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6430 - b - optional vector of right hand side, that will be adjusted by provided solution 6431 6432 Level: intermediate 6433 6434 Notes: 6435 Before calling `MatZeroRowsLocal()`, the user must first set the 6436 local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`. 6437 6438 See `MatZeroRows()` for details on how this routine operates. 6439 6440 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`, 6441 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6442 @*/ 6443 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6444 { 6445 PetscFunctionBegin; 6446 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6447 PetscValidType(mat, 1); 6448 if (numRows) PetscValidIntPointer(rows, 3); 6449 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6450 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6451 MatCheckPreallocated(mat, 1); 6452 6453 if (mat->ops->zerorowslocal) { 6454 PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b); 6455 } else { 6456 IS is, newis; 6457 const PetscInt *newRows; 6458 6459 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6460 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6461 PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis)); 6462 PetscCall(ISGetIndices(newis, &newRows)); 6463 PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b); 6464 PetscCall(ISRestoreIndices(newis, &newRows)); 6465 PetscCall(ISDestroy(&newis)); 6466 PetscCall(ISDestroy(&is)); 6467 } 6468 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6469 PetscFunctionReturn(PETSC_SUCCESS); 6470 } 6471 6472 /*@ 6473 MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal) 6474 of a set of rows of a matrix; using local numbering of rows. 6475 6476 Collective 6477 6478 Input Parameters: 6479 + mat - the matrix 6480 . is - index set of rows to remove 6481 . diag - value put in all diagonals of eliminated rows 6482 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6483 - b - optional vector of right hand side, that will be adjusted by provided solution 6484 6485 Level: intermediate 6486 6487 Notes: 6488 Before calling `MatZeroRowsLocalIS()`, the user must first set the 6489 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6490 6491 See `MatZeroRows()` for details on how this routine operates. 6492 6493 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6494 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6495 @*/ 6496 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6497 { 6498 PetscInt numRows; 6499 const PetscInt *rows; 6500 6501 PetscFunctionBegin; 6502 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6503 PetscValidType(mat, 1); 6504 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6505 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6506 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6507 MatCheckPreallocated(mat, 1); 6508 6509 PetscCall(ISGetLocalSize(is, &numRows)); 6510 PetscCall(ISGetIndices(is, &rows)); 6511 PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b)); 6512 PetscCall(ISRestoreIndices(is, &rows)); 6513 PetscFunctionReturn(PETSC_SUCCESS); 6514 } 6515 6516 /*@ 6517 MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal) 6518 of a set of rows and columns of a matrix; using local numbering of rows. 6519 6520 Collective 6521 6522 Input Parameters: 6523 + mat - the matrix 6524 . numRows - the number of rows to remove 6525 . rows - the global row indices 6526 . diag - value put in all diagonals of eliminated rows 6527 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6528 - b - optional vector of right hand side, that will be adjusted by provided solution 6529 6530 Level: intermediate 6531 6532 Notes: 6533 Before calling `MatZeroRowsColumnsLocal()`, the user must first set the 6534 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6535 6536 See `MatZeroRowsColumns()` for details on how this routine operates. 6537 6538 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6539 `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6540 @*/ 6541 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6542 { 6543 IS is, newis; 6544 const PetscInt *newRows; 6545 6546 PetscFunctionBegin; 6547 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6548 PetscValidType(mat, 1); 6549 if (numRows) PetscValidIntPointer(rows, 3); 6550 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6551 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6552 MatCheckPreallocated(mat, 1); 6553 6554 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6555 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6556 PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis)); 6557 PetscCall(ISGetIndices(newis, &newRows)); 6558 PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b); 6559 PetscCall(ISRestoreIndices(newis, &newRows)); 6560 PetscCall(ISDestroy(&newis)); 6561 PetscCall(ISDestroy(&is)); 6562 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6563 PetscFunctionReturn(PETSC_SUCCESS); 6564 } 6565 6566 /*@ 6567 MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal) 6568 of a set of rows and columns of a matrix; using local numbering of rows. 6569 6570 Collective 6571 6572 Input Parameters: 6573 + mat - the matrix 6574 . is - index set of rows to remove 6575 . diag - value put in all diagonals of eliminated rows 6576 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6577 - b - optional vector of right hand side, that will be adjusted by provided solution 6578 6579 Level: intermediate 6580 6581 Notes: 6582 Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the 6583 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6584 6585 See `MatZeroRowsColumns()` for details on how this routine operates. 6586 6587 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6588 `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6589 @*/ 6590 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6591 { 6592 PetscInt numRows; 6593 const PetscInt *rows; 6594 6595 PetscFunctionBegin; 6596 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6597 PetscValidType(mat, 1); 6598 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6599 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6600 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6601 MatCheckPreallocated(mat, 1); 6602 6603 PetscCall(ISGetLocalSize(is, &numRows)); 6604 PetscCall(ISGetIndices(is, &rows)); 6605 PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b)); 6606 PetscCall(ISRestoreIndices(is, &rows)); 6607 PetscFunctionReturn(PETSC_SUCCESS); 6608 } 6609 6610 /*@C 6611 MatGetSize - Returns the numbers of rows and columns in a matrix. 6612 6613 Not Collective 6614 6615 Input Parameter: 6616 . mat - the matrix 6617 6618 Output Parameters: 6619 + m - the number of global rows 6620 - n - the number of global columns 6621 6622 Level: beginner 6623 6624 Note: 6625 Both output parameters can be `NULL` on input. 6626 6627 .seealso: [](chapter_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()` 6628 @*/ 6629 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n) 6630 { 6631 PetscFunctionBegin; 6632 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6633 if (m) *m = mat->rmap->N; 6634 if (n) *n = mat->cmap->N; 6635 PetscFunctionReturn(PETSC_SUCCESS); 6636 } 6637 6638 /*@C 6639 MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns 6640 of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`. 6641 6642 Not Collective 6643 6644 Input Parameter: 6645 . mat - the matrix 6646 6647 Output Parameters: 6648 + m - the number of local rows, use `NULL` to not obtain this value 6649 - n - the number of local columns, use `NULL` to not obtain this value 6650 6651 Level: beginner 6652 6653 .seealso: [](chapter_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()` 6654 @*/ 6655 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n) 6656 { 6657 PetscFunctionBegin; 6658 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6659 if (m) PetscValidIntPointer(m, 2); 6660 if (n) PetscValidIntPointer(n, 3); 6661 if (m) *m = mat->rmap->n; 6662 if (n) *n = mat->cmap->n; 6663 PetscFunctionReturn(PETSC_SUCCESS); 6664 } 6665 6666 /*@C 6667 MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by 6668 this processor. (The columns of the "diagonal block" for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts. 6669 6670 Not Collective, unless matrix has not been allocated, then collective 6671 6672 Input Parameter: 6673 . mat - the matrix 6674 6675 Output Parameters: 6676 + m - the global index of the first local column, use `NULL` to not obtain this value 6677 - n - one more than the global index of the last local column, use `NULL` to not obtain this value 6678 6679 Level: developer 6680 6681 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout` 6682 @*/ 6683 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n) 6684 { 6685 PetscFunctionBegin; 6686 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6687 PetscValidType(mat, 1); 6688 if (m) PetscValidIntPointer(m, 2); 6689 if (n) PetscValidIntPointer(n, 3); 6690 MatCheckPreallocated(mat, 1); 6691 if (m) *m = mat->cmap->rstart; 6692 if (n) *n = mat->cmap->rend; 6693 PetscFunctionReturn(PETSC_SUCCESS); 6694 } 6695 6696 /*@C 6697 MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6698 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 6699 vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts 6700 6701 Not Collective 6702 6703 Input Parameter: 6704 . mat - the matrix 6705 6706 Output Parameters: 6707 + m - the global index of the first local row, use `NULL` to not obtain this value 6708 - n - one more than the global index of the last local row, use `NULL` to not obtain this value 6709 6710 Level: beginner 6711 6712 Note: 6713 This function requires that the matrix be preallocated. If you have not preallocated, consider using 6714 `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N) 6715 and then `MPI_Scan()` to calculate prefix sums of the local sizes. 6716 6717 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, 6718 `PetscLayout` 6719 @*/ 6720 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n) 6721 { 6722 PetscFunctionBegin; 6723 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6724 PetscValidType(mat, 1); 6725 if (m) PetscValidIntPointer(m, 2); 6726 if (n) PetscValidIntPointer(n, 3); 6727 MatCheckPreallocated(mat, 1); 6728 if (m) *m = mat->rmap->rstart; 6729 if (n) *n = mat->rmap->rend; 6730 PetscFunctionReturn(PETSC_SUCCESS); 6731 } 6732 6733 /*@C 6734 MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6735 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 6736 vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts 6737 6738 Not Collective, unless matrix has not been allocated 6739 6740 Input Parameter: 6741 . mat - the matrix 6742 6743 Output Parameter: 6744 . ranges - start of each processors portion plus one more than the total length at the end 6745 6746 Level: beginner 6747 6748 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout` 6749 @*/ 6750 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges) 6751 { 6752 PetscFunctionBegin; 6753 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6754 PetscValidType(mat, 1); 6755 MatCheckPreallocated(mat, 1); 6756 PetscCall(PetscLayoutGetRanges(mat->rmap, ranges)); 6757 PetscFunctionReturn(PETSC_SUCCESS); 6758 } 6759 6760 /*@C 6761 MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by 6762 each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts. 6763 6764 Not Collective, unless matrix has not been allocated 6765 6766 Input Parameter: 6767 . mat - the matrix 6768 6769 Output Parameter: 6770 . ranges - start of each processors portion plus one more then the total length at the end 6771 6772 Level: beginner 6773 6774 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()` 6775 @*/ 6776 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges) 6777 { 6778 PetscFunctionBegin; 6779 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6780 PetscValidType(mat, 1); 6781 MatCheckPreallocated(mat, 1); 6782 PetscCall(PetscLayoutGetRanges(mat->cmap, ranges)); 6783 PetscFunctionReturn(PETSC_SUCCESS); 6784 } 6785 6786 /*@C 6787 MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this 6788 corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership 6789 is more complicated. See :any:`<sec_matlayout>` for details on matrix layouts. 6790 6791 Not Collective 6792 6793 Input Parameter: 6794 . A - matrix 6795 6796 Output Parameters: 6797 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value 6798 - cols - columns in which this process owns elements, use `NULL` to not obtain this value 6799 6800 Level: intermediate 6801 6802 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK`` 6803 @*/ 6804 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols) 6805 { 6806 PetscErrorCode (*f)(Mat, IS *, IS *); 6807 6808 PetscFunctionBegin; 6809 MatCheckPreallocated(A, 1); 6810 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f)); 6811 if (f) { 6812 PetscCall((*f)(A, rows, cols)); 6813 } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */ 6814 if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows)); 6815 if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols)); 6816 } 6817 PetscFunctionReturn(PETSC_SUCCESS); 6818 } 6819 6820 /*@C 6821 MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()` 6822 Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()` 6823 to complete the factorization. 6824 6825 Collective 6826 6827 Input Parameters: 6828 + fact - the factorized matrix obtained with `MatGetFactor()` 6829 . mat - the matrix 6830 . row - row permutation 6831 . col - column permutation 6832 - info - structure containing 6833 .vb 6834 levels - number of levels of fill. 6835 expected fill - as ratio of original fill. 6836 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 6837 missing diagonal entries) 6838 .ve 6839 6840 Level: developer 6841 6842 Notes: 6843 See [Matrix Factorization](sec_matfactor) for additional information. 6844 6845 Most users should employ the `KSP` interface for linear solvers 6846 instead of working directly with matrix algebra routines such as this. 6847 See, e.g., `KSPCreate()`. 6848 6849 Uses the definition of level of fill as in Y. Saad, 2003 6850 6851 Developer Note: 6852 The Fortran interface is not autogenerated as the 6853 interface definition cannot be generated correctly [due to `MatFactorInfo`] 6854 6855 References: 6856 . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003 6857 6858 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 6859 `MatGetOrdering()`, `MatFactorInfo` 6860 @*/ 6861 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 6862 { 6863 PetscFunctionBegin; 6864 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 6865 PetscValidType(mat, 2); 6866 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 6867 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 6868 PetscValidPointer(info, 5); 6869 PetscValidPointer(fact, 1); 6870 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels); 6871 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 6872 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6873 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6874 MatCheckPreallocated(mat, 2); 6875 6876 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0)); 6877 PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info); 6878 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0)); 6879 PetscFunctionReturn(PETSC_SUCCESS); 6880 } 6881 6882 /*@C 6883 MatICCFactorSymbolic - Performs symbolic incomplete 6884 Cholesky factorization for a symmetric matrix. Use 6885 `MatCholeskyFactorNumeric()` to complete the factorization. 6886 6887 Collective 6888 6889 Input Parameters: 6890 + fact - the factorized matrix obtained with `MatGetFactor()` 6891 . mat - the matrix to be factored 6892 . perm - row and column permutation 6893 - info - structure containing 6894 .vb 6895 levels - number of levels of fill. 6896 expected fill - as ratio of original fill. 6897 .ve 6898 6899 Level: developer 6900 6901 Notes: 6902 Most users should employ the `KSP` interface for linear solvers 6903 instead of working directly with matrix algebra routines such as this. 6904 See, e.g., `KSPCreate()`. 6905 6906 This uses the definition of level of fill as in Y. Saad, 2003 6907 6908 Developer Note: 6909 The Fortran interface is not autogenerated as the 6910 interface definition cannot be generated correctly [due to `MatFactorInfo`] 6911 6912 References: 6913 . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003 6914 6915 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 6916 @*/ 6917 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 6918 { 6919 PetscFunctionBegin; 6920 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 6921 PetscValidType(mat, 2); 6922 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 6923 PetscValidPointer(info, 4); 6924 PetscValidPointer(fact, 1); 6925 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6926 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels); 6927 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 6928 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6929 MatCheckPreallocated(mat, 2); 6930 6931 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 6932 PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info); 6933 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 6934 PetscFunctionReturn(PETSC_SUCCESS); 6935 } 6936 6937 /*@C 6938 MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat 6939 points to an array of valid matrices, they may be reused to store the new 6940 submatrices. 6941 6942 Collective 6943 6944 Input Parameters: 6945 + mat - the matrix 6946 . n - the number of submatrixes to be extracted (on this processor, may be zero) 6947 . irow - index set of rows to extract 6948 . icol - index set of columns to extract 6949 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 6950 6951 Output Parameter: 6952 . submat - the array of submatrices 6953 6954 Level: advanced 6955 6956 Notes: 6957 `MatCreateSubMatrices()` can extract ONLY sequential submatrices 6958 (from both sequential and parallel matrices). Use `MatCreateSubMatrix()` 6959 to extract a parallel submatrix. 6960 6961 Some matrix types place restrictions on the row and column 6962 indices, such as that they be sorted or that they be equal to each other. 6963 6964 The index sets may not have duplicate entries. 6965 6966 When extracting submatrices from a parallel matrix, each processor can 6967 form a different submatrix by setting the rows and columns of its 6968 individual index sets according to the local submatrix desired. 6969 6970 When finished using the submatrices, the user should destroy 6971 them with `MatDestroySubMatrices()`. 6972 6973 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 6974 original matrix has not changed from that last call to `MatCreateSubMatrices()`. 6975 6976 This routine creates the matrices in submat; you should NOT create them before 6977 calling it. It also allocates the array of matrix pointers submat. 6978 6979 For `MATBAIJ` matrices the index sets must respect the block structure, that is if they 6980 request one row/column in a block, they must request all rows/columns that are in 6981 that block. For example, if the block size is 2 you cannot request just row 0 and 6982 column 0. 6983 6984 Fortran Note: 6985 The Fortran interface is slightly different from that given below; it 6986 requires one to pass in as `submat` a `Mat` (integer) array of size at least n+1. 6987 6988 .seealso: [](chapter_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 6989 @*/ 6990 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 6991 { 6992 PetscInt i; 6993 PetscBool eq; 6994 6995 PetscFunctionBegin; 6996 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6997 PetscValidType(mat, 1); 6998 if (n) { 6999 PetscValidPointer(irow, 3); 7000 for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3); 7001 PetscValidPointer(icol, 4); 7002 for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4); 7003 } 7004 PetscValidPointer(submat, 6); 7005 if (n && scall == MAT_REUSE_MATRIX) { 7006 PetscValidPointer(*submat, 6); 7007 for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6); 7008 } 7009 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7010 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7011 MatCheckPreallocated(mat, 1); 7012 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7013 PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat); 7014 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7015 for (i = 0; i < n; i++) { 7016 (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */ 7017 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7018 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7019 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 7020 if (mat->boundtocpu && mat->bindingpropagates) { 7021 PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE)); 7022 PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE)); 7023 } 7024 #endif 7025 } 7026 PetscFunctionReturn(PETSC_SUCCESS); 7027 } 7028 7029 /*@C 7030 MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms). 7031 7032 Collective 7033 7034 Input Parameters: 7035 + mat - the matrix 7036 . n - the number of submatrixes to be extracted 7037 . irow - index set of rows to extract 7038 . icol - index set of columns to extract 7039 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7040 7041 Output Parameter: 7042 . submat - the array of submatrices 7043 7044 Level: advanced 7045 7046 Note: 7047 This is used by `PCGASM` 7048 7049 .seealso: [](chapter_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7050 @*/ 7051 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7052 { 7053 PetscInt i; 7054 PetscBool eq; 7055 7056 PetscFunctionBegin; 7057 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7058 PetscValidType(mat, 1); 7059 if (n) { 7060 PetscValidPointer(irow, 3); 7061 PetscValidHeaderSpecific(*irow, IS_CLASSID, 3); 7062 PetscValidPointer(icol, 4); 7063 PetscValidHeaderSpecific(*icol, IS_CLASSID, 4); 7064 } 7065 PetscValidPointer(submat, 6); 7066 if (n && scall == MAT_REUSE_MATRIX) { 7067 PetscValidPointer(*submat, 6); 7068 PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6); 7069 } 7070 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7071 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7072 MatCheckPreallocated(mat, 1); 7073 7074 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7075 PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat); 7076 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7077 for (i = 0; i < n; i++) { 7078 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7079 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7080 } 7081 PetscFunctionReturn(PETSC_SUCCESS); 7082 } 7083 7084 /*@C 7085 MatDestroyMatrices - Destroys an array of matrices. 7086 7087 Collective 7088 7089 Input Parameters: 7090 + n - the number of local matrices 7091 - mat - the matrices (this is a pointer to the array of matrices) 7092 7093 Level: advanced 7094 7095 Note: 7096 Frees not only the matrices, but also the array that contains the matrices 7097 7098 Fortran Note: 7099 This does not free the array. 7100 7101 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()` 7102 @*/ 7103 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[]) 7104 { 7105 PetscInt i; 7106 7107 PetscFunctionBegin; 7108 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7109 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7110 PetscValidPointer(mat, 2); 7111 7112 for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i])); 7113 7114 /* memory is allocated even if n = 0 */ 7115 PetscCall(PetscFree(*mat)); 7116 PetscFunctionReturn(PETSC_SUCCESS); 7117 } 7118 7119 /*@C 7120 MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`. 7121 7122 Collective 7123 7124 Input Parameters: 7125 + n - the number of local matrices 7126 - mat - the matrices (this is a pointer to the array of matrices, just to match the calling 7127 sequence of `MatCreateSubMatrices()`) 7128 7129 Level: advanced 7130 7131 Note: 7132 Frees not only the matrices, but also the array that contains the matrices 7133 7134 Fortran Note: 7135 This does not free the array. 7136 7137 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7138 @*/ 7139 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[]) 7140 { 7141 Mat mat0; 7142 7143 PetscFunctionBegin; 7144 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7145 /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */ 7146 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7147 PetscValidPointer(mat, 2); 7148 7149 mat0 = (*mat)[0]; 7150 if (mat0 && mat0->ops->destroysubmatrices) { 7151 PetscCall((*mat0->ops->destroysubmatrices)(n, mat)); 7152 } else { 7153 PetscCall(MatDestroyMatrices(n, mat)); 7154 } 7155 PetscFunctionReturn(PETSC_SUCCESS); 7156 } 7157 7158 /*@C 7159 MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process 7160 7161 Collective 7162 7163 Input Parameter: 7164 . mat - the matrix 7165 7166 Output Parameter: 7167 . matstruct - the sequential matrix with the nonzero structure of mat 7168 7169 Level: developer 7170 7171 .seealso: [](chapter_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7172 @*/ 7173 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct) 7174 { 7175 PetscFunctionBegin; 7176 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7177 PetscValidPointer(matstruct, 2); 7178 7179 PetscValidType(mat, 1); 7180 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7181 MatCheckPreallocated(mat, 1); 7182 7183 PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7184 PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct); 7185 PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7186 PetscFunctionReturn(PETSC_SUCCESS); 7187 } 7188 7189 /*@C 7190 MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`. 7191 7192 Collective 7193 7194 Input Parameter: 7195 . mat - the matrix (this is a pointer to the array of matrices, just to match the calling 7196 sequence of `MatGetSeqNonzeroStructure()`) 7197 7198 Level: advanced 7199 7200 Note: 7201 Frees not only the matrices, but also the array that contains the matrices 7202 7203 .seealso: [](chapter_matrices), `Mat`, `MatGetSeqNonzeroStructure()` 7204 @*/ 7205 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat) 7206 { 7207 PetscFunctionBegin; 7208 PetscValidPointer(mat, 1); 7209 PetscCall(MatDestroy(mat)); 7210 PetscFunctionReturn(PETSC_SUCCESS); 7211 } 7212 7213 /*@ 7214 MatIncreaseOverlap - Given a set of submatrices indicated by index sets, 7215 replaces the index sets by larger ones that represent submatrices with 7216 additional overlap. 7217 7218 Collective 7219 7220 Input Parameters: 7221 + mat - the matrix 7222 . n - the number of index sets 7223 . is - the array of index sets (these index sets will changed during the call) 7224 - ov - the additional overlap requested 7225 7226 Options Database Key: 7227 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7228 7229 Level: developer 7230 7231 Note: 7232 The computed overlap preserves the matrix block sizes when the blocks are square. 7233 That is: if a matrix nonzero for a given block would increase the overlap all columns associated with 7234 that block are included in the overlap regardless of whether each specific column would increase the overlap. 7235 7236 .seealso: [](chapter_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()` 7237 @*/ 7238 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov) 7239 { 7240 PetscInt i, bs, cbs; 7241 7242 PetscFunctionBegin; 7243 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7244 PetscValidType(mat, 1); 7245 PetscValidLogicalCollectiveInt(mat, n, 2); 7246 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7247 if (n) { 7248 PetscValidPointer(is, 3); 7249 for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3); 7250 } 7251 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7252 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7253 MatCheckPreallocated(mat, 1); 7254 7255 if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS); 7256 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7257 PetscUseTypeMethod(mat, increaseoverlap, n, is, ov); 7258 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7259 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 7260 if (bs == cbs) { 7261 for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs)); 7262 } 7263 PetscFunctionReturn(PETSC_SUCCESS); 7264 } 7265 7266 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt); 7267 7268 /*@ 7269 MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across 7270 a sub communicator, replaces the index sets by larger ones that represent submatrices with 7271 additional overlap. 7272 7273 Collective 7274 7275 Input Parameters: 7276 + mat - the matrix 7277 . n - the number of index sets 7278 . is - the array of index sets (these index sets will changed during the call) 7279 - ov - the additional overlap requested 7280 7281 ` Options Database Key: 7282 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7283 7284 Level: developer 7285 7286 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()` 7287 @*/ 7288 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov) 7289 { 7290 PetscInt i; 7291 7292 PetscFunctionBegin; 7293 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7294 PetscValidType(mat, 1); 7295 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7296 if (n) { 7297 PetscValidPointer(is, 3); 7298 PetscValidHeaderSpecific(*is, IS_CLASSID, 3); 7299 } 7300 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7301 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7302 MatCheckPreallocated(mat, 1); 7303 if (!ov) PetscFunctionReturn(PETSC_SUCCESS); 7304 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7305 for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov)); 7306 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7307 PetscFunctionReturn(PETSC_SUCCESS); 7308 } 7309 7310 /*@ 7311 MatGetBlockSize - Returns the matrix block size. 7312 7313 Not Collective 7314 7315 Input Parameter: 7316 . mat - the matrix 7317 7318 Output Parameter: 7319 . bs - block size 7320 7321 Level: intermediate 7322 7323 Notes: 7324 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7325 7326 If the block size has not been set yet this routine returns 1. 7327 7328 .seealso: [](chapter_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()` 7329 @*/ 7330 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs) 7331 { 7332 PetscFunctionBegin; 7333 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7334 PetscValidIntPointer(bs, 2); 7335 *bs = PetscAbs(mat->rmap->bs); 7336 PetscFunctionReturn(PETSC_SUCCESS); 7337 } 7338 7339 /*@ 7340 MatGetBlockSizes - Returns the matrix block row and column sizes. 7341 7342 Not Collective 7343 7344 Input Parameter: 7345 . mat - the matrix 7346 7347 Output Parameters: 7348 + rbs - row block size 7349 - cbs - column block size 7350 7351 Level: intermediate 7352 7353 Notes: 7354 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7355 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7356 7357 If a block size has not been set yet this routine returns 1. 7358 7359 .seealso: [](chapter_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()` 7360 @*/ 7361 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs) 7362 { 7363 PetscFunctionBegin; 7364 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7365 if (rbs) PetscValidIntPointer(rbs, 2); 7366 if (cbs) PetscValidIntPointer(cbs, 3); 7367 if (rbs) *rbs = PetscAbs(mat->rmap->bs); 7368 if (cbs) *cbs = PetscAbs(mat->cmap->bs); 7369 PetscFunctionReturn(PETSC_SUCCESS); 7370 } 7371 7372 /*@ 7373 MatSetBlockSize - Sets the matrix block size. 7374 7375 Logically Collective 7376 7377 Input Parameters: 7378 + mat - the matrix 7379 - bs - block size 7380 7381 Level: intermediate 7382 7383 Notes: 7384 Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix. 7385 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7386 7387 For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size 7388 is compatible with the matrix local sizes. 7389 7390 .seealso: [](chapter_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()` 7391 @*/ 7392 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs) 7393 { 7394 PetscFunctionBegin; 7395 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7396 PetscValidLogicalCollectiveInt(mat, bs, 2); 7397 PetscCall(MatSetBlockSizes(mat, bs, bs)); 7398 PetscFunctionReturn(PETSC_SUCCESS); 7399 } 7400 7401 typedef struct { 7402 PetscInt n; 7403 IS *is; 7404 Mat *mat; 7405 PetscObjectState nonzerostate; 7406 Mat C; 7407 } EnvelopeData; 7408 7409 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata) 7410 { 7411 for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i])); 7412 PetscCall(PetscFree(edata->is)); 7413 PetscCall(PetscFree(edata)); 7414 return PETSC_SUCCESS; 7415 } 7416 7417 /* 7418 MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores 7419 the sizes of these blocks in the matrix. An individual block may lie over several processes. 7420 7421 Collective 7422 7423 Input Parameter: 7424 . mat - the matrix 7425 7426 Notes: 7427 There can be zeros within the blocks 7428 7429 The blocks can overlap between processes, including laying on more than two processes 7430 7431 .seealso: [](chapter_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()` 7432 */ 7433 static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat) 7434 { 7435 PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend; 7436 PetscInt *diag, *odiag, sc; 7437 VecScatter scatter; 7438 PetscScalar *seqv; 7439 const PetscScalar *parv; 7440 const PetscInt *ia, *ja; 7441 PetscBool set, flag, done; 7442 Mat AA = mat, A; 7443 MPI_Comm comm; 7444 PetscMPIInt rank, size, tag; 7445 MPI_Status status; 7446 PetscContainer container; 7447 EnvelopeData *edata; 7448 Vec seq, par; 7449 IS isglobal; 7450 7451 PetscFunctionBegin; 7452 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7453 PetscCall(MatIsSymmetricKnown(mat, &set, &flag)); 7454 if (!set || !flag) { 7455 /* TOO: only needs nonzero structure of transpose */ 7456 PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA)); 7457 PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN)); 7458 } 7459 PetscCall(MatAIJGetLocalMat(AA, &A)); 7460 PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7461 PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix"); 7462 7463 PetscCall(MatGetLocalSize(mat, &n, NULL)); 7464 PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag)); 7465 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 7466 PetscCallMPI(MPI_Comm_size(comm, &size)); 7467 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7468 7469 PetscCall(PetscMalloc2(n, &sizes, n, &starts)); 7470 7471 if (rank > 0) { 7472 PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7473 PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7474 } 7475 PetscCall(MatGetOwnershipRange(mat, &rstart, NULL)); 7476 for (i = 0; i < n; i++) { 7477 env = PetscMax(env, ja[ia[i + 1] - 1]); 7478 II = rstart + i; 7479 if (env == II) { 7480 starts[lblocks] = tbs; 7481 sizes[lblocks++] = 1 + II - tbs; 7482 tbs = 1 + II; 7483 } 7484 } 7485 if (rank < size - 1) { 7486 PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm)); 7487 PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm)); 7488 } 7489 7490 PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7491 if (!set || !flag) PetscCall(MatDestroy(&AA)); 7492 PetscCall(MatDestroy(&A)); 7493 7494 PetscCall(PetscNew(&edata)); 7495 PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate)); 7496 edata->n = lblocks; 7497 /* create IS needed for extracting blocks from the original matrix */ 7498 PetscCall(PetscMalloc1(lblocks, &edata->is)); 7499 for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i])); 7500 7501 /* Create the resulting inverse matrix structure with preallocation information */ 7502 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C)); 7503 PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 7504 PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat)); 7505 PetscCall(MatSetType(edata->C, MATAIJ)); 7506 7507 /* Communicate the start and end of each row, from each block to the correct rank */ 7508 /* TODO: Use PetscSF instead of VecScatter */ 7509 for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i]; 7510 PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq)); 7511 PetscCall(VecGetArrayWrite(seq, &seqv)); 7512 for (PetscInt i = 0; i < lblocks; i++) { 7513 for (PetscInt j = 0; j < sizes[i]; j++) { 7514 seqv[cnt] = starts[i]; 7515 seqv[cnt + 1] = starts[i] + sizes[i]; 7516 cnt += 2; 7517 } 7518 } 7519 PetscCall(VecRestoreArrayWrite(seq, &seqv)); 7520 PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 7521 sc -= cnt; 7522 PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par)); 7523 PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal)); 7524 PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter)); 7525 PetscCall(ISDestroy(&isglobal)); 7526 PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7527 PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7528 PetscCall(VecScatterDestroy(&scatter)); 7529 PetscCall(VecDestroy(&seq)); 7530 PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend)); 7531 PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag)); 7532 PetscCall(VecGetArrayRead(par, &parv)); 7533 cnt = 0; 7534 PetscCall(MatGetSize(mat, NULL, &n)); 7535 for (PetscInt i = 0; i < mat->rmap->n; i++) { 7536 PetscInt start, end, d = 0, od = 0; 7537 7538 start = (PetscInt)PetscRealPart(parv[cnt]); 7539 end = (PetscInt)PetscRealPart(parv[cnt + 1]); 7540 cnt += 2; 7541 7542 if (start < cstart) { 7543 od += cstart - start + n - cend; 7544 d += cend - cstart; 7545 } else if (start < cend) { 7546 od += n - cend; 7547 d += cend - start; 7548 } else od += n - start; 7549 if (end <= cstart) { 7550 od -= cstart - end + n - cend; 7551 d -= cend - cstart; 7552 } else if (end < cend) { 7553 od -= n - cend; 7554 d -= cend - end; 7555 } else od -= n - end; 7556 7557 odiag[i] = od; 7558 diag[i] = d; 7559 } 7560 PetscCall(VecRestoreArrayRead(par, &parv)); 7561 PetscCall(VecDestroy(&par)); 7562 PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL)); 7563 PetscCall(PetscFree2(diag, odiag)); 7564 PetscCall(PetscFree2(sizes, starts)); 7565 7566 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container)); 7567 PetscCall(PetscContainerSetPointer(container, edata)); 7568 PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy)); 7569 PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container)); 7570 PetscCall(PetscObjectDereference((PetscObject)container)); 7571 PetscFunctionReturn(PETSC_SUCCESS); 7572 } 7573 7574 /*@ 7575 MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A 7576 7577 Collective 7578 7579 Input Parameters: 7580 + A - the matrix 7581 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine 7582 7583 Output Parameter: 7584 . C - matrix with inverted block diagonal of `A` 7585 7586 Level: advanced 7587 7588 Note: 7589 For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal. 7590 7591 .seealso: [](chapter_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()` 7592 @*/ 7593 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C) 7594 { 7595 PetscContainer container; 7596 EnvelopeData *edata; 7597 PetscObjectState nonzerostate; 7598 7599 PetscFunctionBegin; 7600 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7601 if (!container) { 7602 PetscCall(MatComputeVariableBlockEnvelope(A)); 7603 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7604 } 7605 PetscCall(PetscContainerGetPointer(container, (void **)&edata)); 7606 PetscCall(MatGetNonzeroState(A, &nonzerostate)); 7607 PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure"); 7608 PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output"); 7609 7610 PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat)); 7611 *C = edata->C; 7612 7613 for (PetscInt i = 0; i < edata->n; i++) { 7614 Mat D; 7615 PetscScalar *dvalues; 7616 7617 PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D)); 7618 PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE)); 7619 PetscCall(MatSeqDenseInvert(D)); 7620 PetscCall(MatDenseGetArray(D, &dvalues)); 7621 PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES)); 7622 PetscCall(MatDestroy(&D)); 7623 } 7624 PetscCall(MatDestroySubMatrices(edata->n, &edata->mat)); 7625 PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY)); 7626 PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY)); 7627 PetscFunctionReturn(PETSC_SUCCESS); 7628 } 7629 7630 /*@ 7631 MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size 7632 7633 Logically Collective 7634 7635 Input Parameters: 7636 + mat - the matrix 7637 . nblocks - the number of blocks on this process, each block can only exist on a single process 7638 - bsizes - the block sizes 7639 7640 Level: intermediate 7641 7642 Notes: 7643 Currently used by `PCVPBJACOBI` for `MATAIJ` matrices 7644 7645 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. 7646 7647 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, 7648 `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI` 7649 @*/ 7650 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes) 7651 { 7652 PetscInt i, ncnt = 0, nlocal; 7653 7654 PetscFunctionBegin; 7655 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7656 PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero"); 7657 PetscCall(MatGetLocalSize(mat, &nlocal, NULL)); 7658 for (i = 0; i < nblocks; i++) ncnt += bsizes[i]; 7659 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); 7660 PetscCall(PetscFree(mat->bsizes)); 7661 mat->nblocks = nblocks; 7662 PetscCall(PetscMalloc1(nblocks, &mat->bsizes)); 7663 PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks)); 7664 PetscFunctionReturn(PETSC_SUCCESS); 7665 } 7666 7667 /*@C 7668 MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size 7669 7670 Logically Collective; No Fortran Support 7671 7672 Input Parameter: 7673 . mat - the matrix 7674 7675 Output Parameters: 7676 + nblocks - the number of blocks on this process 7677 - bsizes - the block sizes 7678 7679 Level: intermediate 7680 7681 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()` 7682 @*/ 7683 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes) 7684 { 7685 PetscFunctionBegin; 7686 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7687 *nblocks = mat->nblocks; 7688 *bsizes = mat->bsizes; 7689 PetscFunctionReturn(PETSC_SUCCESS); 7690 } 7691 7692 /*@ 7693 MatSetBlockSizes - Sets the matrix block row and column sizes. 7694 7695 Logically Collective 7696 7697 Input Parameters: 7698 + mat - the matrix 7699 . rbs - row block size 7700 - cbs - column block size 7701 7702 Level: intermediate 7703 7704 Notes: 7705 Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix. 7706 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7707 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7708 7709 For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes 7710 are compatible with the matrix local sizes. 7711 7712 The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`. 7713 7714 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()` 7715 @*/ 7716 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs) 7717 { 7718 PetscFunctionBegin; 7719 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7720 PetscValidLogicalCollectiveInt(mat, rbs, 2); 7721 PetscValidLogicalCollectiveInt(mat, cbs, 3); 7722 PetscTryTypeMethod(mat, setblocksizes, rbs, cbs); 7723 if (mat->rmap->refcnt) { 7724 ISLocalToGlobalMapping l2g = NULL; 7725 PetscLayout nmap = NULL; 7726 7727 PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap)); 7728 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g)); 7729 PetscCall(PetscLayoutDestroy(&mat->rmap)); 7730 mat->rmap = nmap; 7731 mat->rmap->mapping = l2g; 7732 } 7733 if (mat->cmap->refcnt) { 7734 ISLocalToGlobalMapping l2g = NULL; 7735 PetscLayout nmap = NULL; 7736 7737 PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap)); 7738 if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g)); 7739 PetscCall(PetscLayoutDestroy(&mat->cmap)); 7740 mat->cmap = nmap; 7741 mat->cmap->mapping = l2g; 7742 } 7743 PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs)); 7744 PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs)); 7745 PetscFunctionReturn(PETSC_SUCCESS); 7746 } 7747 7748 /*@ 7749 MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices 7750 7751 Logically Collective 7752 7753 Input Parameters: 7754 + mat - the matrix 7755 . fromRow - matrix from which to copy row block size 7756 - fromCol - matrix from which to copy column block size (can be same as fromRow) 7757 7758 Level: developer 7759 7760 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()` 7761 @*/ 7762 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol) 7763 { 7764 PetscFunctionBegin; 7765 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7766 PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2); 7767 PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3); 7768 if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs)); 7769 if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs)); 7770 PetscFunctionReturn(PETSC_SUCCESS); 7771 } 7772 7773 /*@ 7774 MatResidual - Default routine to calculate the residual r = b - Ax 7775 7776 Collective 7777 7778 Input Parameters: 7779 + mat - the matrix 7780 . b - the right-hand-side 7781 - x - the approximate solution 7782 7783 Output Parameter: 7784 . r - location to store the residual 7785 7786 Level: developer 7787 7788 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()` 7789 @*/ 7790 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r) 7791 { 7792 PetscFunctionBegin; 7793 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7794 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 7795 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 7796 PetscValidHeaderSpecific(r, VEC_CLASSID, 4); 7797 PetscValidType(mat, 1); 7798 MatCheckPreallocated(mat, 1); 7799 PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0)); 7800 if (!mat->ops->residual) { 7801 PetscCall(MatMult(mat, x, r)); 7802 PetscCall(VecAYPX(r, -1.0, b)); 7803 } else { 7804 PetscUseTypeMethod(mat, residual, b, x, r); 7805 } 7806 PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0)); 7807 PetscFunctionReturn(PETSC_SUCCESS); 7808 } 7809 7810 /*MC 7811 MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix 7812 7813 Synopsis: 7814 MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 7815 7816 Not Collective 7817 7818 Input Parameters: 7819 + A - the matrix 7820 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7821 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7822 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7823 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7824 always used. 7825 7826 Output Parameters: 7827 + n - number of local rows in the (possibly compressed) matrix 7828 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 7829 . ja - the column indices 7830 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7831 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7832 7833 Level: developer 7834 7835 Note: 7836 Use `MatRestoreRowIJF90()` when you no longer need access to the data 7837 7838 .seealso: [](chapter_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()` 7839 M*/ 7840 7841 /*MC 7842 MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()` 7843 7844 Synopsis: 7845 MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 7846 7847 Not Collective 7848 7849 Input Parameters: 7850 + A - the matrix 7851 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7852 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7853 inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7854 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7855 always used. 7856 . n - number of local rows in the (possibly compressed) matrix 7857 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 7858 . ja - the column indices 7859 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7860 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7861 7862 Level: developer 7863 7864 .seealso: [](chapter_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()` 7865 M*/ 7866 7867 /*@C 7868 MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix 7869 7870 Collective 7871 7872 Input Parameters: 7873 + mat - the matrix 7874 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7875 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7876 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7877 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7878 always used. 7879 7880 Output Parameters: 7881 + n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed 7882 . 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 7883 . ja - the column indices, use `NULL` if not needed 7884 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7885 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7886 7887 Level: developer 7888 7889 Notes: 7890 You CANNOT change any of the ia[] or ja[] values. 7891 7892 Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values. 7893 7894 Fortran Notes: 7895 Use 7896 .vb 7897 PetscInt, pointer :: ia(:),ja(:) 7898 call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr) 7899 ! Access the ith and jth entries via ia(i) and ja(j) 7900 .ve 7901 `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()` 7902 7903 .seealso: [](chapter_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()` 7904 @*/ 7905 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7906 { 7907 PetscFunctionBegin; 7908 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7909 PetscValidType(mat, 1); 7910 if (n) PetscValidIntPointer(n, 5); 7911 if (ia) PetscValidPointer(ia, 6); 7912 if (ja) PetscValidPointer(ja, 7); 7913 if (done) PetscValidBoolPointer(done, 8); 7914 MatCheckPreallocated(mat, 1); 7915 if (!mat->ops->getrowij && done) *done = PETSC_FALSE; 7916 else { 7917 if (done) *done = PETSC_TRUE; 7918 PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0)); 7919 PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done); 7920 PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0)); 7921 } 7922 PetscFunctionReturn(PETSC_SUCCESS); 7923 } 7924 7925 /*@C 7926 MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices. 7927 7928 Collective 7929 7930 Input Parameters: 7931 + mat - the matrix 7932 . shift - 1 or zero indicating we want the indices starting at 0 or 1 7933 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be 7934 symmetrized 7935 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7936 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7937 always used. 7938 . n - number of columns in the (possibly compressed) matrix 7939 . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix 7940 - ja - the row indices 7941 7942 Output Parameter: 7943 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned 7944 7945 Level: developer 7946 7947 .seealso: [](chapter_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 7948 @*/ 7949 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7950 { 7951 PetscFunctionBegin; 7952 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7953 PetscValidType(mat, 1); 7954 PetscValidIntPointer(n, 5); 7955 if (ia) PetscValidPointer(ia, 6); 7956 if (ja) PetscValidPointer(ja, 7); 7957 PetscValidBoolPointer(done, 8); 7958 MatCheckPreallocated(mat, 1); 7959 if (!mat->ops->getcolumnij) *done = PETSC_FALSE; 7960 else { 7961 *done = PETSC_TRUE; 7962 PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 7963 } 7964 PetscFunctionReturn(PETSC_SUCCESS); 7965 } 7966 7967 /*@C 7968 MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`. 7969 7970 Collective 7971 7972 Input Parameters: 7973 + mat - the matrix 7974 . shift - 1 or zero indicating we want the indices starting at 0 or 1 7975 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7976 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7977 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7978 always used. 7979 . n - size of (possibly compressed) matrix 7980 . ia - the row pointers 7981 - ja - the column indices 7982 7983 Output Parameter: 7984 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 7985 7986 Level: developer 7987 7988 Note: 7989 This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental 7990 us of the array after it has been restored. If you pass `NULL`, it will 7991 not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid. 7992 7993 Fortran Note: 7994 `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()` 7995 7996 .seealso: [](chapter_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()` 7997 @*/ 7998 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7999 { 8000 PetscFunctionBegin; 8001 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8002 PetscValidType(mat, 1); 8003 if (ia) PetscValidPointer(ia, 6); 8004 if (ja) PetscValidPointer(ja, 7); 8005 if (done) PetscValidBoolPointer(done, 8); 8006 MatCheckPreallocated(mat, 1); 8007 8008 if (!mat->ops->restorerowij && done) *done = PETSC_FALSE; 8009 else { 8010 if (done) *done = PETSC_TRUE; 8011 PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8012 if (n) *n = 0; 8013 if (ia) *ia = NULL; 8014 if (ja) *ja = NULL; 8015 } 8016 PetscFunctionReturn(PETSC_SUCCESS); 8017 } 8018 8019 /*@C 8020 MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`. 8021 8022 Collective 8023 8024 Input Parameters: 8025 + mat - the matrix 8026 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8027 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8028 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8029 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8030 always used. 8031 8032 Output Parameters: 8033 + n - size of (possibly compressed) matrix 8034 . ia - the column pointers 8035 . ja - the row indices 8036 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8037 8038 Level: developer 8039 8040 .seealso: [](chapter_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()` 8041 @*/ 8042 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8043 { 8044 PetscFunctionBegin; 8045 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8046 PetscValidType(mat, 1); 8047 if (ia) PetscValidPointer(ia, 6); 8048 if (ja) PetscValidPointer(ja, 7); 8049 PetscValidBoolPointer(done, 8); 8050 MatCheckPreallocated(mat, 1); 8051 8052 if (!mat->ops->restorecolumnij) *done = PETSC_FALSE; 8053 else { 8054 *done = PETSC_TRUE; 8055 PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8056 if (n) *n = 0; 8057 if (ia) *ia = NULL; 8058 if (ja) *ja = NULL; 8059 } 8060 PetscFunctionReturn(PETSC_SUCCESS); 8061 } 8062 8063 /*@C 8064 MatColoringPatch -Used inside matrix coloring routines that use `MatGetRowIJ()` and/or `MatGetColumnIJ()`. 8065 8066 Collective 8067 8068 Input Parameters: 8069 + mat - the matrix 8070 . ncolors - maximum color value 8071 . n - number of entries in colorarray 8072 - colorarray - array indicating color for each column 8073 8074 Output Parameter: 8075 . iscoloring - coloring generated using colorarray information 8076 8077 Level: developer 8078 8079 .seealso: [](chapter_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()` 8080 @*/ 8081 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring) 8082 { 8083 PetscFunctionBegin; 8084 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8085 PetscValidType(mat, 1); 8086 PetscValidIntPointer(colorarray, 4); 8087 PetscValidPointer(iscoloring, 5); 8088 MatCheckPreallocated(mat, 1); 8089 8090 if (!mat->ops->coloringpatch) { 8091 PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring)); 8092 } else { 8093 PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring); 8094 } 8095 PetscFunctionReturn(PETSC_SUCCESS); 8096 } 8097 8098 /*@ 8099 MatSetUnfactored - Resets a factored matrix to be treated as unfactored. 8100 8101 Logically Collective 8102 8103 Input Parameter: 8104 . mat - the factored matrix to be reset 8105 8106 Level: developer 8107 8108 Notes: 8109 This routine should be used only with factored matrices formed by in-place 8110 factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE` 8111 format). This option can save memory, for example, when solving nonlinear 8112 systems with a matrix-free Newton-Krylov method and a matrix-based, in-place 8113 ILU(0) preconditioner. 8114 8115 One can specify in-place ILU(0) factorization by calling 8116 .vb 8117 PCType(pc,PCILU); 8118 PCFactorSeUseInPlace(pc); 8119 .ve 8120 or by using the options -pc_type ilu -pc_factor_in_place 8121 8122 In-place factorization ILU(0) can also be used as a local 8123 solver for the blocks within the block Jacobi or additive Schwarz 8124 methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc 8125 for details on setting local solver options. 8126 8127 Most users should employ the `KSP` interface for linear solvers 8128 instead of working directly with matrix algebra routines such as this. 8129 See, e.g., `KSPCreate()`. 8130 8131 .seealso: [](chapter_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()` 8132 @*/ 8133 PetscErrorCode MatSetUnfactored(Mat mat) 8134 { 8135 PetscFunctionBegin; 8136 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8137 PetscValidType(mat, 1); 8138 MatCheckPreallocated(mat, 1); 8139 mat->factortype = MAT_FACTOR_NONE; 8140 if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS); 8141 PetscUseTypeMethod(mat, setunfactored); 8142 PetscFunctionReturn(PETSC_SUCCESS); 8143 } 8144 8145 /*MC 8146 MatDenseGetArrayF90 - Accesses a matrix array from Fortran 8147 8148 Synopsis: 8149 MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8150 8151 Not Collective 8152 8153 Input Parameter: 8154 . x - matrix 8155 8156 Output Parameters: 8157 + xx_v - the Fortran pointer to the array 8158 - ierr - error code 8159 8160 Example of Usage: 8161 .vb 8162 PetscScalar, pointer xx_v(:,:) 8163 .... 8164 call MatDenseGetArrayF90(x,xx_v,ierr) 8165 a = xx_v(3) 8166 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8167 .ve 8168 8169 Level: advanced 8170 8171 .seealso: [](chapter_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()` 8172 M*/ 8173 8174 /*MC 8175 MatDenseRestoreArrayF90 - Restores a matrix array that has been 8176 accessed with `MatDenseGetArrayF90()`. 8177 8178 Synopsis: 8179 MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8180 8181 Not Collective 8182 8183 Input Parameters: 8184 + x - matrix 8185 - xx_v - the Fortran90 pointer to the array 8186 8187 Output Parameter: 8188 . ierr - error code 8189 8190 Example of Usage: 8191 .vb 8192 PetscScalar, pointer xx_v(:,:) 8193 .... 8194 call MatDenseGetArrayF90(x,xx_v,ierr) 8195 a = xx_v(3) 8196 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8197 .ve 8198 8199 Level: advanced 8200 8201 .seealso: [](chapter_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()` 8202 M*/ 8203 8204 /*MC 8205 MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran. 8206 8207 Synopsis: 8208 MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8209 8210 Not Collective 8211 8212 Input Parameter: 8213 . x - matrix 8214 8215 Output Parameters: 8216 + xx_v - the Fortran pointer to the array 8217 - ierr - error code 8218 8219 Example of Usage: 8220 .vb 8221 PetscScalar, pointer xx_v(:) 8222 .... 8223 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8224 a = xx_v(3) 8225 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8226 .ve 8227 8228 Level: advanced 8229 8230 .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()` 8231 M*/ 8232 8233 /*MC 8234 MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been 8235 accessed with `MatSeqAIJGetArrayF90()`. 8236 8237 Synopsis: 8238 MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8239 8240 Not Collective 8241 8242 Input Parameters: 8243 + x - matrix 8244 - xx_v - the Fortran90 pointer to the array 8245 8246 Output Parameter: 8247 . ierr - error code 8248 8249 Example of Usage: 8250 .vb 8251 PetscScalar, pointer xx_v(:) 8252 .... 8253 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8254 a = xx_v(3) 8255 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8256 .ve 8257 8258 Level: advanced 8259 8260 .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()` 8261 M*/ 8262 8263 /*@ 8264 MatCreateSubMatrix - Gets a single submatrix on the same number of processors 8265 as the original matrix. 8266 8267 Collective 8268 8269 Input Parameters: 8270 + mat - the original matrix 8271 . isrow - parallel `IS` containing the rows this processor should obtain 8272 . 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. 8273 - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 8274 8275 Output Parameter: 8276 . newmat - the new submatrix, of the same type as the original matrix 8277 8278 Level: advanced 8279 8280 Notes: 8281 The submatrix will be able to be multiplied with vectors using the same layout as `iscol`. 8282 8283 Some matrix types place restrictions on the row and column indices, such 8284 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; 8285 for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row. 8286 8287 The index sets may not have duplicate entries. 8288 8289 The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`, 8290 the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls 8291 to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX` 8292 will reuse the matrix generated the first time. You should call `MatDestroy()` on `newmat` when 8293 you are finished using it. 8294 8295 The communicator of the newly obtained matrix is ALWAYS the same as the communicator of 8296 the input matrix. 8297 8298 If `iscol` is `NULL` then all columns are obtained (not supported in Fortran). 8299 8300 Example usage: 8301 Consider the following 8x8 matrix with 34 non-zero values, that is 8302 assembled across 3 processors. Let's assume that proc0 owns 3 rows, 8303 proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 8304 as follows 8305 .vb 8306 1 2 0 | 0 3 0 | 0 4 8307 Proc0 0 5 6 | 7 0 0 | 8 0 8308 9 0 10 | 11 0 0 | 12 0 8309 ------------------------------------- 8310 13 0 14 | 15 16 17 | 0 0 8311 Proc1 0 18 0 | 19 20 21 | 0 0 8312 0 0 0 | 22 23 0 | 24 0 8313 ------------------------------------- 8314 Proc2 25 26 27 | 0 0 28 | 29 0 8315 30 0 0 | 31 32 33 | 0 34 8316 .ve 8317 8318 Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6]. The resulting submatrix is 8319 8320 .vb 8321 2 0 | 0 3 0 | 0 8322 Proc0 5 6 | 7 0 0 | 8 8323 ------------------------------- 8324 Proc1 18 0 | 19 20 21 | 0 8325 ------------------------------- 8326 Proc2 26 27 | 0 0 28 | 29 8327 0 0 | 31 32 33 | 0 8328 .ve 8329 8330 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()` 8331 @*/ 8332 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat) 8333 { 8334 PetscMPIInt size; 8335 Mat *local; 8336 IS iscoltmp; 8337 PetscBool flg; 8338 8339 PetscFunctionBegin; 8340 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8341 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 8342 if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 8343 PetscValidPointer(newmat, 5); 8344 if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5); 8345 PetscValidType(mat, 1); 8346 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8347 PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX"); 8348 8349 MatCheckPreallocated(mat, 1); 8350 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8351 8352 if (!iscol || isrow == iscol) { 8353 PetscBool stride; 8354 PetscMPIInt grabentirematrix = 0, grab; 8355 PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride)); 8356 if (stride) { 8357 PetscInt first, step, n, rstart, rend; 8358 PetscCall(ISStrideGetInfo(isrow, &first, &step)); 8359 if (step == 1) { 8360 PetscCall(MatGetOwnershipRange(mat, &rstart, &rend)); 8361 if (rstart == first) { 8362 PetscCall(ISGetLocalSize(isrow, &n)); 8363 if (n == rend - rstart) grabentirematrix = 1; 8364 } 8365 } 8366 } 8367 PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat))); 8368 if (grab) { 8369 PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n")); 8370 if (cll == MAT_INITIAL_MATRIX) { 8371 *newmat = mat; 8372 PetscCall(PetscObjectReference((PetscObject)mat)); 8373 } 8374 PetscFunctionReturn(PETSC_SUCCESS); 8375 } 8376 } 8377 8378 if (!iscol) { 8379 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp)); 8380 } else { 8381 iscoltmp = iscol; 8382 } 8383 8384 /* if original matrix is on just one processor then use submatrix generated */ 8385 if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) { 8386 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat)); 8387 goto setproperties; 8388 } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) { 8389 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local)); 8390 *newmat = *local; 8391 PetscCall(PetscFree(local)); 8392 goto setproperties; 8393 } else if (!mat->ops->createsubmatrix) { 8394 /* Create a new matrix type that implements the operation using the full matrix */ 8395 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8396 switch (cll) { 8397 case MAT_INITIAL_MATRIX: 8398 PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat)); 8399 break; 8400 case MAT_REUSE_MATRIX: 8401 PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp)); 8402 break; 8403 default: 8404 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX"); 8405 } 8406 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8407 goto setproperties; 8408 } 8409 8410 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8411 PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat); 8412 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8413 8414 setproperties: 8415 PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg)); 8416 if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat)); 8417 if (!iscol) PetscCall(ISDestroy(&iscoltmp)); 8418 if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat)); 8419 PetscFunctionReturn(PETSC_SUCCESS); 8420 } 8421 8422 /*@ 8423 MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix 8424 8425 Not Collective 8426 8427 Input Parameters: 8428 + A - the matrix we wish to propagate options from 8429 - B - the matrix we wish to propagate options to 8430 8431 Level: beginner 8432 8433 Note: 8434 Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL` 8435 8436 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, MatIsStructurallySymmetricKnown()` 8437 @*/ 8438 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B) 8439 { 8440 PetscFunctionBegin; 8441 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8442 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 8443 B->symmetry_eternal = A->symmetry_eternal; 8444 B->structural_symmetry_eternal = A->structural_symmetry_eternal; 8445 B->symmetric = A->symmetric; 8446 B->structurally_symmetric = A->structurally_symmetric; 8447 B->spd = A->spd; 8448 B->hermitian = A->hermitian; 8449 PetscFunctionReturn(PETSC_SUCCESS); 8450 } 8451 8452 /*@ 8453 MatStashSetInitialSize - sets the sizes of the matrix stash, that is 8454 used during the assembly process to store values that belong to 8455 other processors. 8456 8457 Not Collective 8458 8459 Input Parameters: 8460 + mat - the matrix 8461 . size - the initial size of the stash. 8462 - bsize - the initial size of the block-stash(if used). 8463 8464 Options Database Keys: 8465 + -matstash_initial_size <size> or <size0,size1,...sizep-1> 8466 - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1> 8467 8468 Level: intermediate 8469 8470 Notes: 8471 The block-stash is used for values set with `MatSetValuesBlocked()` while 8472 the stash is used for values set with `MatSetValues()` 8473 8474 Run with the option -info and look for output of the form 8475 MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs. 8476 to determine the appropriate value, MM, to use for size and 8477 MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs. 8478 to determine the value, BMM to use for bsize 8479 8480 .seealso: [](chapter_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()` 8481 @*/ 8482 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize) 8483 { 8484 PetscFunctionBegin; 8485 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8486 PetscValidType(mat, 1); 8487 PetscCall(MatStashSetInitialSize_Private(&mat->stash, size)); 8488 PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize)); 8489 PetscFunctionReturn(PETSC_SUCCESS); 8490 } 8491 8492 /*@ 8493 MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of 8494 the matrix 8495 8496 Neighbor-wise Collective 8497 8498 Input Parameters: 8499 + mat - the matrix 8500 . x - the vector to be multiplied by the interpolation operator 8501 - y - the vector to be added to the result 8502 8503 Output Parameter: 8504 . w - the resulting vector 8505 8506 Level: intermediate 8507 8508 Notes: 8509 `w` may be the same vector as `y`. 8510 8511 This allows one to use either the restriction or interpolation (its transpose) 8512 matrix to do the interpolation 8513 8514 .seealso: [](chapter_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8515 @*/ 8516 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w) 8517 { 8518 PetscInt M, N, Ny; 8519 8520 PetscFunctionBegin; 8521 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8522 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8523 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8524 PetscValidHeaderSpecific(w, VEC_CLASSID, 4); 8525 PetscCall(MatGetSize(A, &M, &N)); 8526 PetscCall(VecGetSize(y, &Ny)); 8527 if (M == Ny) { 8528 PetscCall(MatMultAdd(A, x, y, w)); 8529 } else { 8530 PetscCall(MatMultTransposeAdd(A, x, y, w)); 8531 } 8532 PetscFunctionReturn(PETSC_SUCCESS); 8533 } 8534 8535 /*@ 8536 MatInterpolate - y = A*x or A'*x depending on the shape of 8537 the matrix 8538 8539 Neighbor-wise Collective 8540 8541 Input Parameters: 8542 + mat - the matrix 8543 - x - the vector to be interpolated 8544 8545 Output Parameter: 8546 . y - the resulting vector 8547 8548 Level: intermediate 8549 8550 Note: 8551 This allows one to use either the restriction or interpolation (its transpose) 8552 matrix to do the interpolation 8553 8554 .seealso: [](chapter_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8555 @*/ 8556 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y) 8557 { 8558 PetscInt M, N, Ny; 8559 8560 PetscFunctionBegin; 8561 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8562 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8563 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8564 PetscCall(MatGetSize(A, &M, &N)); 8565 PetscCall(VecGetSize(y, &Ny)); 8566 if (M == Ny) { 8567 PetscCall(MatMult(A, x, y)); 8568 } else { 8569 PetscCall(MatMultTranspose(A, x, y)); 8570 } 8571 PetscFunctionReturn(PETSC_SUCCESS); 8572 } 8573 8574 /*@ 8575 MatRestrict - y = A*x or A'*x 8576 8577 Neighbor-wise Collective 8578 8579 Input Parameters: 8580 + mat - the matrix 8581 - x - the vector to be restricted 8582 8583 Output Parameter: 8584 . y - the resulting vector 8585 8586 Level: intermediate 8587 8588 Note: 8589 This allows one to use either the restriction or interpolation (its transpose) 8590 matrix to do the restriction 8591 8592 .seealso: [](chapter_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG` 8593 @*/ 8594 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y) 8595 { 8596 PetscInt M, N, Ny; 8597 8598 PetscFunctionBegin; 8599 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8600 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8601 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8602 PetscCall(MatGetSize(A, &M, &N)); 8603 PetscCall(VecGetSize(y, &Ny)); 8604 if (M == Ny) { 8605 PetscCall(MatMult(A, x, y)); 8606 } else { 8607 PetscCall(MatMultTranspose(A, x, y)); 8608 } 8609 PetscFunctionReturn(PETSC_SUCCESS); 8610 } 8611 8612 /*@ 8613 MatMatInterpolateAdd - Y = W + A*X or W + A'*X 8614 8615 Neighbor-wise Collective 8616 8617 Input Parameters: 8618 + mat - the matrix 8619 . x - the input dense matrix to be multiplied 8620 - w - the input dense matrix to be added to the result 8621 8622 Output Parameter: 8623 . y - the output dense matrix 8624 8625 Level: intermediate 8626 8627 Note: 8628 This allows one to use either the restriction or interpolation (its transpose) 8629 matrix to do the interpolation. y matrix can be reused if already created with the proper sizes, 8630 otherwise it will be recreated. y must be initialized to `NULL` if not supplied. 8631 8632 .seealso: [](chapter_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG` 8633 @*/ 8634 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y) 8635 { 8636 PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0; 8637 PetscBool trans = PETSC_TRUE; 8638 MatReuse reuse = MAT_INITIAL_MATRIX; 8639 8640 PetscFunctionBegin; 8641 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8642 PetscValidHeaderSpecific(x, MAT_CLASSID, 2); 8643 PetscValidType(x, 2); 8644 if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3); 8645 if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4); 8646 PetscCall(MatGetSize(A, &M, &N)); 8647 PetscCall(MatGetSize(x, &Mx, &Nx)); 8648 if (N == Mx) trans = PETSC_FALSE; 8649 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); 8650 Mo = trans ? N : M; 8651 if (*y) { 8652 PetscCall(MatGetSize(*y, &My, &Ny)); 8653 if (Mo == My && Nx == Ny) { 8654 reuse = MAT_REUSE_MATRIX; 8655 } else { 8656 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); 8657 PetscCall(MatDestroy(y)); 8658 } 8659 } 8660 8661 if (w && *y == w) { /* this is to minimize changes in PCMG */ 8662 PetscBool flg; 8663 8664 PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w)); 8665 if (w) { 8666 PetscInt My, Ny, Mw, Nw; 8667 8668 PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg)); 8669 PetscCall(MatGetSize(*y, &My, &Ny)); 8670 PetscCall(MatGetSize(w, &Mw, &Nw)); 8671 if (!flg || My != Mw || Ny != Nw) w = NULL; 8672 } 8673 if (!w) { 8674 PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w)); 8675 PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w)); 8676 PetscCall(PetscObjectDereference((PetscObject)w)); 8677 } else { 8678 PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN)); 8679 } 8680 } 8681 if (!trans) { 8682 PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8683 } else { 8684 PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8685 } 8686 if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN)); 8687 PetscFunctionReturn(PETSC_SUCCESS); 8688 } 8689 8690 /*@ 8691 MatMatInterpolate - Y = A*X or A'*X 8692 8693 Neighbor-wise Collective 8694 8695 Input Parameters: 8696 + mat - the matrix 8697 - x - the input dense matrix 8698 8699 Output Parameter: 8700 . y - the output dense matrix 8701 8702 Level: intermediate 8703 8704 Note: 8705 This allows one to use either the restriction or interpolation (its transpose) 8706 matrix to do the interpolation. y matrix can be reused if already created with the proper sizes, 8707 otherwise it will be recreated. y must be initialized to `NULL` if not supplied. 8708 8709 .seealso: [](chapter_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG` 8710 @*/ 8711 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y) 8712 { 8713 PetscFunctionBegin; 8714 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8715 PetscFunctionReturn(PETSC_SUCCESS); 8716 } 8717 8718 /*@ 8719 MatMatRestrict - Y = A*X or A'*X 8720 8721 Neighbor-wise Collective 8722 8723 Input Parameters: 8724 + mat - the matrix 8725 - x - the input dense matrix 8726 8727 Output Parameter: 8728 . y - the output dense matrix 8729 8730 Level: intermediate 8731 8732 Note: 8733 This allows one to use either the restriction or interpolation (its transpose) 8734 matrix to do the restriction. y matrix can be reused if already created with the proper sizes, 8735 otherwise it will be recreated. y must be initialized to `NULL` if not supplied. 8736 8737 .seealso: [](chapter_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG` 8738 @*/ 8739 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y) 8740 { 8741 PetscFunctionBegin; 8742 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8743 PetscFunctionReturn(PETSC_SUCCESS); 8744 } 8745 8746 /*@ 8747 MatGetNullSpace - retrieves the null space of a matrix. 8748 8749 Logically Collective 8750 8751 Input Parameters: 8752 + mat - the matrix 8753 - nullsp - the null space object 8754 8755 Level: developer 8756 8757 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace` 8758 @*/ 8759 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp) 8760 { 8761 PetscFunctionBegin; 8762 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8763 PetscValidPointer(nullsp, 2); 8764 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp; 8765 PetscFunctionReturn(PETSC_SUCCESS); 8766 } 8767 8768 /*@ 8769 MatSetNullSpace - attaches a null space to a matrix. 8770 8771 Logically Collective 8772 8773 Input Parameters: 8774 + mat - the matrix 8775 - nullsp - the null space object 8776 8777 Level: advanced 8778 8779 Notes: 8780 This null space is used by the `KSP` linear solvers to solve singular systems. 8781 8782 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` 8783 8784 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 8785 to zero but the linear system will still be solved in a least squares sense. 8786 8787 The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that 8788 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). 8789 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 8790 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 8791 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). 8792 This \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix. 8793 8794 If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called 8795 `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this 8796 routine also automatically calls `MatSetTransposeNullSpace()`. 8797 8798 The user should call `MatNullSpaceDestroy()`. 8799 8800 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, 8801 `KSPSetPCSide()` 8802 @*/ 8803 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp) 8804 { 8805 PetscFunctionBegin; 8806 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8807 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8808 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8809 PetscCall(MatNullSpaceDestroy(&mat->nullsp)); 8810 mat->nullsp = nullsp; 8811 if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp)); 8812 PetscFunctionReturn(PETSC_SUCCESS); 8813 } 8814 8815 /*@ 8816 MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix. 8817 8818 Logically Collective 8819 8820 Input Parameters: 8821 + mat - the matrix 8822 - nullsp - the null space object 8823 8824 Level: developer 8825 8826 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()` 8827 @*/ 8828 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp) 8829 { 8830 PetscFunctionBegin; 8831 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8832 PetscValidType(mat, 1); 8833 PetscValidPointer(nullsp, 2); 8834 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp; 8835 PetscFunctionReturn(PETSC_SUCCESS); 8836 } 8837 8838 /*@ 8839 MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix 8840 8841 Logically Collective 8842 8843 Input Parameters: 8844 + mat - the matrix 8845 - nullsp - the null space object 8846 8847 Level: advanced 8848 8849 Notes: 8850 This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning. 8851 8852 See `MatSetNullSpace()` 8853 8854 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()` 8855 @*/ 8856 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp) 8857 { 8858 PetscFunctionBegin; 8859 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8860 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8861 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8862 PetscCall(MatNullSpaceDestroy(&mat->transnullsp)); 8863 mat->transnullsp = nullsp; 8864 PetscFunctionReturn(PETSC_SUCCESS); 8865 } 8866 8867 /*@ 8868 MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions 8869 This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix. 8870 8871 Logically Collective 8872 8873 Input Parameters: 8874 + mat - the matrix 8875 - nullsp - the null space object 8876 8877 Level: advanced 8878 8879 Notes: 8880 Overwrites any previous near null space that may have been attached 8881 8882 You can remove the null space by calling this routine with an nullsp of `NULL` 8883 8884 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()` 8885 @*/ 8886 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp) 8887 { 8888 PetscFunctionBegin; 8889 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8890 PetscValidType(mat, 1); 8891 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8892 MatCheckPreallocated(mat, 1); 8893 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8894 PetscCall(MatNullSpaceDestroy(&mat->nearnullsp)); 8895 mat->nearnullsp = nullsp; 8896 PetscFunctionReturn(PETSC_SUCCESS); 8897 } 8898 8899 /*@ 8900 MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()` 8901 8902 Not Collective 8903 8904 Input Parameter: 8905 . mat - the matrix 8906 8907 Output Parameter: 8908 . nullsp - the null space object, `NULL` if not set 8909 8910 Level: advanced 8911 8912 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()` 8913 @*/ 8914 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp) 8915 { 8916 PetscFunctionBegin; 8917 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8918 PetscValidType(mat, 1); 8919 PetscValidPointer(nullsp, 2); 8920 MatCheckPreallocated(mat, 1); 8921 *nullsp = mat->nearnullsp; 8922 PetscFunctionReturn(PETSC_SUCCESS); 8923 } 8924 8925 /*@C 8926 MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix. 8927 8928 Collective 8929 8930 Input Parameters: 8931 + mat - the matrix 8932 . row - row/column permutation 8933 - info - information on desired factorization process 8934 8935 Level: developer 8936 8937 Notes: 8938 Probably really in-place only when level of fill is zero, otherwise allocates 8939 new space to store factored matrix and deletes previous memory. 8940 8941 Most users should employ the `KSP` interface for linear solvers 8942 instead of working directly with matrix algebra routines such as this. 8943 See, e.g., `KSPCreate()`. 8944 8945 Developer Note: 8946 The Fortran interface is not autogenerated as the 8947 interface definition cannot be generated correctly [due to `MatFactorInfo`] 8948 8949 .seealso: [](chapter_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 8950 @*/ 8951 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info) 8952 { 8953 PetscFunctionBegin; 8954 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8955 PetscValidType(mat, 1); 8956 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 8957 PetscValidPointer(info, 3); 8958 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 8959 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 8960 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8961 MatCheckPreallocated(mat, 1); 8962 PetscUseTypeMethod(mat, iccfactor, row, info); 8963 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 8964 PetscFunctionReturn(PETSC_SUCCESS); 8965 } 8966 8967 /*@ 8968 MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the 8969 ghosted ones. 8970 8971 Not Collective 8972 8973 Input Parameters: 8974 + mat - the matrix 8975 - diag - the diagonal values, including ghost ones 8976 8977 Level: developer 8978 8979 Notes: 8980 Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices 8981 8982 This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()` 8983 8984 .seealso: [](chapter_matrices), `Mat`, `MatDiagonalScale()` 8985 @*/ 8986 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag) 8987 { 8988 PetscMPIInt size; 8989 8990 PetscFunctionBegin; 8991 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8992 PetscValidHeaderSpecific(diag, VEC_CLASSID, 2); 8993 PetscValidType(mat, 1); 8994 8995 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled"); 8996 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 8997 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8998 if (size == 1) { 8999 PetscInt n, m; 9000 PetscCall(VecGetSize(diag, &n)); 9001 PetscCall(MatGetSize(mat, NULL, &m)); 9002 PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions"); 9003 PetscCall(MatDiagonalScale(mat, NULL, diag)); 9004 } else { 9005 PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag)); 9006 } 9007 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 9008 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9009 PetscFunctionReturn(PETSC_SUCCESS); 9010 } 9011 9012 /*@ 9013 MatGetInertia - Gets the inertia from a factored matrix 9014 9015 Collective 9016 9017 Input Parameter: 9018 . mat - the matrix 9019 9020 Output Parameters: 9021 + nneg - number of negative eigenvalues 9022 . nzero - number of zero eigenvalues 9023 - npos - number of positive eigenvalues 9024 9025 Level: advanced 9026 9027 Note: 9028 Matrix must have been factored by `MatCholeskyFactor()` 9029 9030 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()` 9031 @*/ 9032 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos) 9033 { 9034 PetscFunctionBegin; 9035 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9036 PetscValidType(mat, 1); 9037 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9038 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled"); 9039 PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos); 9040 PetscFunctionReturn(PETSC_SUCCESS); 9041 } 9042 9043 /*@C 9044 MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors 9045 9046 Neighbor-wise Collective 9047 9048 Input Parameters: 9049 + mat - the factored matrix obtained with `MatGetFactor()` 9050 - b - the right-hand-side vectors 9051 9052 Output Parameter: 9053 . x - the result vectors 9054 9055 Level: developer 9056 9057 Note: 9058 The vectors `b` and `x` cannot be the same. I.e., one cannot 9059 call `MatSolves`(A,x,x). 9060 9061 .seealso: [](chapter_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()` 9062 @*/ 9063 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x) 9064 { 9065 PetscFunctionBegin; 9066 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9067 PetscValidType(mat, 1); 9068 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 9069 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9070 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 9071 9072 MatCheckPreallocated(mat, 1); 9073 PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0)); 9074 PetscUseTypeMethod(mat, solves, b, x); 9075 PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0)); 9076 PetscFunctionReturn(PETSC_SUCCESS); 9077 } 9078 9079 /*@ 9080 MatIsSymmetric - Test whether a matrix is symmetric 9081 9082 Collective 9083 9084 Input Parameters: 9085 + A - the matrix to test 9086 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose) 9087 9088 Output Parameter: 9089 . flg - the result 9090 9091 Level: intermediate 9092 9093 Notes: 9094 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9095 9096 If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()` 9097 9098 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9099 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9100 9101 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`, 9102 `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()` 9103 @*/ 9104 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg) 9105 { 9106 PetscFunctionBegin; 9107 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9108 PetscValidBoolPointer(flg, 3); 9109 9110 if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE; 9111 else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE; 9112 else { 9113 PetscUseTypeMethod(A, issymmetric, tol, flg); 9114 if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg)); 9115 } 9116 PetscFunctionReturn(PETSC_SUCCESS); 9117 } 9118 9119 /*@ 9120 MatIsHermitian - Test whether a matrix is Hermitian 9121 9122 Collective 9123 9124 Input Parameters: 9125 + A - the matrix to test 9126 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian) 9127 9128 Output Parameter: 9129 . flg - the result 9130 9131 Level: intermediate 9132 9133 Notes: 9134 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9135 9136 If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()` 9137 9138 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9139 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`) 9140 9141 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, 9142 `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()` 9143 @*/ 9144 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg) 9145 { 9146 PetscFunctionBegin; 9147 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9148 PetscValidBoolPointer(flg, 3); 9149 9150 if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE; 9151 else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE; 9152 else { 9153 PetscUseTypeMethod(A, ishermitian, tol, flg); 9154 if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg)); 9155 } 9156 PetscFunctionReturn(PETSC_SUCCESS); 9157 } 9158 9159 /*@ 9160 MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state 9161 9162 Not Collective 9163 9164 Input Parameter: 9165 . A - the matrix to check 9166 9167 Output Parameters: 9168 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid) 9169 - flg - the result (only valid if set is `PETSC_TRUE`) 9170 9171 Level: advanced 9172 9173 Notes: 9174 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()` 9175 if you want it explicitly checked 9176 9177 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9178 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9179 9180 .seealso: [](chapter_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9181 @*/ 9182 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9183 { 9184 PetscFunctionBegin; 9185 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9186 PetscValidBoolPointer(set, 2); 9187 PetscValidBoolPointer(flg, 3); 9188 if (A->symmetric != PETSC_BOOL3_UNKNOWN) { 9189 *set = PETSC_TRUE; 9190 *flg = PetscBool3ToBool(A->symmetric); 9191 } else { 9192 *set = PETSC_FALSE; 9193 } 9194 PetscFunctionReturn(PETSC_SUCCESS); 9195 } 9196 9197 /*@ 9198 MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state 9199 9200 Not Collective 9201 9202 Input Parameter: 9203 . A - the matrix to check 9204 9205 Output Parameters: 9206 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid) 9207 - flg - the result (only valid if set is `PETSC_TRUE`) 9208 9209 Level: advanced 9210 9211 Notes: 9212 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). 9213 9214 One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD 9215 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`) 9216 9217 .seealso: [](chapter_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9218 @*/ 9219 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg) 9220 { 9221 PetscFunctionBegin; 9222 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9223 PetscValidBoolPointer(set, 2); 9224 PetscValidBoolPointer(flg, 3); 9225 if (A->spd != PETSC_BOOL3_UNKNOWN) { 9226 *set = PETSC_TRUE; 9227 *flg = PetscBool3ToBool(A->spd); 9228 } else { 9229 *set = PETSC_FALSE; 9230 } 9231 PetscFunctionReturn(PETSC_SUCCESS); 9232 } 9233 9234 /*@ 9235 MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state 9236 9237 Not Collective 9238 9239 Input Parameter: 9240 . A - the matrix to check 9241 9242 Output Parameters: 9243 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid) 9244 - flg - the result (only valid if set is `PETSC_TRUE`) 9245 9246 Level: advanced 9247 9248 Notes: 9249 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()` 9250 if you want it explicitly checked 9251 9252 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9253 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9254 9255 .seealso: [](chapter_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()` 9256 @*/ 9257 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg) 9258 { 9259 PetscFunctionBegin; 9260 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9261 PetscValidBoolPointer(set, 2); 9262 PetscValidBoolPointer(flg, 3); 9263 if (A->hermitian != PETSC_BOOL3_UNKNOWN) { 9264 *set = PETSC_TRUE; 9265 *flg = PetscBool3ToBool(A->hermitian); 9266 } else { 9267 *set = PETSC_FALSE; 9268 } 9269 PetscFunctionReturn(PETSC_SUCCESS); 9270 } 9271 9272 /*@ 9273 MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric 9274 9275 Collective 9276 9277 Input Parameter: 9278 . A - the matrix to test 9279 9280 Output Parameter: 9281 . flg - the result 9282 9283 Level: intermediate 9284 9285 Notes: 9286 If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()` 9287 9288 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 9289 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9290 9291 .seealso: [](chapter_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()` 9292 @*/ 9293 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg) 9294 { 9295 PetscFunctionBegin; 9296 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9297 PetscValidBoolPointer(flg, 2); 9298 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9299 *flg = PetscBool3ToBool(A->structurally_symmetric); 9300 } else { 9301 PetscUseTypeMethod(A, isstructurallysymmetric, flg); 9302 PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg)); 9303 } 9304 PetscFunctionReturn(PETSC_SUCCESS); 9305 } 9306 9307 /*@ 9308 MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state 9309 9310 Not Collective 9311 9312 Input Parameter: 9313 . A - the matrix to check 9314 9315 Output Parameters: 9316 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid) 9317 - flg - the result (only valid if set is PETSC_TRUE) 9318 9319 Level: advanced 9320 9321 Notes: 9322 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 9323 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9324 9325 Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation) 9326 9327 .seealso: [](chapter_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9328 @*/ 9329 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9330 { 9331 PetscFunctionBegin; 9332 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9333 PetscValidBoolPointer(set, 2); 9334 PetscValidBoolPointer(flg, 3); 9335 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9336 *set = PETSC_TRUE; 9337 *flg = PetscBool3ToBool(A->structurally_symmetric); 9338 } else { 9339 *set = PETSC_FALSE; 9340 } 9341 PetscFunctionReturn(PETSC_SUCCESS); 9342 } 9343 9344 /*@ 9345 MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need 9346 to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process 9347 9348 Not Collective 9349 9350 Input Parameter: 9351 . mat - the matrix 9352 9353 Output Parameters: 9354 + nstash - the size of the stash 9355 . reallocs - the number of additional mallocs incurred. 9356 . bnstash - the size of the block stash 9357 - breallocs - the number of additional mallocs incurred.in the block stash 9358 9359 Level: advanced 9360 9361 .seealso: [](chapter_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()` 9362 @*/ 9363 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs) 9364 { 9365 PetscFunctionBegin; 9366 PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs)); 9367 PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs)); 9368 PetscFunctionReturn(PETSC_SUCCESS); 9369 } 9370 9371 /*@C 9372 MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same 9373 parallel layout, `PetscLayout` for rows and columns 9374 9375 Collective 9376 9377 Input Parameter: 9378 . mat - the matrix 9379 9380 Output Parameters: 9381 + right - (optional) vector that the matrix can be multiplied against 9382 - left - (optional) vector that the matrix vector product can be stored in 9383 9384 Level: advanced 9385 9386 Notes: 9387 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()`. 9388 9389 These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed 9390 9391 .seealso: [](chapter_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()` 9392 @*/ 9393 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left) 9394 { 9395 PetscFunctionBegin; 9396 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9397 PetscValidType(mat, 1); 9398 if (mat->ops->getvecs) { 9399 PetscUseTypeMethod(mat, getvecs, right, left); 9400 } else { 9401 PetscInt rbs, cbs; 9402 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 9403 if (right) { 9404 PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup"); 9405 PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), right)); 9406 PetscCall(VecSetSizes(*right, mat->cmap->n, PETSC_DETERMINE)); 9407 PetscCall(VecSetBlockSize(*right, cbs)); 9408 PetscCall(VecSetType(*right, mat->defaultvectype)); 9409 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9410 if (mat->boundtocpu && mat->bindingpropagates) { 9411 PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE)); 9412 PetscCall(VecBindToCPU(*right, PETSC_TRUE)); 9413 } 9414 #endif 9415 PetscCall(PetscLayoutReference(mat->cmap, &(*right)->map)); 9416 } 9417 if (left) { 9418 PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup"); 9419 PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), left)); 9420 PetscCall(VecSetSizes(*left, mat->rmap->n, PETSC_DETERMINE)); 9421 PetscCall(VecSetBlockSize(*left, rbs)); 9422 PetscCall(VecSetType(*left, mat->defaultvectype)); 9423 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9424 if (mat->boundtocpu && mat->bindingpropagates) { 9425 PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE)); 9426 PetscCall(VecBindToCPU(*left, PETSC_TRUE)); 9427 } 9428 #endif 9429 PetscCall(PetscLayoutReference(mat->rmap, &(*left)->map)); 9430 } 9431 } 9432 PetscFunctionReturn(PETSC_SUCCESS); 9433 } 9434 9435 /*@C 9436 MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure 9437 with default values. 9438 9439 Not Collective 9440 9441 Input Parameter: 9442 . info - the `MatFactorInfo` data structure 9443 9444 Level: developer 9445 9446 Notes: 9447 The solvers are generally used through the `KSP` and `PC` objects, for example 9448 `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC` 9449 9450 Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed 9451 9452 Developer Note: 9453 The Fortran interface is not autogenerated as the 9454 interface definition cannot be generated correctly [due to `MatFactorInfo`] 9455 9456 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo` 9457 @*/ 9458 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info) 9459 { 9460 PetscFunctionBegin; 9461 PetscCall(PetscMemzero(info, sizeof(MatFactorInfo))); 9462 PetscFunctionReturn(PETSC_SUCCESS); 9463 } 9464 9465 /*@ 9466 MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed 9467 9468 Collective 9469 9470 Input Parameters: 9471 + mat - the factored matrix 9472 - is - the index set defining the Schur indices (0-based) 9473 9474 Level: advanced 9475 9476 Notes: 9477 Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system. 9478 9479 You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call. 9480 9481 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9482 9483 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`, 9484 `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9485 @*/ 9486 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is) 9487 { 9488 PetscErrorCode (*f)(Mat, IS); 9489 9490 PetscFunctionBegin; 9491 PetscValidType(mat, 1); 9492 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9493 PetscValidType(is, 2); 9494 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 9495 PetscCheckSameComm(mat, 1, is, 2); 9496 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 9497 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f)); 9498 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO"); 9499 PetscCall(MatDestroy(&mat->schur)); 9500 PetscCall((*f)(mat, is)); 9501 PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created"); 9502 PetscFunctionReturn(PETSC_SUCCESS); 9503 } 9504 9505 /*@ 9506 MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step 9507 9508 Logically Collective 9509 9510 Input Parameters: 9511 + F - the factored matrix obtained by calling `MatGetFactor()` 9512 . S - location where to return the Schur complement, can be `NULL` 9513 - status - the status of the Schur complement matrix, can be `NULL` 9514 9515 Level: advanced 9516 9517 Notes: 9518 You must call `MatFactorSetSchurIS()` before calling this routine. 9519 9520 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9521 9522 The routine provides a copy of the Schur matrix stored within the solver data structures. 9523 The caller must destroy the object when it is no longer needed. 9524 If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse. 9525 9526 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) 9527 9528 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9529 9530 Developer Note: 9531 The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc 9532 matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix. 9533 9534 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9535 @*/ 9536 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9537 { 9538 PetscFunctionBegin; 9539 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9540 if (S) PetscValidPointer(S, 2); 9541 if (status) PetscValidPointer(status, 3); 9542 if (S) { 9543 PetscErrorCode (*f)(Mat, Mat *); 9544 9545 PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f)); 9546 if (f) { 9547 PetscCall((*f)(F, S)); 9548 } else { 9549 PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S)); 9550 } 9551 } 9552 if (status) *status = F->schur_status; 9553 PetscFunctionReturn(PETSC_SUCCESS); 9554 } 9555 9556 /*@ 9557 MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix 9558 9559 Logically Collective 9560 9561 Input Parameters: 9562 + F - the factored matrix obtained by calling `MatGetFactor()` 9563 . *S - location where to return the Schur complement, can be `NULL` 9564 - status - the status of the Schur complement matrix, can be `NULL` 9565 9566 Level: advanced 9567 9568 Notes: 9569 You must call `MatFactorSetSchurIS()` before calling this routine. 9570 9571 Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS` 9572 9573 The routine returns a the Schur Complement stored within the data structures of the solver. 9574 9575 If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement. 9576 9577 The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed. 9578 9579 Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix 9580 9581 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9582 9583 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9584 @*/ 9585 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9586 { 9587 PetscFunctionBegin; 9588 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9589 if (S) PetscValidPointer(S, 2); 9590 if (status) PetscValidPointer(status, 3); 9591 if (S) *S = F->schur; 9592 if (status) *status = F->schur_status; 9593 PetscFunctionReturn(PETSC_SUCCESS); 9594 } 9595 9596 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F) 9597 { 9598 Mat S = F->schur; 9599 9600 PetscFunctionBegin; 9601 switch (F->schur_status) { 9602 case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through 9603 case MAT_FACTOR_SCHUR_INVERTED: 9604 if (S) { 9605 S->ops->solve = NULL; 9606 S->ops->matsolve = NULL; 9607 S->ops->solvetranspose = NULL; 9608 S->ops->matsolvetranspose = NULL; 9609 S->ops->solveadd = NULL; 9610 S->ops->solvetransposeadd = NULL; 9611 S->factortype = MAT_FACTOR_NONE; 9612 PetscCall(PetscFree(S->solvertype)); 9613 } 9614 case MAT_FACTOR_SCHUR_FACTORED: // fall-through 9615 break; 9616 default: 9617 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9618 } 9619 PetscFunctionReturn(PETSC_SUCCESS); 9620 } 9621 9622 /*@ 9623 MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()` 9624 9625 Logically Collective 9626 9627 Input Parameters: 9628 + F - the factored matrix obtained by calling `MatGetFactor()` 9629 . *S - location where the Schur complement is stored 9630 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`) 9631 9632 Level: advanced 9633 9634 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9635 @*/ 9636 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status) 9637 { 9638 PetscFunctionBegin; 9639 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9640 if (S) { 9641 PetscValidHeaderSpecific(*S, MAT_CLASSID, 2); 9642 *S = NULL; 9643 } 9644 F->schur_status = status; 9645 PetscCall(MatFactorUpdateSchurStatus_Private(F)); 9646 PetscFunctionReturn(PETSC_SUCCESS); 9647 } 9648 9649 /*@ 9650 MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step 9651 9652 Logically Collective 9653 9654 Input Parameters: 9655 + F - the factored matrix obtained by calling `MatGetFactor()` 9656 . rhs - location where the right hand side of the Schur complement system is stored 9657 - sol - location where the solution of the Schur complement system has to be returned 9658 9659 Level: advanced 9660 9661 Notes: 9662 The sizes of the vectors should match the size of the Schur complement 9663 9664 Must be called after `MatFactorSetSchurIS()` 9665 9666 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()` 9667 @*/ 9668 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol) 9669 { 9670 PetscFunctionBegin; 9671 PetscValidType(F, 1); 9672 PetscValidType(rhs, 2); 9673 PetscValidType(sol, 3); 9674 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9675 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9676 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9677 PetscCheckSameComm(F, 1, rhs, 2); 9678 PetscCheckSameComm(F, 1, sol, 3); 9679 PetscCall(MatFactorFactorizeSchurComplement(F)); 9680 switch (F->schur_status) { 9681 case MAT_FACTOR_SCHUR_FACTORED: 9682 PetscCall(MatSolveTranspose(F->schur, rhs, sol)); 9683 break; 9684 case MAT_FACTOR_SCHUR_INVERTED: 9685 PetscCall(MatMultTranspose(F->schur, rhs, sol)); 9686 break; 9687 default: 9688 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9689 } 9690 PetscFunctionReturn(PETSC_SUCCESS); 9691 } 9692 9693 /*@ 9694 MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step 9695 9696 Logically Collective 9697 9698 Input Parameters: 9699 + F - the factored matrix obtained by calling `MatGetFactor()` 9700 . rhs - location where the right hand side of the Schur complement system is stored 9701 - sol - location where the solution of the Schur complement system has to be returned 9702 9703 Level: advanced 9704 9705 Notes: 9706 The sizes of the vectors should match the size of the Schur complement 9707 9708 Must be called after `MatFactorSetSchurIS()` 9709 9710 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()` 9711 @*/ 9712 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol) 9713 { 9714 PetscFunctionBegin; 9715 PetscValidType(F, 1); 9716 PetscValidType(rhs, 2); 9717 PetscValidType(sol, 3); 9718 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9719 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9720 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9721 PetscCheckSameComm(F, 1, rhs, 2); 9722 PetscCheckSameComm(F, 1, sol, 3); 9723 PetscCall(MatFactorFactorizeSchurComplement(F)); 9724 switch (F->schur_status) { 9725 case MAT_FACTOR_SCHUR_FACTORED: 9726 PetscCall(MatSolve(F->schur, rhs, sol)); 9727 break; 9728 case MAT_FACTOR_SCHUR_INVERTED: 9729 PetscCall(MatMult(F->schur, rhs, sol)); 9730 break; 9731 default: 9732 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9733 } 9734 PetscFunctionReturn(PETSC_SUCCESS); 9735 } 9736 9737 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat); 9738 #if PetscDefined(HAVE_CUDA) 9739 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat); 9740 #endif 9741 9742 /* Schur status updated in the interface */ 9743 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F) 9744 { 9745 Mat S = F->schur; 9746 9747 PetscFunctionBegin; 9748 if (S) { 9749 PetscMPIInt size; 9750 PetscBool isdense, isdensecuda; 9751 9752 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size)); 9753 PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented"); 9754 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense)); 9755 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda)); 9756 PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name); 9757 PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0)); 9758 if (isdense) { 9759 PetscCall(MatSeqDenseInvertFactors_Private(S)); 9760 } else if (isdensecuda) { 9761 #if defined(PETSC_HAVE_CUDA) 9762 PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S)); 9763 #endif 9764 } 9765 // HIP?????????????? 9766 PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0)); 9767 } 9768 PetscFunctionReturn(PETSC_SUCCESS); 9769 } 9770 9771 /*@ 9772 MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step 9773 9774 Logically Collective 9775 9776 Input Parameter: 9777 . F - the factored matrix obtained by calling `MatGetFactor()` 9778 9779 Level: advanced 9780 9781 Notes: 9782 Must be called after `MatFactorSetSchurIS()`. 9783 9784 Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it. 9785 9786 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()` 9787 @*/ 9788 PetscErrorCode MatFactorInvertSchurComplement(Mat F) 9789 { 9790 PetscFunctionBegin; 9791 PetscValidType(F, 1); 9792 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9793 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS); 9794 PetscCall(MatFactorFactorizeSchurComplement(F)); 9795 PetscCall(MatFactorInvertSchurComplement_Private(F)); 9796 F->schur_status = MAT_FACTOR_SCHUR_INVERTED; 9797 PetscFunctionReturn(PETSC_SUCCESS); 9798 } 9799 9800 /*@ 9801 MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step 9802 9803 Logically Collective 9804 9805 Input Parameter: 9806 . F - the factored matrix obtained by calling `MatGetFactor()` 9807 9808 Level: advanced 9809 9810 Note: 9811 Must be called after `MatFactorSetSchurIS()` 9812 9813 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()` 9814 @*/ 9815 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F) 9816 { 9817 MatFactorInfo info; 9818 9819 PetscFunctionBegin; 9820 PetscValidType(F, 1); 9821 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9822 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS); 9823 PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0)); 9824 PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo))); 9825 if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */ 9826 PetscCall(MatCholeskyFactor(F->schur, NULL, &info)); 9827 } else { 9828 PetscCall(MatLUFactor(F->schur, NULL, NULL, &info)); 9829 } 9830 PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0)); 9831 F->schur_status = MAT_FACTOR_SCHUR_FACTORED; 9832 PetscFunctionReturn(PETSC_SUCCESS); 9833 } 9834 9835 /*@ 9836 MatPtAP - Creates the matrix product C = P^T * A * P 9837 9838 Neighbor-wise Collective 9839 9840 Input Parameters: 9841 + A - the matrix 9842 . P - the projection matrix 9843 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9844 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate 9845 if the result is a dense matrix this is irrelevant 9846 9847 Output Parameter: 9848 . C - the product matrix 9849 9850 Level: intermediate 9851 9852 Notes: 9853 C will be created and must be destroyed by the user with `MatDestroy()`. 9854 9855 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9856 9857 Developer Note: 9858 For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`. 9859 9860 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()` 9861 @*/ 9862 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C) 9863 { 9864 PetscFunctionBegin; 9865 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 9866 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9867 9868 if (scall == MAT_INITIAL_MATRIX) { 9869 PetscCall(MatProductCreate(A, P, NULL, C)); 9870 PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP)); 9871 PetscCall(MatProductSetAlgorithm(*C, "default")); 9872 PetscCall(MatProductSetFill(*C, fill)); 9873 9874 (*C)->product->api_user = PETSC_TRUE; 9875 PetscCall(MatProductSetFromOptions(*C)); 9876 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); 9877 PetscCall(MatProductSymbolic(*C)); 9878 } else { /* scall == MAT_REUSE_MATRIX */ 9879 PetscCall(MatProductReplaceMats(A, P, NULL, *C)); 9880 } 9881 9882 PetscCall(MatProductNumeric(*C)); 9883 (*C)->symmetric = A->symmetric; 9884 (*C)->spd = A->spd; 9885 PetscFunctionReturn(PETSC_SUCCESS); 9886 } 9887 9888 /*@ 9889 MatRARt - Creates the matrix product C = R * A * R^T 9890 9891 Neighbor-wise Collective 9892 9893 Input Parameters: 9894 + A - the matrix 9895 . R - the projection matrix 9896 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9897 - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate 9898 if the result is a dense matrix this is irrelevant 9899 9900 Output Parameter: 9901 . C - the product matrix 9902 9903 Level: intermediate 9904 9905 Notes: 9906 C will be created and must be destroyed by the user with `MatDestroy()`. 9907 9908 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9909 9910 This routine is currently only implemented for pairs of `MATAIJ` matrices and classes 9911 which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes, 9912 parallel MatRARt is implemented via explicit transpose of R, which could be very expensive. 9913 We recommend using MatPtAP(). 9914 9915 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()` 9916 @*/ 9917 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C) 9918 { 9919 PetscFunctionBegin; 9920 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 9921 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9922 9923 if (scall == MAT_INITIAL_MATRIX) { 9924 PetscCall(MatProductCreate(A, R, NULL, C)); 9925 PetscCall(MatProductSetType(*C, MATPRODUCT_RARt)); 9926 PetscCall(MatProductSetAlgorithm(*C, "default")); 9927 PetscCall(MatProductSetFill(*C, fill)); 9928 9929 (*C)->product->api_user = PETSC_TRUE; 9930 PetscCall(MatProductSetFromOptions(*C)); 9931 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); 9932 PetscCall(MatProductSymbolic(*C)); 9933 } else { /* scall == MAT_REUSE_MATRIX */ 9934 PetscCall(MatProductReplaceMats(A, R, NULL, *C)); 9935 } 9936 9937 PetscCall(MatProductNumeric(*C)); 9938 if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 9939 PetscFunctionReturn(PETSC_SUCCESS); 9940 } 9941 9942 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C) 9943 { 9944 PetscFunctionBegin; 9945 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9946 9947 if (scall == MAT_INITIAL_MATRIX) { 9948 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype])); 9949 PetscCall(MatProductCreate(A, B, NULL, C)); 9950 PetscCall(MatProductSetType(*C, ptype)); 9951 PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT)); 9952 PetscCall(MatProductSetFill(*C, fill)); 9953 9954 (*C)->product->api_user = PETSC_TRUE; 9955 PetscCall(MatProductSetFromOptions(*C)); 9956 PetscCall(MatProductSymbolic(*C)); 9957 } else { /* scall == MAT_REUSE_MATRIX */ 9958 Mat_Product *product = (*C)->product; 9959 PetscBool isdense; 9960 9961 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, "")); 9962 if (isdense && product && product->type != ptype) { 9963 PetscCall(MatProductClear(*C)); 9964 product = NULL; 9965 } 9966 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype])); 9967 if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */ 9968 PetscCheck(isdense, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first"); 9969 PetscCall(MatProductCreate_Private(A, B, NULL, *C)); 9970 product = (*C)->product; 9971 product->fill = fill; 9972 product->api_user = PETSC_TRUE; 9973 product->clear = PETSC_TRUE; 9974 9975 PetscCall(MatProductSetType(*C, ptype)); 9976 PetscCall(MatProductSetFromOptions(*C)); 9977 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); 9978 PetscCall(MatProductSymbolic(*C)); 9979 } else { /* user may change input matrices A or B when REUSE */ 9980 PetscCall(MatProductReplaceMats(A, B, NULL, *C)); 9981 } 9982 } 9983 PetscCall(MatProductNumeric(*C)); 9984 PetscFunctionReturn(PETSC_SUCCESS); 9985 } 9986 9987 /*@ 9988 MatMatMult - Performs matrix-matrix multiplication C=A*B. 9989 9990 Neighbor-wise Collective 9991 9992 Input Parameters: 9993 + A - the left matrix 9994 . B - the right matrix 9995 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9996 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate 9997 if the result is a dense matrix this is irrelevant 9998 9999 Output Parameter: 10000 . C - the product matrix 10001 10002 Notes: 10003 Unless scall is `MAT_REUSE_MATRIX` C will be created. 10004 10005 `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 10006 call to this function with `MAT_INITIAL_MATRIX`. 10007 10008 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed. 10009 10010 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`, 10011 rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse. 10012 10013 Example of Usage: 10014 .vb 10015 MatProductCreate(A,B,NULL,&C); 10016 MatProductSetType(C,MATPRODUCT_AB); 10017 MatProductSymbolic(C); 10018 MatProductNumeric(C); // compute C=A * B 10019 MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1 10020 MatProductNumeric(C); 10021 MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1 10022 MatProductNumeric(C); 10023 .ve 10024 10025 Level: intermediate 10026 10027 .seealso: [](chapter_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()` 10028 @*/ 10029 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10030 { 10031 PetscFunctionBegin; 10032 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C)); 10033 PetscFunctionReturn(PETSC_SUCCESS); 10034 } 10035 10036 /*@ 10037 MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T. 10038 10039 Neighbor-wise Collective 10040 10041 Input Parameters: 10042 + A - the left matrix 10043 . B - the right matrix 10044 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10045 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 10046 10047 Output Parameter: 10048 . C - the product matrix 10049 10050 Level: intermediate 10051 10052 Notes: 10053 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10054 10055 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call 10056 10057 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10058 actually needed. 10059 10060 This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class, 10061 and for pairs of `MATMPIDENSE` matrices. 10062 10063 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt` 10064 10065 Options Database Keys: 10066 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the 10067 first redundantly copies the transposed B matrix on each process and requiers O(log P) communication complexity; 10068 the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity. 10069 10070 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductCreate()`, `MatProductAlgorithm`, `MatProductType`, `MATPRODUCT_ABt` 10071 @*/ 10072 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10073 { 10074 PetscFunctionBegin; 10075 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C)); 10076 if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10077 PetscFunctionReturn(PETSC_SUCCESS); 10078 } 10079 10080 /*@ 10081 MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B. 10082 10083 Neighbor-wise Collective 10084 10085 Input Parameters: 10086 + A - the left matrix 10087 . B - the right matrix 10088 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10089 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 10090 10091 Output Parameter: 10092 . C - the product matrix 10093 10094 Level: intermediate 10095 10096 Notes: 10097 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10098 10099 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call. 10100 10101 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB` 10102 10103 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10104 actually needed. 10105 10106 This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes 10107 which inherit from `MATSEQAIJ`. C will be of the same type as the input matrices. 10108 10109 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()` 10110 @*/ 10111 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10112 { 10113 PetscFunctionBegin; 10114 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C)); 10115 PetscFunctionReturn(PETSC_SUCCESS); 10116 } 10117 10118 /*@ 10119 MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C. 10120 10121 Neighbor-wise Collective 10122 10123 Input Parameters: 10124 + A - the left matrix 10125 . B - the middle matrix 10126 . C - the right matrix 10127 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10128 - 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 10129 if the result is a dense matrix this is irrelevant 10130 10131 Output Parameter: 10132 . D - the product matrix 10133 10134 Level: intermediate 10135 10136 Notes: 10137 Unless scall is `MAT_REUSE_MATRIX` D will be created. 10138 10139 `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call 10140 10141 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC` 10142 10143 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10144 actually needed. 10145 10146 If you have many matrices with the same non-zero structure to multiply, you 10147 should use `MAT_REUSE_MATRIX` in all calls but the first 10148 10149 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()` 10150 @*/ 10151 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D) 10152 { 10153 PetscFunctionBegin; 10154 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6); 10155 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10156 10157 if (scall == MAT_INITIAL_MATRIX) { 10158 PetscCall(MatProductCreate(A, B, C, D)); 10159 PetscCall(MatProductSetType(*D, MATPRODUCT_ABC)); 10160 PetscCall(MatProductSetAlgorithm(*D, "default")); 10161 PetscCall(MatProductSetFill(*D, fill)); 10162 10163 (*D)->product->api_user = PETSC_TRUE; 10164 PetscCall(MatProductSetFromOptions(*D)); 10165 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, 10166 ((PetscObject)C)->type_name); 10167 PetscCall(MatProductSymbolic(*D)); 10168 } else { /* user may change input matrices when REUSE */ 10169 PetscCall(MatProductReplaceMats(A, B, C, *D)); 10170 } 10171 PetscCall(MatProductNumeric(*D)); 10172 PetscFunctionReturn(PETSC_SUCCESS); 10173 } 10174 10175 /*@ 10176 MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators. 10177 10178 Collective 10179 10180 Input Parameters: 10181 + mat - the matrix 10182 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices) 10183 . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used) 10184 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10185 10186 Output Parameter: 10187 . matredundant - redundant matrix 10188 10189 Level: advanced 10190 10191 Notes: 10192 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 10193 original matrix has not changed from that last call to MatCreateRedundantMatrix(). 10194 10195 This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before 10196 calling it. 10197 10198 `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be. 10199 10200 .seealso: [](chapter_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubComm` 10201 @*/ 10202 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant) 10203 { 10204 MPI_Comm comm; 10205 PetscMPIInt size; 10206 PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs; 10207 Mat_Redundant *redund = NULL; 10208 PetscSubcomm psubcomm = NULL; 10209 MPI_Comm subcomm_in = subcomm; 10210 Mat *matseq; 10211 IS isrow, iscol; 10212 PetscBool newsubcomm = PETSC_FALSE; 10213 10214 PetscFunctionBegin; 10215 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10216 if (nsubcomm && reuse == MAT_REUSE_MATRIX) { 10217 PetscValidPointer(*matredundant, 5); 10218 PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5); 10219 } 10220 10221 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10222 if (size == 1 || nsubcomm == 1) { 10223 if (reuse == MAT_INITIAL_MATRIX) { 10224 PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant)); 10225 } else { 10226 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"); 10227 PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN)); 10228 } 10229 PetscFunctionReturn(PETSC_SUCCESS); 10230 } 10231 10232 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10233 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10234 MatCheckPreallocated(mat, 1); 10235 10236 PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0)); 10237 if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */ 10238 /* create psubcomm, then get subcomm */ 10239 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10240 PetscCallMPI(MPI_Comm_size(comm, &size)); 10241 PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size); 10242 10243 PetscCall(PetscSubcommCreate(comm, &psubcomm)); 10244 PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm)); 10245 PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS)); 10246 PetscCall(PetscSubcommSetFromOptions(psubcomm)); 10247 PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL)); 10248 newsubcomm = PETSC_TRUE; 10249 PetscCall(PetscSubcommDestroy(&psubcomm)); 10250 } 10251 10252 /* get isrow, iscol and a local sequential matrix matseq[0] */ 10253 if (reuse == MAT_INITIAL_MATRIX) { 10254 mloc_sub = PETSC_DECIDE; 10255 nloc_sub = PETSC_DECIDE; 10256 if (bs < 1) { 10257 PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M)); 10258 PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N)); 10259 } else { 10260 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M)); 10261 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N)); 10262 } 10263 PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm)); 10264 rstart = rend - mloc_sub; 10265 PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow)); 10266 PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol)); 10267 } else { /* reuse == MAT_REUSE_MATRIX */ 10268 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"); 10269 /* retrieve subcomm */ 10270 PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm)); 10271 redund = (*matredundant)->redundant; 10272 isrow = redund->isrow; 10273 iscol = redund->iscol; 10274 matseq = redund->matseq; 10275 } 10276 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq)); 10277 10278 /* get matredundant over subcomm */ 10279 if (reuse == MAT_INITIAL_MATRIX) { 10280 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant)); 10281 10282 /* create a supporting struct and attach it to C for reuse */ 10283 PetscCall(PetscNew(&redund)); 10284 (*matredundant)->redundant = redund; 10285 redund->isrow = isrow; 10286 redund->iscol = iscol; 10287 redund->matseq = matseq; 10288 if (newsubcomm) { 10289 redund->subcomm = subcomm; 10290 } else { 10291 redund->subcomm = MPI_COMM_NULL; 10292 } 10293 } else { 10294 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant)); 10295 } 10296 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 10297 if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) { 10298 PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE)); 10299 PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE)); 10300 } 10301 #endif 10302 PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0)); 10303 PetscFunctionReturn(PETSC_SUCCESS); 10304 } 10305 10306 /*@C 10307 MatGetMultiProcBlock - Create multiple 'parallel submatrices' from 10308 a given `Mat`. Each submatrix can span multiple procs. 10309 10310 Collective 10311 10312 Input Parameters: 10313 + mat - the matrix 10314 . subcomm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))` 10315 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10316 10317 Output Parameter: 10318 . subMat - parallel sub-matrices each spanning a given `subcomm` 10319 10320 Level: advanced 10321 10322 Notes: 10323 The submatrix partition across processors is dictated by `subComm` a 10324 communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm` 10325 is not restricted to be grouped with consecutive original ranks. 10326 10327 Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices 10328 map directly to the layout of the original matrix [wrt the local 10329 row,col partitioning]. So the original 'DiagonalMat' naturally maps 10330 into the 'DiagonalMat' of the `subMat`, hence it is used directly from 10331 the `subMat`. However the offDiagMat looses some columns - and this is 10332 reconstructed with `MatSetValues()` 10333 10334 This is used by `PCBJACOBI` when a single block spans multiple MPI ranks 10335 10336 .seealso: [](chapter_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI` 10337 @*/ 10338 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) 10339 { 10340 PetscMPIInt commsize, subCommSize; 10341 10342 PetscFunctionBegin; 10343 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize)); 10344 PetscCallMPI(MPI_Comm_size(subComm, &subCommSize)); 10345 PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize); 10346 10347 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"); 10348 PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10349 PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat); 10350 PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10351 PetscFunctionReturn(PETSC_SUCCESS); 10352 } 10353 10354 /*@ 10355 MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering 10356 10357 Not Collective 10358 10359 Input Parameters: 10360 + mat - matrix to extract local submatrix from 10361 . isrow - local row indices for submatrix 10362 - iscol - local column indices for submatrix 10363 10364 Output Parameter: 10365 . submat - the submatrix 10366 10367 Level: intermediate 10368 10369 Notes: 10370 `submat` should be disposed of with `MatRestoreLocalSubMatrix()`. 10371 10372 Depending on the format of `mat`, the returned submat may not implement `MatMult()`. Its communicator may be 10373 the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of `mat`'s. 10374 10375 `submat` always implements `MatSetValuesLocal()`. If `isrow` and `iscol` have the same block size, then 10376 `MatSetValuesBlockedLocal()` will also be implemented. 10377 10378 `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`. 10379 Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided. 10380 10381 .seealso: [](chapter_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()` 10382 @*/ 10383 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10384 { 10385 PetscFunctionBegin; 10386 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10387 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10388 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10389 PetscCheckSameComm(isrow, 2, iscol, 3); 10390 PetscValidPointer(submat, 4); 10391 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call"); 10392 10393 if (mat->ops->getlocalsubmatrix) { 10394 PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat); 10395 } else { 10396 PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat)); 10397 } 10398 PetscFunctionReturn(PETSC_SUCCESS); 10399 } 10400 10401 /*@ 10402 MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()` 10403 10404 Not Collective 10405 10406 Input Parameters: 10407 + mat - matrix to extract local submatrix from 10408 . isrow - local row indices for submatrix 10409 . iscol - local column indices for submatrix 10410 - submat - the submatrix 10411 10412 Level: intermediate 10413 10414 .seealso: [](chapter_matrices), `Mat`, `MatGetLocalSubMatrix()` 10415 @*/ 10416 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10417 { 10418 PetscFunctionBegin; 10419 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10420 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10421 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10422 PetscCheckSameComm(isrow, 2, iscol, 3); 10423 PetscValidPointer(submat, 4); 10424 if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4); 10425 10426 if (mat->ops->restorelocalsubmatrix) { 10427 PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat); 10428 } else { 10429 PetscCall(MatDestroy(submat)); 10430 } 10431 *submat = NULL; 10432 PetscFunctionReturn(PETSC_SUCCESS); 10433 } 10434 10435 /*@ 10436 MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix 10437 10438 Collective 10439 10440 Input Parameter: 10441 . mat - the matrix 10442 10443 Output Parameter: 10444 . is - if any rows have zero diagonals this contains the list of them 10445 10446 Level: developer 10447 10448 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10449 @*/ 10450 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is) 10451 { 10452 PetscFunctionBegin; 10453 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10454 PetscValidType(mat, 1); 10455 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10456 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10457 10458 if (!mat->ops->findzerodiagonals) { 10459 Vec diag; 10460 const PetscScalar *a; 10461 PetscInt *rows; 10462 PetscInt rStart, rEnd, r, nrow = 0; 10463 10464 PetscCall(MatCreateVecs(mat, &diag, NULL)); 10465 PetscCall(MatGetDiagonal(mat, diag)); 10466 PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd)); 10467 PetscCall(VecGetArrayRead(diag, &a)); 10468 for (r = 0; r < rEnd - rStart; ++r) 10469 if (a[r] == 0.0) ++nrow; 10470 PetscCall(PetscMalloc1(nrow, &rows)); 10471 nrow = 0; 10472 for (r = 0; r < rEnd - rStart; ++r) 10473 if (a[r] == 0.0) rows[nrow++] = r + rStart; 10474 PetscCall(VecRestoreArrayRead(diag, &a)); 10475 PetscCall(VecDestroy(&diag)); 10476 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is)); 10477 } else { 10478 PetscUseTypeMethod(mat, findzerodiagonals, is); 10479 } 10480 PetscFunctionReturn(PETSC_SUCCESS); 10481 } 10482 10483 /*@ 10484 MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size) 10485 10486 Collective 10487 10488 Input Parameter: 10489 . mat - the matrix 10490 10491 Output Parameter: 10492 . is - contains the list of rows with off block diagonal entries 10493 10494 Level: developer 10495 10496 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10497 @*/ 10498 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is) 10499 { 10500 PetscFunctionBegin; 10501 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10502 PetscValidType(mat, 1); 10503 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10504 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10505 10506 PetscUseTypeMethod(mat, findoffblockdiagonalentries, is); 10507 PetscFunctionReturn(PETSC_SUCCESS); 10508 } 10509 10510 /*@C 10511 MatInvertBlockDiagonal - Inverts the block diagonal entries. 10512 10513 Collective; No Fortran Support 10514 10515 Input Parameter: 10516 . mat - the matrix 10517 10518 Output Parameter: 10519 . values - the block inverses in column major order (FORTRAN-like) 10520 10521 Level: advanced 10522 10523 Notes: 10524 The size of the blocks is determined by the block size of the matrix. 10525 10526 The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case 10527 10528 The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size 10529 10530 .seealso: [](chapter_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()` 10531 @*/ 10532 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values) 10533 { 10534 PetscFunctionBegin; 10535 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10536 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10537 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10538 PetscUseTypeMethod(mat, invertblockdiagonal, values); 10539 PetscFunctionReturn(PETSC_SUCCESS); 10540 } 10541 10542 /*@C 10543 MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries. 10544 10545 Collective; No Fortran Support 10546 10547 Input Parameters: 10548 + mat - the matrix 10549 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()` 10550 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()` 10551 10552 Output Parameter: 10553 . values - the block inverses in column major order (FORTRAN-like) 10554 10555 Level: advanced 10556 10557 Notes: 10558 Use `MatInvertBlockDiagonal()` if all blocks have the same size 10559 10560 The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case 10561 10562 .seealso: [](chapter_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()` 10563 @*/ 10564 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values) 10565 { 10566 PetscFunctionBegin; 10567 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10568 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10569 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10570 PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values); 10571 PetscFunctionReturn(PETSC_SUCCESS); 10572 } 10573 10574 /*@ 10575 MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A 10576 10577 Collective 10578 10579 Input Parameters: 10580 + A - the matrix 10581 - C - matrix with inverted block diagonal of `A`. This matrix should be created and may have its type set. 10582 10583 Level: advanced 10584 10585 Note: 10586 The blocksize of the matrix is used to determine the blocks on the diagonal of `C` 10587 10588 .seealso: [](chapter_matrices), `Mat`, `MatInvertBlockDiagonal()` 10589 @*/ 10590 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C) 10591 { 10592 const PetscScalar *vals; 10593 PetscInt *dnnz; 10594 PetscInt m, rstart, rend, bs, i, j; 10595 10596 PetscFunctionBegin; 10597 PetscCall(MatInvertBlockDiagonal(A, &vals)); 10598 PetscCall(MatGetBlockSize(A, &bs)); 10599 PetscCall(MatGetLocalSize(A, &m, NULL)); 10600 PetscCall(MatSetLayouts(C, A->rmap, A->cmap)); 10601 PetscCall(PetscMalloc1(m / bs, &dnnz)); 10602 for (j = 0; j < m / bs; j++) dnnz[j] = 1; 10603 PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL)); 10604 PetscCall(PetscFree(dnnz)); 10605 PetscCall(MatGetOwnershipRange(C, &rstart, &rend)); 10606 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE)); 10607 for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES)); 10608 PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 10609 PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 10610 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE)); 10611 PetscFunctionReturn(PETSC_SUCCESS); 10612 } 10613 10614 /*@C 10615 MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created 10616 via `MatTransposeColoringCreate()`. 10617 10618 Collective 10619 10620 Input Parameter: 10621 . c - coloring context 10622 10623 Level: intermediate 10624 10625 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringCreate()` 10626 @*/ 10627 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c) 10628 { 10629 MatTransposeColoring matcolor = *c; 10630 10631 PetscFunctionBegin; 10632 if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS); 10633 if (--((PetscObject)matcolor)->refct > 0) { 10634 matcolor = NULL; 10635 PetscFunctionReturn(PETSC_SUCCESS); 10636 } 10637 10638 PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow)); 10639 PetscCall(PetscFree(matcolor->rows)); 10640 PetscCall(PetscFree(matcolor->den2sp)); 10641 PetscCall(PetscFree(matcolor->colorforcol)); 10642 PetscCall(PetscFree(matcolor->columns)); 10643 if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart)); 10644 PetscCall(PetscHeaderDestroy(c)); 10645 PetscFunctionReturn(PETSC_SUCCESS); 10646 } 10647 10648 /*@C 10649 MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which 10650 a `MatTransposeColoring` context has been created, computes a dense B^T by applying 10651 `MatTransposeColoring` to sparse B. 10652 10653 Collective 10654 10655 Input Parameters: 10656 + coloring - coloring context created with `MatTransposeColoringCreate()` 10657 - B - sparse matrix 10658 10659 Output Parameter: 10660 . Btdense - dense matrix B^T 10661 10662 Level: developer 10663 10664 Note: 10665 These are used internally for some implementations of `MatRARt()` 10666 10667 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()` 10668 @*/ 10669 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense) 10670 { 10671 PetscFunctionBegin; 10672 PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10673 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 10674 PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3); 10675 10676 PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense)); 10677 PetscFunctionReturn(PETSC_SUCCESS); 10678 } 10679 10680 /*@C 10681 MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which 10682 a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense 10683 in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix 10684 `Csp` from `Cden`. 10685 10686 Collective 10687 10688 Input Parameters: 10689 + matcoloring - coloring context created with `MatTransposeColoringCreate()` 10690 - Cden - matrix product of a sparse matrix and a dense matrix Btdense 10691 10692 Output Parameter: 10693 . Csp - sparse matrix 10694 10695 Level: developer 10696 10697 Note: 10698 These are used internally for some implementations of `MatRARt()` 10699 10700 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()` 10701 @*/ 10702 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp) 10703 { 10704 PetscFunctionBegin; 10705 PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10706 PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2); 10707 PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3); 10708 10709 PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp)); 10710 PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY)); 10711 PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY)); 10712 PetscFunctionReturn(PETSC_SUCCESS); 10713 } 10714 10715 /*@C 10716 MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T. 10717 10718 Collective 10719 10720 Input Parameters: 10721 + mat - the matrix product C 10722 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()` 10723 10724 Output Parameter: 10725 . color - the new coloring context 10726 10727 Level: intermediate 10728 10729 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`, 10730 `MatTransColoringApplyDenToSp()` 10731 @*/ 10732 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color) 10733 { 10734 MatTransposeColoring c; 10735 MPI_Comm comm; 10736 10737 PetscFunctionBegin; 10738 PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10739 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10740 PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL)); 10741 10742 c->ctype = iscoloring->ctype; 10743 PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c); 10744 10745 *color = c; 10746 PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10747 PetscFunctionReturn(PETSC_SUCCESS); 10748 } 10749 10750 /*@ 10751 MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the 10752 matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the 10753 same, otherwise it will be larger 10754 10755 Not Collective 10756 10757 Input Parameter: 10758 . A - the matrix 10759 10760 Output Parameter: 10761 . state - the current state 10762 10763 Level: intermediate 10764 10765 Notes: 10766 You can only compare states from two different calls to the SAME matrix, you cannot compare calls between 10767 different matrices 10768 10769 Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix 10770 10771 Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers. 10772 10773 .seealso: [](chapter_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()` 10774 @*/ 10775 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state) 10776 { 10777 PetscFunctionBegin; 10778 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10779 *state = mat->nonzerostate; 10780 PetscFunctionReturn(PETSC_SUCCESS); 10781 } 10782 10783 /*@ 10784 MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential 10785 matrices from each processor 10786 10787 Collective 10788 10789 Input Parameters: 10790 + comm - the communicators the parallel matrix will live on 10791 . seqmat - the input sequential matrices 10792 . n - number of local columns (or `PETSC_DECIDE`) 10793 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10794 10795 Output Parameter: 10796 . mpimat - the parallel matrix generated 10797 10798 Level: developer 10799 10800 Note: 10801 The number of columns of the matrix in EACH processor MUST be the same. 10802 10803 .seealso: [](chapter_matrices), `Mat` 10804 @*/ 10805 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat) 10806 { 10807 PetscMPIInt size; 10808 10809 PetscFunctionBegin; 10810 PetscCallMPI(MPI_Comm_size(comm, &size)); 10811 if (size == 1) { 10812 if (reuse == MAT_INITIAL_MATRIX) { 10813 PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat)); 10814 } else { 10815 PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN)); 10816 } 10817 PetscFunctionReturn(PETSC_SUCCESS); 10818 } 10819 10820 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"); 10821 10822 PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0)); 10823 PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat)); 10824 PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0)); 10825 PetscFunctionReturn(PETSC_SUCCESS); 10826 } 10827 10828 /*@ 10829 MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent ranks' ownership ranges. 10830 10831 Collective 10832 10833 Input Parameters: 10834 + A - the matrix to create subdomains from 10835 - N - requested number of subdomains 10836 10837 Output Parameters: 10838 + n - number of subdomains resulting on this rank 10839 - iss - `IS` list with indices of subdomains on this rank 10840 10841 Level: advanced 10842 10843 Note: 10844 The number of subdomains must be smaller than the communicator size 10845 10846 .seealso: [](chapter_matrices), `Mat`, `IS` 10847 @*/ 10848 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[]) 10849 { 10850 MPI_Comm comm, subcomm; 10851 PetscMPIInt size, rank, color; 10852 PetscInt rstart, rend, k; 10853 10854 PetscFunctionBegin; 10855 PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 10856 PetscCallMPI(MPI_Comm_size(comm, &size)); 10857 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 10858 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); 10859 *n = 1; 10860 k = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */ 10861 color = rank / k; 10862 PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm)); 10863 PetscCall(PetscMalloc1(1, iss)); 10864 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 10865 PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0])); 10866 PetscCallMPI(MPI_Comm_free(&subcomm)); 10867 PetscFunctionReturn(PETSC_SUCCESS); 10868 } 10869 10870 /*@ 10871 MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection. 10872 10873 If the interpolation and restriction operators are the same, uses `MatPtAP()`. 10874 If they are not the same, uses `MatMatMatMult()`. 10875 10876 Once the coarse grid problem is constructed, correct for interpolation operators 10877 that are not of full rank, which can legitimately happen in the case of non-nested 10878 geometric multigrid. 10879 10880 Input Parameters: 10881 + restrct - restriction operator 10882 . dA - fine grid matrix 10883 . interpolate - interpolation operator 10884 . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10885 - fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate 10886 10887 Output Parameter: 10888 . A - the Galerkin coarse matrix 10889 10890 Options Database Key: 10891 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used 10892 10893 Level: developer 10894 10895 .seealso: [](chapter_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()` 10896 @*/ 10897 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A) 10898 { 10899 IS zerorows; 10900 Vec diag; 10901 10902 PetscFunctionBegin; 10903 PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10904 /* Construct the coarse grid matrix */ 10905 if (interpolate == restrct) { 10906 PetscCall(MatPtAP(dA, interpolate, reuse, fill, A)); 10907 } else { 10908 PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A)); 10909 } 10910 10911 /* If the interpolation matrix is not of full rank, A will have zero rows. 10912 This can legitimately happen in the case of non-nested geometric multigrid. 10913 In that event, we set the rows of the matrix to the rows of the identity, 10914 ignoring the equations (as the RHS will also be zero). */ 10915 10916 PetscCall(MatFindZeroRows(*A, &zerorows)); 10917 10918 if (zerorows != NULL) { /* if there are any zero rows */ 10919 PetscCall(MatCreateVecs(*A, &diag, NULL)); 10920 PetscCall(MatGetDiagonal(*A, diag)); 10921 PetscCall(VecISSet(diag, zerorows, 1.0)); 10922 PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES)); 10923 PetscCall(VecDestroy(&diag)); 10924 PetscCall(ISDestroy(&zerorows)); 10925 } 10926 PetscFunctionReturn(PETSC_SUCCESS); 10927 } 10928 10929 /*@C 10930 MatSetOperation - Allows user to set a matrix operation for any matrix type 10931 10932 Logically Collective 10933 10934 Input Parameters: 10935 + mat - the matrix 10936 . op - the name of the operation 10937 - f - the function that provides the operation 10938 10939 Level: developer 10940 10941 Usage: 10942 .vb 10943 extern PetscErrorCode usermult(Mat, Vec, Vec); 10944 10945 PetscCall(MatCreateXXX(comm, ..., &A)); 10946 PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFunction)usermult)); 10947 .ve 10948 10949 Notes: 10950 See the file `include/petscmat.h` for a complete list of matrix 10951 operations, which all have the form MATOP_<OPERATION>, where 10952 <OPERATION> is the name (in all capital letters) of the 10953 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 10954 10955 All user-provided functions (except for `MATOP_DESTROY`) should have the same calling 10956 sequence as the usual matrix interface routines, since they 10957 are intended to be accessed via the usual matrix interface 10958 routines, e.g., 10959 .vb 10960 MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec) 10961 .ve 10962 10963 In particular each function MUST return `PETSC_SUCCESS` on success and 10964 nonzero on failure. 10965 10966 This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type. 10967 10968 .seealso: [](chapter_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()` 10969 @*/ 10970 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void)) 10971 { 10972 PetscFunctionBegin; 10973 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10974 if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view; 10975 (((void (**)(void))mat->ops)[op]) = f; 10976 PetscFunctionReturn(PETSC_SUCCESS); 10977 } 10978 10979 /*@C 10980 MatGetOperation - Gets a matrix operation for any matrix type. 10981 10982 Not Collective 10983 10984 Input Parameters: 10985 + mat - the matrix 10986 - op - the name of the operation 10987 10988 Output Parameter: 10989 . f - the function that provides the operation 10990 10991 Level: developer 10992 10993 Usage: 10994 .vb 10995 PetscErrorCode (*usermult)(Mat, Vec, Vec); 10996 MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult); 10997 .ve 10998 10999 Notes: 11000 See the file include/petscmat.h for a complete list of matrix 11001 operations, which all have the form MATOP_<OPERATION>, where 11002 <OPERATION> is the name (in all capital letters) of the 11003 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11004 11005 This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type. 11006 11007 .seealso: [](chapter_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()` 11008 @*/ 11009 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void)) 11010 { 11011 PetscFunctionBegin; 11012 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11013 *f = (((void (**)(void))mat->ops)[op]); 11014 PetscFunctionReturn(PETSC_SUCCESS); 11015 } 11016 11017 /*@ 11018 MatHasOperation - Determines whether the given matrix supports the particular operation. 11019 11020 Not Collective 11021 11022 Input Parameters: 11023 + mat - the matrix 11024 - op - the operation, for example, `MATOP_GET_DIAGONAL` 11025 11026 Output Parameter: 11027 . has - either `PETSC_TRUE` or `PETSC_FALSE` 11028 11029 Level: advanced 11030 11031 Note: 11032 See `MatSetOperation()` for additional discussion on naming convention and usage of `op`. 11033 11034 .seealso: [](chapter_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()` 11035 @*/ 11036 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has) 11037 { 11038 PetscFunctionBegin; 11039 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11040 PetscValidBoolPointer(has, 3); 11041 if (mat->ops->hasoperation) { 11042 PetscUseTypeMethod(mat, hasoperation, op, has); 11043 } else { 11044 if (((void **)mat->ops)[op]) *has = PETSC_TRUE; 11045 else { 11046 *has = PETSC_FALSE; 11047 if (op == MATOP_CREATE_SUBMATRIX) { 11048 PetscMPIInt size; 11049 11050 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 11051 if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has)); 11052 } 11053 } 11054 } 11055 PetscFunctionReturn(PETSC_SUCCESS); 11056 } 11057 11058 /*@ 11059 MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent 11060 11061 Collective 11062 11063 Input Parameter: 11064 . mat - the matrix 11065 11066 Output Parameter: 11067 . cong - either `PETSC_TRUE` or `PETSC_FALSE` 11068 11069 Level: beginner 11070 11071 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout` 11072 @*/ 11073 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong) 11074 { 11075 PetscFunctionBegin; 11076 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11077 PetscValidType(mat, 1); 11078 PetscValidBoolPointer(cong, 2); 11079 if (!mat->rmap || !mat->cmap) { 11080 *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE; 11081 PetscFunctionReturn(PETSC_SUCCESS); 11082 } 11083 if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */ 11084 PetscCall(PetscLayoutSetUp(mat->rmap)); 11085 PetscCall(PetscLayoutSetUp(mat->cmap)); 11086 PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong)); 11087 if (*cong) mat->congruentlayouts = 1; 11088 else mat->congruentlayouts = 0; 11089 } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE; 11090 PetscFunctionReturn(PETSC_SUCCESS); 11091 } 11092 11093 PetscErrorCode MatSetInf(Mat A) 11094 { 11095 PetscFunctionBegin; 11096 PetscUseTypeMethod(A, setinf); 11097 PetscFunctionReturn(PETSC_SUCCESS); 11098 } 11099 11100 /*@C 11101 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 11102 and possibly removes small values from the graph structure. 11103 11104 Collective 11105 11106 Input Parameters: 11107 + A - the matrix 11108 . sym - `PETSC_TRUE` indicates that the graph should be symmetrized 11109 . scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry 11110 - filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value 11111 11112 Output Parameter: 11113 . graph - the resulting graph 11114 11115 Level: advanced 11116 11117 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `PCGAMG` 11118 @*/ 11119 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph) 11120 { 11121 PetscFunctionBegin; 11122 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11123 PetscValidType(A, 1); 11124 PetscValidLogicalCollectiveBool(A, scale, 3); 11125 PetscValidPointer(graph, 5); 11126 PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph); 11127 PetscFunctionReturn(PETSC_SUCCESS); 11128 } 11129 11130 /*@ 11131 MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place, 11132 meaning the same memory is used for the matrix, and no new memory is allocated. 11133 11134 Collective 11135 11136 Input Parameter: 11137 . A - the matrix 11138 11139 Level: intermediate 11140 11141 Developer Note: 11142 The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end 11143 of the arrays in the data structure are unneeded. 11144 11145 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatChop()` 11146 @*/ 11147 PetscErrorCode MatEliminateZeros(Mat A) 11148 { 11149 PetscFunctionBegin; 11150 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11151 PetscUseTypeMethod(A, eliminatezeros); 11152 PetscFunctionReturn(PETSC_SUCCESS); 11153 } 11154