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_DenseCopyToGPU, MAT_DenseCopyFromGPU; 42 PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom; 43 PetscLogEvent MAT_FactorFactS, MAT_FactorInvS; 44 PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights; 45 PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR; 46 47 const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL}; 48 49 /*@ 50 MatSetRandom - Sets all components of a matrix to random numbers. 51 52 Logically Collective 53 54 Input Parameters: 55 + x - the matrix 56 - rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or `NULL` and 57 it will create one internally. 58 59 Example: 60 .vb 61 PetscRandomCreate(PETSC_COMM_WORLD,&rctx); 62 MatSetRandom(x,rctx); 63 PetscRandomDestroy(rctx); 64 .ve 65 66 Level: intermediate 67 68 Notes: 69 For sparse matrices that have been preallocated but not been assembled it randomly selects appropriate locations, 70 71 for sparse matrices that already have locations it fills the locations with random numbers. 72 73 It generates an error if used on sparse matrices that have not been preallocated. 74 75 .seealso: [](chapter_matrices), `Mat`, `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomCreate()`, `PetscRandomDestroy()` 76 @*/ 77 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx) 78 { 79 PetscRandom randObj = NULL; 80 81 PetscFunctionBegin; 82 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 83 if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2); 84 PetscValidType(x, 1); 85 MatCheckPreallocated(x, 1); 86 87 if (!rctx) { 88 MPI_Comm comm; 89 PetscCall(PetscObjectGetComm((PetscObject)x, &comm)); 90 PetscCall(PetscRandomCreate(comm, &randObj)); 91 PetscCall(PetscRandomSetType(randObj, x->defaultrandtype)); 92 PetscCall(PetscRandomSetFromOptions(randObj)); 93 rctx = randObj; 94 } 95 PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0)); 96 PetscUseTypeMethod(x, setrandom, rctx); 97 PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0)); 98 99 PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY)); 100 PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY)); 101 PetscCall(PetscRandomDestroy(&randObj)); 102 PetscFunctionReturn(PETSC_SUCCESS); 103 } 104 105 /*@ 106 MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in 107 108 Logically Collective 109 110 Input Parameter: 111 . mat - the factored matrix 112 113 Output Parameters: 114 + pivot - the pivot value computed 115 - row - the row that the zero pivot occurred. This row value must be interpreted carefully due to row reorderings and which processes 116 the share the matrix 117 118 Level: advanced 119 120 Notes: 121 This routine does not work for factorizations done with external packages. 122 123 This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT` 124 125 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 126 127 .seealso: [](chapter_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, 128 `MAT_FACTOR_NUMERIC_ZEROPIVOT` 129 @*/ 130 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row) 131 { 132 PetscFunctionBegin; 133 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 134 PetscValidRealPointer(pivot, 2); 135 PetscValidIntPointer(row, 3); 136 *pivot = mat->factorerror_zeropivot_value; 137 *row = mat->factorerror_zeropivot_row; 138 PetscFunctionReturn(PETSC_SUCCESS); 139 } 140 141 /*@ 142 MatFactorGetError - gets the error code from a factorization 143 144 Logically Collective 145 146 Input Parameter: 147 . mat - the factored matrix 148 149 Output Parameter: 150 . err - the error code 151 152 Level: advanced 153 154 Note: 155 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 156 157 .seealso: [](chapter_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, 158 `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, `MatFactorError` 159 @*/ 160 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err) 161 { 162 PetscFunctionBegin; 163 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 164 PetscValidPointer(err, 2); 165 *err = mat->factorerrortype; 166 PetscFunctionReturn(PETSC_SUCCESS); 167 } 168 169 /*@ 170 MatFactorClearError - clears the error code in a factorization 171 172 Logically Collective 173 174 Input Parameter: 175 . mat - the factored matrix 176 177 Level: developer 178 179 Note: 180 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 181 182 .seealso: [](chapter_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`, 183 `MatGetErrorCode()`, `MatFactorError` 184 @*/ 185 PetscErrorCode MatFactorClearError(Mat mat) 186 { 187 PetscFunctionBegin; 188 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 189 mat->factorerrortype = MAT_FACTOR_NOERROR; 190 mat->factorerror_zeropivot_value = 0.0; 191 mat->factorerror_zeropivot_row = 0; 192 PetscFunctionReturn(PETSC_SUCCESS); 193 } 194 195 PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero) 196 { 197 Vec r, l; 198 const PetscScalar *al; 199 PetscInt i, nz, gnz, N, n; 200 201 PetscFunctionBegin; 202 PetscCall(MatCreateVecs(mat, &r, &l)); 203 if (!cols) { /* nonzero rows */ 204 PetscCall(MatGetSize(mat, &N, NULL)); 205 PetscCall(MatGetLocalSize(mat, &n, NULL)); 206 PetscCall(VecSet(l, 0.0)); 207 PetscCall(VecSetRandom(r, NULL)); 208 PetscCall(MatMult(mat, r, l)); 209 PetscCall(VecGetArrayRead(l, &al)); 210 } else { /* nonzero columns */ 211 PetscCall(MatGetSize(mat, NULL, &N)); 212 PetscCall(MatGetLocalSize(mat, NULL, &n)); 213 PetscCall(VecSet(r, 0.0)); 214 PetscCall(VecSetRandom(l, NULL)); 215 PetscCall(MatMultTranspose(mat, l, r)); 216 PetscCall(VecGetArrayRead(r, &al)); 217 } 218 if (tol <= 0.0) { 219 for (i = 0, nz = 0; i < n; i++) 220 if (al[i] != 0.0) nz++; 221 } else { 222 for (i = 0, nz = 0; i < n; i++) 223 if (PetscAbsScalar(al[i]) > tol) nz++; 224 } 225 PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 226 if (gnz != N) { 227 PetscInt *nzr; 228 PetscCall(PetscMalloc1(nz, &nzr)); 229 if (nz) { 230 if (tol < 0) { 231 for (i = 0, nz = 0; i < n; i++) 232 if (al[i] != 0.0) nzr[nz++] = i; 233 } else { 234 for (i = 0, nz = 0; i < n; i++) 235 if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i; 236 } 237 } 238 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero)); 239 } else *nonzero = NULL; 240 if (!cols) { /* nonzero rows */ 241 PetscCall(VecRestoreArrayRead(l, &al)); 242 } else { 243 PetscCall(VecRestoreArrayRead(r, &al)); 244 } 245 PetscCall(VecDestroy(&l)); 246 PetscCall(VecDestroy(&r)); 247 PetscFunctionReturn(PETSC_SUCCESS); 248 } 249 250 /*@ 251 MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix 252 253 Input Parameter: 254 . A - the matrix 255 256 Output Parameter: 257 . keptrows - the rows that are not completely zero 258 259 Level: intermediate 260 261 Note: 262 `keptrows` is set to `NULL` if all rows are nonzero. 263 264 .seealso: [](chapter_matrices), `Mat`, `MatFindZeroRows()` 265 @*/ 266 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows) 267 { 268 PetscFunctionBegin; 269 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 270 PetscValidType(mat, 1); 271 PetscValidPointer(keptrows, 2); 272 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 273 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 274 if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows); 275 else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows)); 276 PetscFunctionReturn(PETSC_SUCCESS); 277 } 278 279 /*@ 280 MatFindZeroRows - Locate all rows that are completely zero in the matrix 281 282 Input Parameter: 283 . A - the matrix 284 285 Output Parameter: 286 . zerorows - the rows that are completely zero 287 288 Level: intermediate 289 290 Note: 291 `zerorows` is set to `NULL` if no rows are zero. 292 293 .seealso: [](chapter_matrices), `Mat`, `MatFindNonzeroRows()` 294 @*/ 295 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows) 296 { 297 IS keptrows; 298 PetscInt m, n; 299 300 PetscFunctionBegin; 301 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 302 PetscValidType(mat, 1); 303 PetscValidPointer(zerorows, 2); 304 PetscCall(MatFindNonzeroRows(mat, &keptrows)); 305 /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows. 306 In keeping with this convention, we set zerorows to NULL if there are no zero 307 rows. */ 308 if (keptrows == NULL) { 309 *zerorows = NULL; 310 } else { 311 PetscCall(MatGetOwnershipRange(mat, &m, &n)); 312 PetscCall(ISComplement(keptrows, m, n, zerorows)); 313 PetscCall(ISDestroy(&keptrows)); 314 } 315 PetscFunctionReturn(PETSC_SUCCESS); 316 } 317 318 /*@ 319 MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling 320 321 Not Collective 322 323 Input Parameter: 324 . A - the matrix 325 326 Output Parameter: 327 . a - the diagonal part (which is a SEQUENTIAL matrix) 328 329 Level: advanced 330 331 Notes: 332 See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix. 333 334 Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation. 335 336 .seealso: [](chapter_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ` 337 @*/ 338 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a) 339 { 340 PetscFunctionBegin; 341 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 342 PetscValidType(A, 1); 343 PetscValidPointer(a, 2); 344 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 345 if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a); 346 else { 347 PetscMPIInt size; 348 349 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 350 PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name); 351 *a = A; 352 } 353 PetscFunctionReturn(PETSC_SUCCESS); 354 } 355 356 /*@ 357 MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries. 358 359 Collective 360 361 Input Parameter: 362 . mat - the matrix 363 364 Output Parameter: 365 . trace - the sum of the diagonal entries 366 367 Level: advanced 368 369 .seealso: [](chapter_matrices), `Mat` 370 @*/ 371 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace) 372 { 373 Vec diag; 374 375 PetscFunctionBegin; 376 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 377 PetscValidScalarPointer(trace, 2); 378 PetscCall(MatCreateVecs(mat, &diag, NULL)); 379 PetscCall(MatGetDiagonal(mat, diag)); 380 PetscCall(VecSum(diag, trace)); 381 PetscCall(VecDestroy(&diag)); 382 PetscFunctionReturn(PETSC_SUCCESS); 383 } 384 385 /*@ 386 MatRealPart - Zeros out the imaginary part of the matrix 387 388 Logically Collective 389 390 Input Parameter: 391 . mat - the matrix 392 393 Level: advanced 394 395 .seealso: [](chapter_matrices), `Mat`, `MatImaginaryPart()` 396 @*/ 397 PetscErrorCode MatRealPart(Mat mat) 398 { 399 PetscFunctionBegin; 400 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 401 PetscValidType(mat, 1); 402 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 403 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 404 MatCheckPreallocated(mat, 1); 405 PetscUseTypeMethod(mat, realpart); 406 PetscFunctionReturn(PETSC_SUCCESS); 407 } 408 409 /*@C 410 MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix 411 412 Collective 413 414 Input Parameter: 415 . mat - the matrix 416 417 Output Parameters: 418 + nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each block) 419 - ghosts - the global indices of the ghost points 420 421 Level: advanced 422 423 Note: 424 `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()` 425 426 .seealso: [](chapter_matrices), `Mat`, `VecCreateGhost()` 427 @*/ 428 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[]) 429 { 430 PetscFunctionBegin; 431 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 432 PetscValidType(mat, 1); 433 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 434 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 435 if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts); 436 else { 437 if (nghosts) *nghosts = 0; 438 if (ghosts) *ghosts = NULL; 439 } 440 PetscFunctionReturn(PETSC_SUCCESS); 441 } 442 443 /*@ 444 MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part 445 446 Logically Collective 447 448 Input Parameter: 449 . mat - the matrix 450 451 Level: advanced 452 453 .seealso: [](chapter_matrices), `Mat`, `MatRealPart()` 454 @*/ 455 PetscErrorCode MatImaginaryPart(Mat mat) 456 { 457 PetscFunctionBegin; 458 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 459 PetscValidType(mat, 1); 460 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 461 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 462 MatCheckPreallocated(mat, 1); 463 PetscUseTypeMethod(mat, imaginarypart); 464 PetscFunctionReturn(PETSC_SUCCESS); 465 } 466 467 /*@ 468 MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices) 469 470 Not Collective 471 472 Input Parameter: 473 . mat - the matrix 474 475 Output Parameters: 476 + missing - is any diagonal missing 477 - dd - first diagonal entry that is missing (optional) on this process 478 479 Level: advanced 480 481 .seealso: [](chapter_matrices), `Mat` 482 @*/ 483 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd) 484 { 485 PetscFunctionBegin; 486 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 487 PetscValidType(mat, 1); 488 PetscValidBoolPointer(missing, 2); 489 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name); 490 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 491 PetscUseTypeMethod(mat, missingdiagonal, missing, dd); 492 PetscFunctionReturn(PETSC_SUCCESS); 493 } 494 495 /*@C 496 MatGetRow - Gets a row of a matrix. You MUST call `MatRestoreRow()` 497 for each row that you get to ensure that your application does 498 not bleed memory. 499 500 Not Collective 501 502 Input Parameters: 503 + mat - the matrix 504 - row - the row to get 505 506 Output Parameters: 507 + ncols - if not `NULL`, the number of nonzeros in the row 508 . cols - if not `NULL`, the column numbers 509 - vals - if not `NULL`, the values 510 511 Level: advanced 512 513 Notes: 514 This routine is provided for people who need to have direct access 515 to the structure of a matrix. We hope that we provide enough 516 high-level matrix routines that few users will need it. 517 518 `MatGetRow()` always returns 0-based column indices, regardless of 519 whether the internal representation is 0-based (default) or 1-based. 520 521 For better efficiency, set cols and/or vals to `NULL` if you do 522 not wish to extract these quantities. 523 524 The user can only examine the values extracted with `MatGetRow()`; 525 the values cannot be altered. To change the matrix entries, one 526 must use `MatSetValues()`. 527 528 You can only have one call to `MatGetRow()` outstanding for a particular 529 matrix at a time, per processor. `MatGetRow()` can only obtain rows 530 associated with the given processor, it cannot get rows from the 531 other processors; for that we suggest using `MatCreateSubMatrices()`, then 532 MatGetRow() on the submatrix. The row index passed to `MatGetRow()` 533 is in the global number of rows. 534 535 Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix. 536 537 Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly. 538 539 Fortran Note: 540 The calling sequence is 541 .vb 542 MatGetRow(matrix,row,ncols,cols,values,ierr) 543 Mat matrix (input) 544 integer row (input) 545 integer ncols (output) 546 integer cols(maxcols) (output) 547 double precision (or double complex) values(maxcols) output 548 .ve 549 where maxcols >= maximum nonzeros in any row of the matrix. 550 551 Caution: 552 Do not try to change the contents of the output arrays (`cols` and `vals`). 553 In some cases, this may corrupt the matrix. 554 555 .seealso: [](chapter_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()` 556 @*/ 557 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 558 { 559 PetscInt incols; 560 561 PetscFunctionBegin; 562 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 563 PetscValidType(mat, 1); 564 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 565 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 566 MatCheckPreallocated(mat, 1); 567 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); 568 PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0)); 569 PetscUseTypeMethod(mat, getrow, row, &incols, (PetscInt **)cols, (PetscScalar **)vals); 570 if (ncols) *ncols = incols; 571 PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0)); 572 PetscFunctionReturn(PETSC_SUCCESS); 573 } 574 575 /*@ 576 MatConjugate - replaces the matrix values with their complex conjugates 577 578 Logically Collective 579 580 Input Parameter: 581 . mat - the matrix 582 583 Level: advanced 584 585 .seealso: [](chapter_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()` 586 @*/ 587 PetscErrorCode MatConjugate(Mat mat) 588 { 589 PetscFunctionBegin; 590 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 591 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 592 if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) { 593 PetscUseTypeMethod(mat, conjugate); 594 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 595 } 596 PetscFunctionReturn(PETSC_SUCCESS); 597 } 598 599 /*@C 600 MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`. 601 602 Not Collective 603 604 Input Parameters: 605 + mat - the matrix 606 . row - the row to get 607 . ncols - the number of nonzeros 608 . cols - the columns of the nonzeros 609 - vals - if nonzero the column values 610 611 Level: advanced 612 613 Notes: 614 This routine should be called after you have finished examining the entries. 615 616 This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental 617 us of the array after it has been restored. If you pass `NULL`, it will 618 not zero the pointers. Use of `cols` or `vals` after `MatRestoreRow()` is invalid. 619 620 Fortran Notes: 621 The calling sequence is 622 .vb 623 MatRestoreRow(matrix,row,ncols,cols,values,ierr) 624 Mat matrix (input) 625 integer row (input) 626 integer ncols (output) 627 integer cols(maxcols) (output) 628 double precision (or double complex) values(maxcols) output 629 .ve 630 Where maxcols >= maximum nonzeros in any row of the matrix. 631 632 In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()` 633 before another call to `MatGetRow()` can be made. 634 635 .seealso: [](chapter_matrices), `Mat`, `MatGetRow()` 636 @*/ 637 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 638 { 639 PetscFunctionBegin; 640 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 641 if (ncols) PetscValidIntPointer(ncols, 3); 642 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 643 if (!mat->ops->restorerow) PetscFunctionReturn(PETSC_SUCCESS); 644 PetscUseTypeMethod(mat, restorerow, row, ncols, (PetscInt **)cols, (PetscScalar **)vals); 645 if (ncols) *ncols = 0; 646 if (cols) *cols = NULL; 647 if (vals) *vals = NULL; 648 PetscFunctionReturn(PETSC_SUCCESS); 649 } 650 651 /*@ 652 MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 653 You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag. 654 655 Not Collective 656 657 Input Parameter: 658 . mat - the matrix 659 660 Level: advanced 661 662 Note: 663 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. 664 665 .seealso: [](chapter_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()` 666 @*/ 667 PetscErrorCode MatGetRowUpperTriangular(Mat mat) 668 { 669 PetscFunctionBegin; 670 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 671 PetscValidType(mat, 1); 672 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 673 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 674 MatCheckPreallocated(mat, 1); 675 if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS); 676 PetscUseTypeMethod(mat, getrowuppertriangular); 677 PetscFunctionReturn(PETSC_SUCCESS); 678 } 679 680 /*@ 681 MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 682 683 Not Collective 684 685 Input Parameter: 686 . mat - the matrix 687 688 Level: advanced 689 690 Note: 691 This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`. 692 693 .seealso: [](chapter_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()` 694 @*/ 695 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat) 696 { 697 PetscFunctionBegin; 698 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 699 PetscValidType(mat, 1); 700 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 701 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 702 MatCheckPreallocated(mat, 1); 703 if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS); 704 PetscUseTypeMethod(mat, restorerowuppertriangular); 705 PetscFunctionReturn(PETSC_SUCCESS); 706 } 707 708 /*@C 709 MatSetOptionsPrefix - Sets the prefix used for searching for all 710 `Mat` options in the database. 711 712 Logically Collective 713 714 Input Parameters: 715 + A - the matrix 716 - prefix - the prefix to prepend to all option names 717 718 Level: advanced 719 720 Notes: 721 A hyphen (-) must NOT be given at the beginning of the prefix name. 722 The first character of all runtime options is AUTOMATICALLY the hyphen. 723 724 This is NOT used for options for the factorization of the matrix. Normally the 725 prefix is automatically passed in from the PC calling the factorization. To set 726 it directly use `MatSetOptionsPrefixFactor()` 727 728 .seealso: [](chapter_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()` 729 @*/ 730 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[]) 731 { 732 PetscFunctionBegin; 733 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 734 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix)); 735 PetscFunctionReturn(PETSC_SUCCESS); 736 } 737 738 /*@C 739 MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for 740 for matrices created with `MatGetFactor()` 741 742 Logically Collective 743 744 Input Parameters: 745 + A - the matrix 746 - prefix - the prefix to prepend to all option names for the factored matrix 747 748 Level: developer 749 750 Notes: 751 A hyphen (-) must NOT be given at the beginning of the prefix name. 752 The first character of all runtime options is AUTOMATICALLY the hyphen. 753 754 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 755 it directly when not using `KSP`/`PC` use `MatSetOptionsPrefixFactor()` 756 757 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()` 758 @*/ 759 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[]) 760 { 761 PetscFunctionBegin; 762 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 763 if (prefix) { 764 PetscValidCharPointer(prefix, 2); 765 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 766 if (prefix != A->factorprefix) { 767 PetscCall(PetscFree(A->factorprefix)); 768 PetscCall(PetscStrallocpy(prefix, &A->factorprefix)); 769 } 770 } else PetscCall(PetscFree(A->factorprefix)); 771 PetscFunctionReturn(PETSC_SUCCESS); 772 } 773 774 /*@C 775 MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for 776 for matrices created with `MatGetFactor()` 777 778 Logically Collective 779 780 Input Parameters: 781 + A - the matrix 782 - prefix - the prefix to prepend to all option names for the factored matrix 783 784 Level: developer 785 786 Notes: 787 A hyphen (-) must NOT be given at the beginning of the prefix name. 788 The first character of all runtime options is AUTOMATICALLY the hyphen. 789 790 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 791 it directly when not using `KSP`/`PC` use `MatAppendOptionsPrefixFactor()` 792 793 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`, 794 `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`, 795 `MatSetOptionsPrefix()` 796 @*/ 797 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[]) 798 { 799 size_t len1, len2, new_len; 800 801 PetscFunctionBegin; 802 PetscValidHeader(A, 1); 803 if (!prefix) PetscFunctionReturn(PETSC_SUCCESS); 804 if (!A->factorprefix) { 805 PetscCall(MatSetOptionsPrefixFactor(A, prefix)); 806 PetscFunctionReturn(PETSC_SUCCESS); 807 } 808 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 809 810 PetscCall(PetscStrlen(A->factorprefix, &len1)); 811 PetscCall(PetscStrlen(prefix, &len2)); 812 new_len = len1 + len2 + 1; 813 PetscCall(PetscRealloc(new_len * sizeof(*(A->factorprefix)), &A->factorprefix)); 814 PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1)); 815 PetscFunctionReturn(PETSC_SUCCESS); 816 } 817 818 /*@C 819 MatAppendOptionsPrefix - Appends to the prefix used for searching for all 820 matrix options in the database. 821 822 Logically Collective 823 824 Input Parameters: 825 + A - the matrix 826 - prefix - the prefix to prepend to all option names 827 828 Level: advanced 829 830 Note: 831 A hyphen (-) must NOT be given at the beginning of the prefix name. 832 The first character of all runtime options is AUTOMATICALLY the hyphen. 833 834 .seealso: [](chapter_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()` 835 @*/ 836 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[]) 837 { 838 PetscFunctionBegin; 839 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 840 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix)); 841 PetscFunctionReturn(PETSC_SUCCESS); 842 } 843 844 /*@C 845 MatGetOptionsPrefix - Gets the prefix used for searching for all 846 matrix options in the database. 847 848 Not Collective 849 850 Input Parameter: 851 . A - the matrix 852 853 Output Parameter: 854 . prefix - pointer to the prefix string used 855 856 Level: advanced 857 858 Fortran Note: 859 The user should pass in a string `prefix` of 860 sufficient length to hold the prefix. 861 862 .seealso: [](chapter_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()` 863 @*/ 864 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[]) 865 { 866 PetscFunctionBegin; 867 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 868 PetscValidPointer(prefix, 2); 869 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix)); 870 PetscFunctionReturn(PETSC_SUCCESS); 871 } 872 873 /*@ 874 MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by users. 875 876 Collective 877 878 Input Parameter: 879 . A - the matrix 880 881 Level: beginner 882 883 Notes: 884 The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`. 885 886 Users can reset the preallocation to access the original memory. 887 888 Currently only supported for `MATAIJ` matrices. 889 890 .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()` 891 @*/ 892 PetscErrorCode MatResetPreallocation(Mat A) 893 { 894 PetscFunctionBegin; 895 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 896 PetscValidType(A, 1); 897 PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A)); 898 PetscFunctionReturn(PETSC_SUCCESS); 899 } 900 901 /*@ 902 MatSetUp - Sets up the internal matrix data structures for later use. 903 904 Collective 905 906 Input Parameter: 907 . A - the matrix 908 909 Level: intermediate 910 911 Notes: 912 If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of 913 setting values in the matrix. 914 915 If a suitable preallocation routine is used, this function does not need to be called. 916 917 This routine is called internally by other matrix functions when needed so rarely needs to be called by users 918 919 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()` 920 @*/ 921 PetscErrorCode MatSetUp(Mat A) 922 { 923 PetscFunctionBegin; 924 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 925 if (!((PetscObject)A)->type_name) { 926 PetscMPIInt size; 927 928 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 929 PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ)); 930 } 931 if (!A->preallocated) PetscTryTypeMethod(A, setup); 932 PetscCall(PetscLayoutSetUp(A->rmap)); 933 PetscCall(PetscLayoutSetUp(A->cmap)); 934 A->preallocated = PETSC_TRUE; 935 PetscFunctionReturn(PETSC_SUCCESS); 936 } 937 938 #if defined(PETSC_HAVE_SAWS) 939 #include <petscviewersaws.h> 940 #endif 941 942 /*@C 943 MatViewFromOptions - View properties of the matrix based on options set in the options database 944 945 Collective 946 947 Input Parameters: 948 + A - the matrix 949 . obj - optional additional object that provides the options prefix to use 950 - name - command line option 951 952 Options Database Key: 953 . -mat_view [viewertype]:... - the viewer and its options 954 955 Level: intermediate 956 957 Notes: 958 .vb 959 If no value is provided ascii:stdout is used 960 ascii[:[filename][:[format][:append]]] defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab, 961 for example ascii::ascii_info prints just the information about the object not all details 962 unless :append is given filename opens in write mode, overwriting what was already there 963 binary[:[filename][:[format][:append]]] defaults to the file binaryoutput 964 draw[:drawtype[:filename]] for example, draw:tikz, draw:tikz:figure.tex or draw:x 965 socket[:port] defaults to the standard output port 966 saws[:communicatorname] publishes object to the Scientific Application Webserver (SAWs) 967 .ve 968 969 .seealso: [](chapter_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()` 970 @*/ 971 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[]) 972 { 973 PetscFunctionBegin; 974 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 975 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 976 PetscFunctionReturn(PETSC_SUCCESS); 977 } 978 979 /*@C 980 MatView - display information about a matrix in a variety ways 981 982 Collective 983 984 Input Parameters: 985 + mat - the matrix 986 - viewer - visualization context 987 988 Options Database Keys: 989 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 990 . -mat_view ::ascii_info_detail - Prints more detailed info 991 . -mat_view - Prints matrix in ASCII format 992 . -mat_view ::ascii_matlab - Prints matrix in Matlab format 993 . -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 994 . -display <name> - Sets display name (default is host) 995 . -draw_pause <sec> - Sets number of seconds to pause after display 996 . -mat_view socket - Sends matrix to socket, can be accessed from Matlab (see Users-Manual: ch_matlab for details) 997 . -viewer_socket_machine <machine> - 998 . -viewer_socket_port <port> - 999 . -mat_view binary - save matrix to file in binary format 1000 - -viewer_binary_filename <name> - 1001 1002 Level: beginner 1003 1004 Notes: 1005 The available visualization contexts include 1006 + `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices 1007 . `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD` 1008 . `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm 1009 - `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure 1010 1011 The user can open alternative visualization contexts with 1012 + `PetscViewerASCIIOpen()` - Outputs matrix to a specified file 1013 . `PetscViewerBinaryOpen()` - Outputs matrix in binary to a 1014 specified file; corresponding input uses MatLoad() 1015 . `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to 1016 an X window display 1017 - `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer. 1018 Currently only the sequential dense and AIJ 1019 matrix types support the Socket viewer. 1020 1021 The user can call `PetscViewerPushFormat()` to specify the output 1022 format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`, 1023 `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`). Available formats include 1024 + `PETSC_VIEWER_DEFAULT` - default, prints matrix contents 1025 . `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in Matlab format 1026 . `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros 1027 . `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse 1028 format common among all matrix types 1029 . `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific 1030 format (which is in many cases the same as the default) 1031 . `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix 1032 size and structure (not the matrix entries) 1033 - `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about 1034 the matrix structure 1035 1036 The ASCII viewers are only recommended for small matrices on at most a moderate number of processes, 1037 the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format. 1038 1039 In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer). 1040 1041 See the manual page for `MatLoad()` for the exact format of the binary file when the binary 1042 viewer is used. 1043 1044 See share/petsc/matlab/PetscBinaryRead.m for a Matlab code that can read in the binary file when the binary 1045 viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python. 1046 1047 One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure, 1048 and then use the following mouse functions. 1049 .vb 1050 left mouse: zoom in 1051 middle mouse: zoom out 1052 right mouse: continue with the simulation 1053 .ve 1054 1055 .seealso: [](chapter_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`, 1056 `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()` 1057 @*/ 1058 PetscErrorCode MatView(Mat mat, PetscViewer viewer) 1059 { 1060 PetscInt rows, cols, rbs, cbs; 1061 PetscBool isascii, isstring, issaws; 1062 PetscViewerFormat format; 1063 PetscMPIInt size; 1064 1065 PetscFunctionBegin; 1066 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1067 PetscValidType(mat, 1); 1068 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer)); 1069 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1070 PetscCheckSameComm(mat, 1, viewer, 2); 1071 1072 PetscCall(PetscViewerGetFormat(viewer, &format)); 1073 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 1074 if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS); 1075 1076 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 1077 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 1078 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws)); 1079 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"); 1080 1081 PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0)); 1082 if (isascii) { 1083 if (!mat->preallocated) { 1084 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n")); 1085 PetscFunctionReturn(PETSC_SUCCESS); 1086 } 1087 if (!mat->assembled) { 1088 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n")); 1089 PetscFunctionReturn(PETSC_SUCCESS); 1090 } 1091 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer)); 1092 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1093 MatNullSpace nullsp, transnullsp; 1094 1095 PetscCall(PetscViewerASCIIPushTab(viewer)); 1096 PetscCall(MatGetSize(mat, &rows, &cols)); 1097 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1098 if (rbs != 1 || cbs != 1) { 1099 if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs)); 1100 else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs)); 1101 } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols)); 1102 if (mat->factortype) { 1103 MatSolverType solver; 1104 PetscCall(MatFactorGetSolverType(mat, &solver)); 1105 PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver)); 1106 } 1107 if (mat->ops->getinfo) { 1108 MatInfo info; 1109 PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info)); 1110 PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated)); 1111 if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs)); 1112 } 1113 PetscCall(MatGetNullSpace(mat, &nullsp)); 1114 PetscCall(MatGetTransposeNullSpace(mat, &transnullsp)); 1115 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached null space\n")); 1116 if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached transposed null space\n")); 1117 PetscCall(MatGetNearNullSpace(mat, &nullsp)); 1118 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached near null space\n")); 1119 PetscCall(PetscViewerASCIIPushTab(viewer)); 1120 PetscCall(MatProductView(mat, viewer)); 1121 PetscCall(PetscViewerASCIIPopTab(viewer)); 1122 } 1123 } else if (issaws) { 1124 #if defined(PETSC_HAVE_SAWS) 1125 PetscMPIInt rank; 1126 1127 PetscCall(PetscObjectName((PetscObject)mat)); 1128 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 1129 if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer)); 1130 #endif 1131 } else if (isstring) { 1132 const char *type; 1133 PetscCall(MatGetType(mat, &type)); 1134 PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type)); 1135 PetscTryTypeMethod(mat, view, viewer); 1136 } 1137 if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) { 1138 PetscCall(PetscViewerASCIIPushTab(viewer)); 1139 PetscUseTypeMethod(mat, viewnative, viewer); 1140 PetscCall(PetscViewerASCIIPopTab(viewer)); 1141 } else if (mat->ops->view) { 1142 PetscCall(PetscViewerASCIIPushTab(viewer)); 1143 PetscUseTypeMethod(mat, view, viewer); 1144 PetscCall(PetscViewerASCIIPopTab(viewer)); 1145 } 1146 if (isascii) { 1147 PetscCall(PetscViewerGetFormat(viewer, &format)); 1148 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer)); 1149 } 1150 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1151 PetscFunctionReturn(PETSC_SUCCESS); 1152 } 1153 1154 #if defined(PETSC_USE_DEBUG) 1155 #include <../src/sys/totalview/tv_data_display.h> 1156 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat) 1157 { 1158 TV_add_row("Local rows", "int", &mat->rmap->n); 1159 TV_add_row("Local columns", "int", &mat->cmap->n); 1160 TV_add_row("Global rows", "int", &mat->rmap->N); 1161 TV_add_row("Global columns", "int", &mat->cmap->N); 1162 TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name); 1163 return TV_format_OK; 1164 } 1165 #endif 1166 1167 /*@C 1168 MatLoad - Loads a matrix that has been stored in binary/HDF5 format 1169 with `MatView()`. The matrix format is determined from the options database. 1170 Generates a parallel MPI matrix if the communicator has more than one 1171 processor. The default matrix type is `MATAIJ`. 1172 1173 Collective 1174 1175 Input Parameters: 1176 + mat - the newly loaded matrix, this needs to have been created with `MatCreate()` 1177 or some related function before a call to `MatLoad()` 1178 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer 1179 1180 Options Database Keys: 1181 Used with block matrix formats (`MATSEQBAIJ`, ...) to specify 1182 block size 1183 . -matload_block_size <bs> - set block size 1184 1185 Level: beginner 1186 1187 Notes: 1188 If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the 1189 `Mat` before calling this routine if you wish to set it from the options database. 1190 1191 `MatLoad()` automatically loads into the options database any options 1192 given in the file filename.info where filename is the name of the file 1193 that was passed to the `PetscViewerBinaryOpen()`. The options in the info 1194 file will be ignored if you use the -viewer_binary_skip_info option. 1195 1196 If the type or size of mat is not set before a call to `MatLoad()`, PETSc 1197 sets the default matrix type AIJ and sets the local and global sizes. 1198 If type and/or size is already set, then the same are used. 1199 1200 In parallel, each processor can load a subset of rows (or the 1201 entire matrix). This routine is especially useful when a large 1202 matrix is stored on disk and only part of it is desired on each 1203 processor. For example, a parallel solver may access only some of 1204 the rows from each processor. The algorithm used here reads 1205 relatively small blocks of data rather than reading the entire 1206 matrix and then subsetting it. 1207 1208 Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`. 1209 Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`, 1210 or the sequence like 1211 .vb 1212 `PetscViewer` v; 1213 `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v); 1214 `PetscViewerSetType`(v,`PETSCVIEWERBINARY`); 1215 `PetscViewerSetFromOptions`(v); 1216 `PetscViewerFileSetMode`(v,`FILE_MODE_READ`); 1217 `PetscViewerFileSetName`(v,"datafile"); 1218 .ve 1219 The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option 1220 $ -viewer_type {binary,hdf5} 1221 1222 See the example src/ksp/ksp/tutorials/ex27.c with the first approach, 1223 and src/mat/tutorials/ex10.c with the second approach. 1224 1225 In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks 1226 is read onto rank 0 and then shipped to its destination rank, one after another. 1227 Multiple objects, both matrices and vectors, can be stored within the same file. 1228 Their PetscObject name is ignored; they are loaded in the order of their storage. 1229 1230 Most users should not need to know the details of the binary storage 1231 format, since `MatLoad()` and `MatView()` completely hide these details. 1232 But for anyone who's interested, the standard binary matrix storage 1233 format is 1234 1235 .vb 1236 PetscInt MAT_FILE_CLASSID 1237 PetscInt number of rows 1238 PetscInt number of columns 1239 PetscInt total number of nonzeros 1240 PetscInt *number nonzeros in each row 1241 PetscInt *column indices of all nonzeros (starting index is zero) 1242 PetscScalar *values of all nonzeros 1243 .ve 1244 1245 PETSc automatically does the byte swapping for 1246 machines that store the bytes reversed. Thus if you write your own binary 1247 read/write routines you have to swap the bytes; see `PetscBinaryRead()` 1248 and `PetscBinaryWrite()` to see how this may be done. 1249 1250 In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used. 1251 Each processor's chunk is loaded independently by its owning rank. 1252 Multiple objects, both matrices and vectors, can be stored within the same file. 1253 They are looked up by their PetscObject name. 1254 1255 As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use 1256 by default the same structure and naming of the AIJ arrays and column count 1257 within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g. 1258 $ save example.mat A b -v7.3 1259 can be directly read by this routine (see Reference 1 for details). 1260 1261 Depending on your MATLAB version, this format might be a default, 1262 otherwise you can set it as default in Preferences. 1263 1264 Unless -nocompression flag is used to save the file in MATLAB, 1265 PETSc must be configured with ZLIB package. 1266 1267 See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c 1268 1269 This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5` 1270 1271 Corresponding `MatView()` is not yet implemented. 1272 1273 The loaded matrix is actually a transpose of the original one in MATLAB, 1274 unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above). 1275 With this format, matrix is automatically transposed by PETSc, 1276 unless the matrix is marked as SPD or symmetric 1277 (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`). 1278 1279 References: 1280 . * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version 1281 1282 .seealso: [](chapter_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()` 1283 @*/ 1284 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer) 1285 { 1286 PetscBool flg; 1287 1288 PetscFunctionBegin; 1289 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1290 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1291 1292 if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ)); 1293 1294 flg = PETSC_FALSE; 1295 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL)); 1296 if (flg) { 1297 PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE)); 1298 PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE)); 1299 } 1300 flg = PETSC_FALSE; 1301 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL)); 1302 if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE)); 1303 1304 PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0)); 1305 PetscUseTypeMethod(mat, load, viewer); 1306 PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0)); 1307 PetscFunctionReturn(PETSC_SUCCESS); 1308 } 1309 1310 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant) 1311 { 1312 Mat_Redundant *redund = *redundant; 1313 1314 PetscFunctionBegin; 1315 if (redund) { 1316 if (redund->matseq) { /* via MatCreateSubMatrices() */ 1317 PetscCall(ISDestroy(&redund->isrow)); 1318 PetscCall(ISDestroy(&redund->iscol)); 1319 PetscCall(MatDestroySubMatrices(1, &redund->matseq)); 1320 } else { 1321 PetscCall(PetscFree2(redund->send_rank, redund->recv_rank)); 1322 PetscCall(PetscFree(redund->sbuf_j)); 1323 PetscCall(PetscFree(redund->sbuf_a)); 1324 for (PetscInt i = 0; i < redund->nrecvs; i++) { 1325 PetscCall(PetscFree(redund->rbuf_j[i])); 1326 PetscCall(PetscFree(redund->rbuf_a[i])); 1327 } 1328 PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a)); 1329 } 1330 1331 if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm)); 1332 PetscCall(PetscFree(redund)); 1333 } 1334 PetscFunctionReturn(PETSC_SUCCESS); 1335 } 1336 1337 /*@C 1338 MatDestroy - Frees space taken by a matrix. 1339 1340 Collective 1341 1342 Input Parameter: 1343 . A - the matrix 1344 1345 Level: beginner 1346 1347 Developer Note: 1348 Some special arrays of matrices are not destroyed in this routine but instead by the routines called by 1349 `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines. 1350 `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes 1351 if changes are needed here. 1352 1353 .seealso: [](chapter_matrices), `Mat`, `MatCreate()` 1354 @*/ 1355 PetscErrorCode MatDestroy(Mat *A) 1356 { 1357 PetscFunctionBegin; 1358 if (!*A) PetscFunctionReturn(PETSC_SUCCESS); 1359 PetscValidHeaderSpecific(*A, MAT_CLASSID, 1); 1360 if (--((PetscObject)(*A))->refct > 0) { 1361 *A = NULL; 1362 PetscFunctionReturn(PETSC_SUCCESS); 1363 } 1364 1365 /* if memory was published with SAWs then destroy it */ 1366 PetscCall(PetscObjectSAWsViewOff((PetscObject)*A)); 1367 PetscTryTypeMethod((*A), destroy); 1368 1369 PetscCall(PetscFree((*A)->factorprefix)); 1370 PetscCall(PetscFree((*A)->defaultvectype)); 1371 PetscCall(PetscFree((*A)->defaultrandtype)); 1372 PetscCall(PetscFree((*A)->bsizes)); 1373 PetscCall(PetscFree((*A)->solvertype)); 1374 for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i])); 1375 if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL; 1376 PetscCall(MatDestroy_Redundant(&(*A)->redundant)); 1377 PetscCall(MatProductClear(*A)); 1378 PetscCall(MatNullSpaceDestroy(&(*A)->nullsp)); 1379 PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp)); 1380 PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp)); 1381 PetscCall(MatDestroy(&(*A)->schur)); 1382 PetscCall(PetscLayoutDestroy(&(*A)->rmap)); 1383 PetscCall(PetscLayoutDestroy(&(*A)->cmap)); 1384 PetscCall(PetscHeaderDestroy(A)); 1385 PetscFunctionReturn(PETSC_SUCCESS); 1386 } 1387 1388 /*@C 1389 MatSetValues - Inserts or adds a block of values into a matrix. 1390 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1391 MUST be called after all calls to `MatSetValues()` have been completed. 1392 1393 Not Collective 1394 1395 Input Parameters: 1396 + mat - the matrix 1397 . v - a logically two-dimensional array of values 1398 . m - the number of rows 1399 . idxm - the global indices of the rows 1400 . n - the number of columns 1401 . idxn - the global indices of the columns 1402 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1403 1404 Level: beginner 1405 1406 Notes: 1407 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1408 1409 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1410 options cannot be mixed without intervening calls to the assembly 1411 routines. 1412 1413 `MatSetValues()` uses 0-based row and column numbers in Fortran 1414 as well as in C. 1415 1416 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1417 simply ignored. This allows easily inserting element stiffness matrices 1418 with homogeneous Dirchlet boundary conditions that you don't want represented 1419 in the matrix. 1420 1421 Efficiency Alert: 1422 The routine `MatSetValuesBlocked()` may offer much better efficiency 1423 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1424 1425 Developer Note: 1426 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1427 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1428 1429 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1430 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1431 @*/ 1432 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1433 { 1434 PetscFunctionBeginHot; 1435 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1436 PetscValidType(mat, 1); 1437 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1438 PetscValidIntPointer(idxm, 3); 1439 PetscValidIntPointer(idxn, 5); 1440 MatCheckPreallocated(mat, 1); 1441 1442 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1443 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1444 1445 if (PetscDefined(USE_DEBUG)) { 1446 PetscInt i, j; 1447 1448 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1449 for (i = 0; i < m; i++) { 1450 for (j = 0; j < n; j++) { 1451 if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j])) 1452 #if defined(PETSC_USE_COMPLEX) 1453 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]); 1454 #else 1455 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]); 1456 #endif 1457 } 1458 } 1459 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); 1460 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); 1461 } 1462 1463 if (mat->assembled) { 1464 mat->was_assembled = PETSC_TRUE; 1465 mat->assembled = PETSC_FALSE; 1466 } 1467 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1468 PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv); 1469 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1470 PetscFunctionReturn(PETSC_SUCCESS); 1471 } 1472 1473 /*@C 1474 MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns 1475 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1476 MUST be called after all calls to `MatSetValues()` have been completed. 1477 1478 Not Collective 1479 1480 Input Parameters: 1481 + mat - the matrix 1482 . v - a logically two-dimensional array of values 1483 . ism - the rows to provide 1484 . isn - the columns to provide 1485 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1486 1487 Level: beginner 1488 1489 Notes: 1490 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1491 1492 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1493 options cannot be mixed without intervening calls to the assembly 1494 routines. 1495 1496 `MatSetValues()` uses 0-based row and column numbers in Fortran 1497 as well as in C. 1498 1499 Negative indices may be passed in `ism` and `isn`, these rows and columns are 1500 simply ignored. This allows easily inserting element stiffness matrices 1501 with homogeneous Dirchlet boundary conditions that you don't want represented 1502 in the matrix. 1503 1504 Efficiency Alert: 1505 The routine `MatSetValuesBlocked()` may offer much better efficiency 1506 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1507 1508 This is currently not optimized for any particular `ISType` 1509 1510 Developer Notes: 1511 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1512 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1513 1514 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1515 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()` 1516 @*/ 1517 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv) 1518 { 1519 PetscInt m, n; 1520 const PetscInt *rows, *cols; 1521 1522 PetscFunctionBeginHot; 1523 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1524 PetscCall(ISGetIndices(ism, &rows)); 1525 PetscCall(ISGetIndices(isn, &cols)); 1526 PetscCall(ISGetLocalSize(ism, &m)); 1527 PetscCall(ISGetLocalSize(isn, &n)); 1528 PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv)); 1529 PetscCall(ISRestoreIndices(ism, &rows)); 1530 PetscCall(ISRestoreIndices(isn, &cols)); 1531 PetscFunctionReturn(PETSC_SUCCESS); 1532 } 1533 1534 /*@ 1535 MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1536 values into a matrix 1537 1538 Not Collective 1539 1540 Input Parameters: 1541 + mat - the matrix 1542 . row - the (block) row to set 1543 - v - a logically two-dimensional array of values 1544 1545 Level: intermediate 1546 1547 Notes: 1548 The values, `v`, are column-oriented (for the block version) and sorted 1549 1550 All the nonzeros in the row must be provided 1551 1552 The matrix must have previously had its column indices set, likely by having been assembled. 1553 1554 The row must belong to this process 1555 1556 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1557 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()` 1558 @*/ 1559 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[]) 1560 { 1561 PetscInt globalrow; 1562 1563 PetscFunctionBegin; 1564 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1565 PetscValidType(mat, 1); 1566 PetscValidScalarPointer(v, 3); 1567 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow)); 1568 PetscCall(MatSetValuesRow(mat, globalrow, v)); 1569 PetscFunctionReturn(PETSC_SUCCESS); 1570 } 1571 1572 /*@ 1573 MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1574 values into a matrix 1575 1576 Not Collective 1577 1578 Input Parameters: 1579 + mat - the matrix 1580 . row - the (block) row to set 1581 - 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 1582 1583 Level: advanced 1584 1585 Notes: 1586 The values, `v`, are column-oriented for the block version. 1587 1588 All the nonzeros in the row must be provided 1589 1590 THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used. 1591 1592 The row must belong to this process 1593 1594 .seealso: [](chapter_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1595 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()` 1596 @*/ 1597 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[]) 1598 { 1599 PetscFunctionBeginHot; 1600 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1601 PetscValidType(mat, 1); 1602 MatCheckPreallocated(mat, 1); 1603 PetscValidScalarPointer(v, 3); 1604 PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values"); 1605 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1606 mat->insertmode = INSERT_VALUES; 1607 1608 if (mat->assembled) { 1609 mat->was_assembled = PETSC_TRUE; 1610 mat->assembled = PETSC_FALSE; 1611 } 1612 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1613 PetscUseTypeMethod(mat, setvaluesrow, row, v); 1614 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1615 PetscFunctionReturn(PETSC_SUCCESS); 1616 } 1617 1618 /*@ 1619 MatSetValuesStencil - Inserts or adds a block of values into a matrix. 1620 Using structured grid indexing 1621 1622 Not Collective 1623 1624 Input Parameters: 1625 + mat - the matrix 1626 . m - number of rows being entered 1627 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered 1628 . n - number of columns being entered 1629 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered 1630 . v - a logically two-dimensional array of values 1631 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values 1632 1633 Level: beginner 1634 1635 Notes: 1636 By default the values, `v`, are row-oriented. See `MatSetOption()` for other options. 1637 1638 Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1639 options cannot be mixed without intervening calls to the assembly 1640 routines. 1641 1642 The grid coordinates are across the entire grid, not just the local portion 1643 1644 `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran 1645 as well as in C. 1646 1647 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1648 1649 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1650 or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1651 1652 The columns and rows in the stencil passed in MUST be contained within the 1653 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1654 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1655 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1656 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1657 1658 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 1659 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 1660 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 1661 `DM_BOUNDARY_PERIODIC` boundary type. 1662 1663 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 1664 a single value per point) you can skip filling those indices. 1665 1666 Inspired by the structured grid interface to the HYPRE package 1667 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1668 1669 Efficiency Alert: 1670 The routine `MatSetValuesBlockedStencil()` may offer much better efficiency 1671 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1672 1673 Fortran Note: 1674 `idxm` and `idxn` should be declared as 1675 $ MatStencil idxm(4,m),idxn(4,n) 1676 and the values inserted using 1677 .vb 1678 idxm(MatStencil_i,1) = i 1679 idxm(MatStencil_j,1) = j 1680 idxm(MatStencil_k,1) = k 1681 idxm(MatStencil_c,1) = c 1682 etc 1683 .ve 1684 1685 .seealso: [](chapter_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1686 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil` 1687 @*/ 1688 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1689 { 1690 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1691 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1692 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1693 1694 PetscFunctionBegin; 1695 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1696 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1697 PetscValidType(mat, 1); 1698 PetscValidPointer(idxm, 3); 1699 PetscValidPointer(idxn, 5); 1700 1701 if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 1702 jdxm = buf; 1703 jdxn = buf + m; 1704 } else { 1705 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1706 jdxm = bufm; 1707 jdxn = bufn; 1708 } 1709 for (i = 0; i < m; i++) { 1710 for (j = 0; j < 3 - sdim; j++) dxm++; 1711 tmp = *dxm++ - starts[0]; 1712 for (j = 0; j < dim - 1; j++) { 1713 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1714 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1715 } 1716 if (mat->stencil.noc) dxm++; 1717 jdxm[i] = tmp; 1718 } 1719 for (i = 0; i < n; i++) { 1720 for (j = 0; j < 3 - sdim; j++) dxn++; 1721 tmp = *dxn++ - starts[0]; 1722 for (j = 0; j < dim - 1; j++) { 1723 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1724 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1725 } 1726 if (mat->stencil.noc) dxn++; 1727 jdxn[i] = tmp; 1728 } 1729 PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv)); 1730 PetscCall(PetscFree2(bufm, bufn)); 1731 PetscFunctionReturn(PETSC_SUCCESS); 1732 } 1733 1734 /*@ 1735 MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix. 1736 Using structured grid indexing 1737 1738 Not Collective 1739 1740 Input Parameters: 1741 + mat - the matrix 1742 . m - number of rows being entered 1743 . idxm - grid coordinates for matrix rows being entered 1744 . n - number of columns being entered 1745 . idxn - grid coordinates for matrix columns being entered 1746 . v - a logically two-dimensional array of values 1747 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values 1748 1749 Level: beginner 1750 1751 Notes: 1752 By default the values, `v`, are row-oriented and unsorted. 1753 See `MatSetOption()` for other options. 1754 1755 Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1756 options cannot be mixed without intervening calls to the assembly 1757 routines. 1758 1759 The grid coordinates are across the entire grid, not just the local portion 1760 1761 `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran 1762 as well as in C. 1763 1764 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1765 1766 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1767 or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1768 1769 The columns and rows in the stencil passed in MUST be contained within the 1770 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1771 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1772 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1773 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1774 1775 Negative indices may be passed in idxm and idxn, these rows and columns are 1776 simply ignored. This allows easily inserting element stiffness matrices 1777 with homogeneous Dirchlet boundary conditions that you don't want represented 1778 in the matrix. 1779 1780 Inspired by the structured grid interface to the HYPRE package 1781 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1782 1783 Fortran Note: 1784 `idxm` and `idxn` should be declared as 1785 $ MatStencil idxm(4,m),idxn(4,n) 1786 and the values inserted using 1787 .vb 1788 idxm(MatStencil_i,1) = i 1789 idxm(MatStencil_j,1) = j 1790 idxm(MatStencil_k,1) = k 1791 etc 1792 .ve 1793 1794 .seealso: [](chapter_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1795 `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`, 1796 `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` 1797 @*/ 1798 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1799 { 1800 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1801 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1802 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1803 1804 PetscFunctionBegin; 1805 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1806 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1807 PetscValidType(mat, 1); 1808 PetscValidPointer(idxm, 3); 1809 PetscValidPointer(idxn, 5); 1810 PetscValidScalarPointer(v, 6); 1811 1812 if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 1813 jdxm = buf; 1814 jdxn = buf + m; 1815 } else { 1816 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1817 jdxm = bufm; 1818 jdxn = bufn; 1819 } 1820 for (i = 0; i < m; i++) { 1821 for (j = 0; j < 3 - sdim; j++) dxm++; 1822 tmp = *dxm++ - starts[0]; 1823 for (j = 0; j < sdim - 1; j++) { 1824 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1825 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1826 } 1827 dxm++; 1828 jdxm[i] = tmp; 1829 } 1830 for (i = 0; i < n; i++) { 1831 for (j = 0; j < 3 - sdim; j++) dxn++; 1832 tmp = *dxn++ - starts[0]; 1833 for (j = 0; j < sdim - 1; j++) { 1834 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1835 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1836 } 1837 dxn++; 1838 jdxn[i] = tmp; 1839 } 1840 PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv)); 1841 PetscCall(PetscFree2(bufm, bufn)); 1842 PetscFunctionReturn(PETSC_SUCCESS); 1843 } 1844 1845 /*@ 1846 MatSetStencil - Sets the grid information for setting values into a matrix via 1847 `MatSetValuesStencil()` 1848 1849 Not Collective 1850 1851 Input Parameters: 1852 + mat - the matrix 1853 . dim - dimension of the grid 1, 2, or 3 1854 . dims - number of grid points in x, y, and z direction, including ghost points on your processor 1855 . starts - starting point of ghost nodes on your processor in x, y, and z direction 1856 - dof - number of degrees of freedom per node 1857 1858 Level: beginner 1859 1860 Notes: 1861 Inspired by the structured grid interface to the HYPRE package 1862 (www.llnl.gov/CASC/hyper) 1863 1864 For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the 1865 user. 1866 1867 .seealso: [](chapter_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1868 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()` 1869 @*/ 1870 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof) 1871 { 1872 PetscFunctionBegin; 1873 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1874 PetscValidIntPointer(dims, 3); 1875 PetscValidIntPointer(starts, 4); 1876 1877 mat->stencil.dim = dim + (dof > 1); 1878 for (PetscInt i = 0; i < dim; i++) { 1879 mat->stencil.dims[i] = dims[dim - i - 1]; /* copy the values in backwards */ 1880 mat->stencil.starts[i] = starts[dim - i - 1]; 1881 } 1882 mat->stencil.dims[dim] = dof; 1883 mat->stencil.starts[dim] = 0; 1884 mat->stencil.noc = (PetscBool)(dof == 1); 1885 PetscFunctionReturn(PETSC_SUCCESS); 1886 } 1887 1888 /*@C 1889 MatSetValuesBlocked - Inserts or adds a block of values into a matrix. 1890 1891 Not Collective 1892 1893 Input Parameters: 1894 + mat - the matrix 1895 . v - a logically two-dimensional array of values 1896 . m - the number of block rows 1897 . idxm - the global block indices 1898 . n - the number of block columns 1899 . idxn - the global block indices 1900 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values 1901 1902 Level: intermediate 1903 1904 Notes: 1905 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call 1906 MatXXXXSetPreallocation() or `MatSetUp()` before using this routine. 1907 1908 The `m` and `n` count the NUMBER of blocks in the row direction and column direction, 1909 NOT the total number of rows/columns; for example, if the block size is 2 and 1910 you are passing in values for rows 2,3,4,5 then m would be 2 (not 4). 1911 The values in idxm would be 1 2; that is the first index for each block divided by 1912 the block size. 1913 1914 You must call `MatSetBlockSize()` when constructing this matrix (before 1915 preallocating it). 1916 1917 By default the values, `v`, are row-oriented, so the layout of 1918 `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options. 1919 1920 Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES` 1921 options cannot be mixed without intervening calls to the assembly 1922 routines. 1923 1924 `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran 1925 as well as in C. 1926 1927 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1928 simply ignored. This allows easily inserting element stiffness matrices 1929 with homogeneous Dirchlet boundary conditions that you don't want represented 1930 in the matrix. 1931 1932 Each time an entry is set within a sparse matrix via `MatSetValues()`, 1933 internal searching must be done to determine where to place the 1934 data in the matrix storage space. By instead inserting blocks of 1935 entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is 1936 reduced. 1937 1938 Example: 1939 .vb 1940 Suppose m=n=2 and block size(bs) = 2 The array is 1941 1942 1 2 | 3 4 1943 5 6 | 7 8 1944 - - - | - - - 1945 9 10 | 11 12 1946 13 14 | 15 16 1947 1948 v[] should be passed in like 1949 v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] 1950 1951 If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then 1952 v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16] 1953 .ve 1954 1955 .seealso: [](chapter_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()` 1956 @*/ 1957 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1958 { 1959 PetscFunctionBeginHot; 1960 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1961 PetscValidType(mat, 1); 1962 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1963 PetscValidIntPointer(idxm, 3); 1964 PetscValidIntPointer(idxn, 5); 1965 MatCheckPreallocated(mat, 1); 1966 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1967 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1968 if (PetscDefined(USE_DEBUG)) { 1969 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1970 PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 1971 } 1972 if (PetscDefined(USE_DEBUG)) { 1973 PetscInt rbs, cbs, M, N, i; 1974 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1975 PetscCall(MatGetSize(mat, &M, &N)); 1976 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); 1977 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); 1978 } 1979 if (mat->assembled) { 1980 mat->was_assembled = PETSC_TRUE; 1981 mat->assembled = PETSC_FALSE; 1982 } 1983 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1984 if (mat->ops->setvaluesblocked) { 1985 PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv); 1986 } else { 1987 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn; 1988 PetscInt i, j, bs, cbs; 1989 1990 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 1991 if (m * bs + n * cbs <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 1992 iidxm = buf; 1993 iidxn = buf + m * bs; 1994 } else { 1995 PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc)); 1996 iidxm = bufr; 1997 iidxn = bufc; 1998 } 1999 for (i = 0; i < m; i++) { 2000 for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j; 2001 } 2002 if (m != n || bs != cbs || idxm != idxn) { 2003 for (i = 0; i < n; i++) { 2004 for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j; 2005 } 2006 } else iidxn = iidxm; 2007 PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv)); 2008 PetscCall(PetscFree2(bufr, bufc)); 2009 } 2010 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2011 PetscFunctionReturn(PETSC_SUCCESS); 2012 } 2013 2014 /*@C 2015 MatGetValues - Gets a block of local values from a matrix. 2016 2017 Not Collective; can only return values that are owned by the give process 2018 2019 Input Parameters: 2020 + mat - the matrix 2021 . v - a logically two-dimensional array for storing the values 2022 . m - the number of rows 2023 . idxm - the global indices of the rows 2024 . n - the number of columns 2025 - idxn - the global indices of the columns 2026 2027 Level: advanced 2028 2029 Notes: 2030 The user must allocate space (m*n `PetscScalar`s) for the values, `v`. 2031 The values, `v`, are then returned in a row-oriented format, 2032 analogous to that used by default in `MatSetValues()`. 2033 2034 `MatGetValues()` uses 0-based row and column numbers in 2035 Fortran as well as in C. 2036 2037 `MatGetValues()` requires that the matrix has been assembled 2038 with `MatAssemblyBegin()`/`MatAssemblyEnd()`. Thus, calls to 2039 `MatSetValues()` and `MatGetValues()` CANNOT be made in succession 2040 without intermediate matrix assembly. 2041 2042 Negative row or column indices will be ignored and those locations in `v` will be 2043 left unchanged. 2044 2045 For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI rank. 2046 That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable 2047 from `MatGetOwnershipRange`(mat,&rstart,&rend). 2048 2049 .seealso: [](chapter_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()` 2050 @*/ 2051 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) 2052 { 2053 PetscFunctionBegin; 2054 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2055 PetscValidType(mat, 1); 2056 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); 2057 PetscValidIntPointer(idxm, 3); 2058 PetscValidIntPointer(idxn, 5); 2059 PetscValidScalarPointer(v, 6); 2060 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2061 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2062 MatCheckPreallocated(mat, 1); 2063 2064 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2065 PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v); 2066 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2067 PetscFunctionReturn(PETSC_SUCCESS); 2068 } 2069 2070 /*@C 2071 MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices 2072 defined previously by `MatSetLocalToGlobalMapping()` 2073 2074 Not Collective 2075 2076 Input Parameters: 2077 + mat - the matrix 2078 . nrow - number of rows 2079 . irow - the row local indices 2080 . ncol - number of columns 2081 - icol - the column local indices 2082 2083 Output Parameter: 2084 . y - a logically two-dimensional array of values 2085 2086 Level: advanced 2087 2088 Notes: 2089 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine. 2090 2091 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, 2092 are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can 2093 determine if the resulting global row associated with the local row r is owned by the requesting MPI rank by applying the `ISLocalToGlobalMapping` set 2094 with `MatSetLocalToGlobalMapping()`. 2095 2096 Developer Note: 2097 This is labelled with C so does not automatically generate Fortran stubs and interfaces 2098 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2099 2100 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2101 `MatSetValuesLocal()`, `MatGetValues()` 2102 @*/ 2103 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[]) 2104 { 2105 PetscFunctionBeginHot; 2106 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2107 PetscValidType(mat, 1); 2108 MatCheckPreallocated(mat, 1); 2109 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */ 2110 PetscValidIntPointer(irow, 3); 2111 PetscValidIntPointer(icol, 5); 2112 if (PetscDefined(USE_DEBUG)) { 2113 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2114 PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2115 } 2116 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2117 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2118 if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y); 2119 else { 2120 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm; 2121 if ((nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2122 irowm = buf; 2123 icolm = buf + nrow; 2124 } else { 2125 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2126 irowm = bufr; 2127 icolm = bufc; 2128 } 2129 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping())."); 2130 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping())."); 2131 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm)); 2132 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm)); 2133 PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y)); 2134 PetscCall(PetscFree2(bufr, bufc)); 2135 } 2136 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2137 PetscFunctionReturn(PETSC_SUCCESS); 2138 } 2139 2140 /*@ 2141 MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and 2142 the same size. Currently, this can only be called once and creates the given matrix. 2143 2144 Not Collective 2145 2146 Input Parameters: 2147 + mat - the matrix 2148 . nb - the number of blocks 2149 . bs - the number of rows (and columns) in each block 2150 . rows - a concatenation of the rows for each block 2151 - v - a concatenation of logically two-dimensional arrays of values 2152 2153 Level: advanced 2154 2155 Note: 2156 `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values 2157 2158 In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix. 2159 2160 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 2161 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()` 2162 @*/ 2163 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[]) 2164 { 2165 PetscFunctionBegin; 2166 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2167 PetscValidType(mat, 1); 2168 PetscValidIntPointer(rows, 4); 2169 PetscValidScalarPointer(v, 5); 2170 PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2171 2172 PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0)); 2173 if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v); 2174 else { 2175 for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES)); 2176 } 2177 PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0)); 2178 PetscFunctionReturn(PETSC_SUCCESS); 2179 } 2180 2181 /*@ 2182 MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by 2183 the routine `MatSetValuesLocal()` to allow users to insert matrix entries 2184 using a local (per-processor) numbering. 2185 2186 Not Collective 2187 2188 Input Parameters: 2189 + x - the matrix 2190 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()` 2191 - cmapping - column mapping 2192 2193 Level: intermediate 2194 2195 Note: 2196 If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix 2197 2198 .seealso: [](chapter_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()` 2199 @*/ 2200 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping) 2201 { 2202 PetscFunctionBegin; 2203 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 2204 PetscValidType(x, 1); 2205 if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2); 2206 if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3); 2207 if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping); 2208 else { 2209 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping)); 2210 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping)); 2211 } 2212 PetscFunctionReturn(PETSC_SUCCESS); 2213 } 2214 2215 /*@ 2216 MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()` 2217 2218 Not Collective 2219 2220 Input Parameter: 2221 . A - the matrix 2222 2223 Output Parameters: 2224 + rmapping - row mapping 2225 - cmapping - column mapping 2226 2227 Level: advanced 2228 2229 .seealso: [](chapter_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()` 2230 @*/ 2231 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping) 2232 { 2233 PetscFunctionBegin; 2234 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2235 PetscValidType(A, 1); 2236 if (rmapping) { 2237 PetscValidPointer(rmapping, 2); 2238 *rmapping = A->rmap->mapping; 2239 } 2240 if (cmapping) { 2241 PetscValidPointer(cmapping, 3); 2242 *cmapping = A->cmap->mapping; 2243 } 2244 PetscFunctionReturn(PETSC_SUCCESS); 2245 } 2246 2247 /*@ 2248 MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix 2249 2250 Logically Collective 2251 2252 Input Parameters: 2253 + A - the matrix 2254 . rmap - row layout 2255 - cmap - column layout 2256 2257 Level: advanced 2258 2259 Note: 2260 The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called. 2261 2262 .seealso: [](chapter_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()` 2263 @*/ 2264 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap) 2265 { 2266 PetscFunctionBegin; 2267 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2268 PetscCall(PetscLayoutReference(rmap, &A->rmap)); 2269 PetscCall(PetscLayoutReference(cmap, &A->cmap)); 2270 PetscFunctionReturn(PETSC_SUCCESS); 2271 } 2272 2273 /*@ 2274 MatGetLayouts - Gets the `PetscLayout` objects for rows and columns 2275 2276 Not Collective 2277 2278 Input Parameter: 2279 . A - the matrix 2280 2281 Output Parameters: 2282 + rmap - row layout 2283 - cmap - column layout 2284 2285 Level: advanced 2286 2287 .seealso: [](chapter_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()` 2288 @*/ 2289 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap) 2290 { 2291 PetscFunctionBegin; 2292 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2293 PetscValidType(A, 1); 2294 if (rmap) { 2295 PetscValidPointer(rmap, 2); 2296 *rmap = A->rmap; 2297 } 2298 if (cmap) { 2299 PetscValidPointer(cmap, 3); 2300 *cmap = A->cmap; 2301 } 2302 PetscFunctionReturn(PETSC_SUCCESS); 2303 } 2304 2305 /*@C 2306 MatSetValuesLocal - Inserts or adds values into certain locations of a matrix, 2307 using a local numbering of the nodes. 2308 2309 Not Collective 2310 2311 Input Parameters: 2312 + mat - the matrix 2313 . nrow - number of rows 2314 . irow - the row local indices 2315 . ncol - number of columns 2316 . icol - the column local indices 2317 . y - a logically two-dimensional array of values 2318 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2319 2320 Level: intermediate 2321 2322 Notes: 2323 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 2324 `MatSetUp()` before using this routine 2325 2326 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine 2327 2328 Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2329 options cannot be mixed without intervening calls to the assembly 2330 routines. 2331 2332 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2333 MUST be called after all calls to `MatSetValuesLocal()` have been completed. 2334 2335 Developer Note: 2336 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2337 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2338 2339 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2340 `MatGetValuesLocal()` 2341 @*/ 2342 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2343 { 2344 PetscFunctionBeginHot; 2345 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2346 PetscValidType(mat, 1); 2347 MatCheckPreallocated(mat, 1); 2348 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2349 PetscValidIntPointer(irow, 3); 2350 PetscValidIntPointer(icol, 5); 2351 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2352 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2353 if (PetscDefined(USE_DEBUG)) { 2354 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2355 PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2356 } 2357 2358 if (mat->assembled) { 2359 mat->was_assembled = PETSC_TRUE; 2360 mat->assembled = PETSC_FALSE; 2361 } 2362 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2363 if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv); 2364 else { 2365 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2366 const PetscInt *irowm, *icolm; 2367 2368 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2369 bufr = buf; 2370 bufc = buf + nrow; 2371 irowm = bufr; 2372 icolm = bufc; 2373 } else { 2374 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2375 irowm = bufr; 2376 icolm = bufc; 2377 } 2378 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr)); 2379 else irowm = irow; 2380 if (mat->cmap->mapping) { 2381 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2382 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc)); 2383 } else icolm = irowm; 2384 } else icolm = icol; 2385 PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv)); 2386 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2387 } 2388 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2389 PetscFunctionReturn(PETSC_SUCCESS); 2390 } 2391 2392 /*@C 2393 MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix, 2394 using a local ordering of the nodes a block at a time. 2395 2396 Not Collective 2397 2398 Input Parameters: 2399 + x - the matrix 2400 . nrow - number of rows 2401 . irow - the row local indices 2402 . ncol - number of columns 2403 . icol - the column local indices 2404 . y - a logically two-dimensional array of values 2405 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2406 2407 Level: intermediate 2408 2409 Notes: 2410 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 2411 `MatSetUp()` before using this routine 2412 2413 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()` 2414 before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the 2415 2416 Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2417 options cannot be mixed without intervening calls to the assembly 2418 routines. 2419 2420 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2421 MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed. 2422 2423 Developer Note: 2424 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2425 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2426 2427 .seealso: [](chapter_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, 2428 `MatSetValuesLocal()`, `MatSetValuesBlocked()` 2429 @*/ 2430 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2431 { 2432 PetscFunctionBeginHot; 2433 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2434 PetscValidType(mat, 1); 2435 MatCheckPreallocated(mat, 1); 2436 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2437 PetscValidIntPointer(irow, 3); 2438 PetscValidIntPointer(icol, 5); 2439 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2440 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2441 if (PetscDefined(USE_DEBUG)) { 2442 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2443 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); 2444 } 2445 2446 if (mat->assembled) { 2447 mat->was_assembled = PETSC_TRUE; 2448 mat->assembled = PETSC_FALSE; 2449 } 2450 if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */ 2451 PetscInt irbs, rbs; 2452 PetscCall(MatGetBlockSizes(mat, &rbs, NULL)); 2453 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs)); 2454 PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs); 2455 } 2456 if (PetscUnlikelyDebug(mat->cmap->mapping)) { 2457 PetscInt icbs, cbs; 2458 PetscCall(MatGetBlockSizes(mat, NULL, &cbs)); 2459 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs)); 2460 PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs); 2461 } 2462 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2463 if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv); 2464 else { 2465 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2466 const PetscInt *irowm, *icolm; 2467 2468 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2469 bufr = buf; 2470 bufc = buf + nrow; 2471 irowm = bufr; 2472 icolm = bufc; 2473 } else { 2474 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2475 irowm = bufr; 2476 icolm = bufc; 2477 } 2478 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr)); 2479 else irowm = irow; 2480 if (mat->cmap->mapping) { 2481 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2482 PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc)); 2483 } else icolm = irowm; 2484 } else icolm = icol; 2485 PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv)); 2486 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2487 } 2488 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2489 PetscFunctionReturn(PETSC_SUCCESS); 2490 } 2491 2492 /*@ 2493 MatMultDiagonalBlock - Computes the matrix-vector product, y = Dx. Where D is defined by the inode or block structure of the diagonal 2494 2495 Collective 2496 2497 Input Parameters: 2498 + mat - the matrix 2499 - x - the vector to be multiplied 2500 2501 Output Parameter: 2502 . y - the result 2503 2504 Level: developer 2505 2506 Note: 2507 The vectors `x` and `y` cannot be the same. I.e., one cannot 2508 call `MatMultDiagonalBlock`(A,y,y). 2509 2510 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2511 @*/ 2512 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y) 2513 { 2514 PetscFunctionBegin; 2515 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2516 PetscValidType(mat, 1); 2517 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2518 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2519 2520 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2521 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2522 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2523 MatCheckPreallocated(mat, 1); 2524 2525 PetscUseTypeMethod(mat, multdiagonalblock, x, y); 2526 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2527 PetscFunctionReturn(PETSC_SUCCESS); 2528 } 2529 2530 /*@ 2531 MatMult - Computes the matrix-vector product, y = Ax. 2532 2533 Neighbor-wise Collective 2534 2535 Input Parameters: 2536 + mat - the matrix 2537 - x - the vector to be multiplied 2538 2539 Output Parameter: 2540 . y - the result 2541 2542 Level: beginner 2543 2544 Note: 2545 The vectors `x` and `y` cannot be the same. I.e., one cannot 2546 call `MatMult`(A,y,y). 2547 2548 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2549 @*/ 2550 PetscErrorCode MatMult(Mat mat, Vec x, Vec y) 2551 { 2552 PetscFunctionBegin; 2553 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2554 PetscValidType(mat, 1); 2555 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2556 VecCheckAssembled(x); 2557 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2558 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2559 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2560 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2561 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); 2562 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); 2563 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); 2564 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); 2565 PetscCall(VecSetErrorIfLocked(y, 3)); 2566 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2567 MatCheckPreallocated(mat, 1); 2568 2569 PetscCall(VecLockReadPush(x)); 2570 PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0)); 2571 PetscUseTypeMethod(mat, mult, x, y); 2572 PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0)); 2573 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2574 PetscCall(VecLockReadPop(x)); 2575 PetscFunctionReturn(PETSC_SUCCESS); 2576 } 2577 2578 /*@ 2579 MatMultTranspose - Computes matrix transpose times a vector y = A^T * x. 2580 2581 Neighbor-wise Collective 2582 2583 Input Parameters: 2584 + mat - the matrix 2585 - x - the vector to be multiplied 2586 2587 Output Parameter: 2588 . y - the result 2589 2590 Level: beginner 2591 2592 Notes: 2593 The vectors `x` and `y` cannot be the same. I.e., one cannot 2594 call `MatMultTranspose`(A,y,y). 2595 2596 For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple, 2597 use `MatMultHermitianTranspose()` 2598 2599 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()` 2600 @*/ 2601 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y) 2602 { 2603 PetscErrorCode (*op)(Mat, Vec, Vec) = NULL; 2604 2605 PetscFunctionBegin; 2606 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2607 PetscValidType(mat, 1); 2608 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2609 VecCheckAssembled(x); 2610 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2611 2612 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2613 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2614 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2615 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); 2616 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); 2617 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); 2618 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); 2619 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2620 MatCheckPreallocated(mat, 1); 2621 2622 if (!mat->ops->multtranspose) { 2623 if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult; 2624 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); 2625 } else op = mat->ops->multtranspose; 2626 PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0)); 2627 PetscCall(VecLockReadPush(x)); 2628 PetscCall((*op)(mat, x, y)); 2629 PetscCall(VecLockReadPop(x)); 2630 PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0)); 2631 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2632 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2633 PetscFunctionReturn(PETSC_SUCCESS); 2634 } 2635 2636 /*@ 2637 MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector. 2638 2639 Neighbor-wise Collective 2640 2641 Input Parameters: 2642 + mat - the matrix 2643 - x - the vector to be multilplied 2644 2645 Output Parameter: 2646 . y - the result 2647 2648 Level: beginner 2649 2650 Notes: 2651 The vectors `x` and `y` cannot be the same. I.e., one cannot 2652 call `MatMultHermitianTranspose`(A,y,y). 2653 2654 Also called the conjugate transpose, complex conjugate transpose, or adjoint. 2655 2656 For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical. 2657 2658 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()` 2659 @*/ 2660 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y) 2661 { 2662 PetscFunctionBegin; 2663 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2664 PetscValidType(mat, 1); 2665 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2666 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2667 2668 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2669 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2670 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2671 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); 2672 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); 2673 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); 2674 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); 2675 MatCheckPreallocated(mat, 1); 2676 2677 PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0)); 2678 #if defined(PETSC_USE_COMPLEX) 2679 if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) { 2680 PetscCall(VecLockReadPush(x)); 2681 if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y); 2682 else PetscUseTypeMethod(mat, mult, x, y); 2683 PetscCall(VecLockReadPop(x)); 2684 } else { 2685 Vec w; 2686 PetscCall(VecDuplicate(x, &w)); 2687 PetscCall(VecCopy(x, w)); 2688 PetscCall(VecConjugate(w)); 2689 PetscCall(MatMultTranspose(mat, w, y)); 2690 PetscCall(VecDestroy(&w)); 2691 PetscCall(VecConjugate(y)); 2692 } 2693 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2694 #else 2695 PetscCall(MatMultTranspose(mat, x, y)); 2696 #endif 2697 PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0)); 2698 PetscFunctionReturn(PETSC_SUCCESS); 2699 } 2700 2701 /*@ 2702 MatMultAdd - Computes v3 = v2 + A * v1. 2703 2704 Neighbor-wise Collective 2705 2706 Input Parameters: 2707 + mat - the matrix 2708 . v1 - the vector to be multiplied by `mat` 2709 - v2 - the vector to be added to the result 2710 2711 Output Parameter: 2712 . v3 - the result 2713 2714 Level: beginner 2715 2716 Note: 2717 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2718 call `MatMultAdd`(A,v1,v2,v1). 2719 2720 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()` 2721 @*/ 2722 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2723 { 2724 PetscFunctionBegin; 2725 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2726 PetscValidType(mat, 1); 2727 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2728 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2729 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2730 2731 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2732 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2733 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); 2734 /* 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); 2735 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); */ 2736 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); 2737 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); 2738 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2739 MatCheckPreallocated(mat, 1); 2740 2741 PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3)); 2742 PetscCall(VecLockReadPush(v1)); 2743 PetscUseTypeMethod(mat, multadd, v1, v2, v3); 2744 PetscCall(VecLockReadPop(v1)); 2745 PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3)); 2746 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2747 PetscFunctionReturn(PETSC_SUCCESS); 2748 } 2749 2750 /*@ 2751 MatMultTransposeAdd - Computes v3 = v2 + A' * v1. 2752 2753 Neighbor-wise Collective 2754 2755 Input Parameters: 2756 + mat - the matrix 2757 . v1 - the vector to be multiplied by the transpose of the matrix 2758 - v2 - the vector to be added to the result 2759 2760 Output Parameter: 2761 . v3 - the result 2762 2763 Level: beginner 2764 2765 Note: 2766 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2767 call `MatMultTransposeAdd`(A,v1,v2,v1). 2768 2769 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2770 @*/ 2771 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2772 { 2773 PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd; 2774 2775 PetscFunctionBegin; 2776 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2777 PetscValidType(mat, 1); 2778 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2779 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2780 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2781 2782 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2783 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2784 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); 2785 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); 2786 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); 2787 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2788 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2789 MatCheckPreallocated(mat, 1); 2790 2791 PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2792 PetscCall(VecLockReadPush(v1)); 2793 PetscCall((*op)(mat, v1, v2, v3)); 2794 PetscCall(VecLockReadPop(v1)); 2795 PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2796 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2797 PetscFunctionReturn(PETSC_SUCCESS); 2798 } 2799 2800 /*@ 2801 MatMultHermitianTransposeAdd - Computes v3 = v2 + A^H * v1. 2802 2803 Neighbor-wise Collective 2804 2805 Input Parameters: 2806 + mat - the matrix 2807 . v1 - the vector to be multiplied by the Hermitian transpose 2808 - v2 - the vector to be added to the result 2809 2810 Output Parameter: 2811 . v3 - the result 2812 2813 Level: beginner 2814 2815 Note: 2816 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2817 call `MatMultHermitianTransposeAdd`(A,v1,v2,v1). 2818 2819 .seealso: [](chapter_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2820 @*/ 2821 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2822 { 2823 PetscFunctionBegin; 2824 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2825 PetscValidType(mat, 1); 2826 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2827 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2828 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2829 2830 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2831 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2832 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2833 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); 2834 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); 2835 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); 2836 MatCheckPreallocated(mat, 1); 2837 2838 PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2839 PetscCall(VecLockReadPush(v1)); 2840 if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3); 2841 else { 2842 Vec w, z; 2843 PetscCall(VecDuplicate(v1, &w)); 2844 PetscCall(VecCopy(v1, w)); 2845 PetscCall(VecConjugate(w)); 2846 PetscCall(VecDuplicate(v3, &z)); 2847 PetscCall(MatMultTranspose(mat, w, z)); 2848 PetscCall(VecDestroy(&w)); 2849 PetscCall(VecConjugate(z)); 2850 if (v2 != v3) { 2851 PetscCall(VecWAXPY(v3, 1.0, v2, z)); 2852 } else { 2853 PetscCall(VecAXPY(v3, 1.0, z)); 2854 } 2855 PetscCall(VecDestroy(&z)); 2856 } 2857 PetscCall(VecLockReadPop(v1)); 2858 PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2859 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2860 PetscFunctionReturn(PETSC_SUCCESS); 2861 } 2862 2863 /*@C 2864 MatGetFactorType - gets the type of factorization it is 2865 2866 Not Collective 2867 2868 Input Parameter: 2869 . mat - the matrix 2870 2871 Output Parameter: 2872 . 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` 2873 2874 Level: intermediate 2875 2876 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2877 `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2878 @*/ 2879 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t) 2880 { 2881 PetscFunctionBegin; 2882 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2883 PetscValidType(mat, 1); 2884 PetscValidPointer(t, 2); 2885 *t = mat->factortype; 2886 PetscFunctionReturn(PETSC_SUCCESS); 2887 } 2888 2889 /*@C 2890 MatSetFactorType - sets the type of factorization it is 2891 2892 Logically Collective 2893 2894 Input Parameters: 2895 + mat - the matrix 2896 - 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` 2897 2898 Level: intermediate 2899 2900 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2901 `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2902 @*/ 2903 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t) 2904 { 2905 PetscFunctionBegin; 2906 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2907 PetscValidType(mat, 1); 2908 mat->factortype = t; 2909 PetscFunctionReturn(PETSC_SUCCESS); 2910 } 2911 2912 /*@C 2913 MatGetInfo - Returns information about matrix storage (number of 2914 nonzeros, memory, etc.). 2915 2916 Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag 2917 2918 Input Parameters: 2919 + mat - the matrix 2920 - 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) 2921 2922 Output Parameter: 2923 . info - matrix information context 2924 2925 Notes: 2926 The `MatInfo` context contains a variety of matrix data, including 2927 number of nonzeros allocated and used, number of mallocs during 2928 matrix assembly, etc. Additional information for factored matrices 2929 is provided (such as the fill ratio, number of mallocs during 2930 factorization, etc.). Much of this info is printed to `PETSC_STDOUT` 2931 when using the runtime options 2932 $ -info -mat_view ::ascii_info 2933 2934 Example: 2935 See the file ${PETSC_DIR}/include/petscmat.h for a complete list of 2936 data within the MatInfo context. For example, 2937 .vb 2938 MatInfo info; 2939 Mat A; 2940 double mal, nz_a, nz_u; 2941 2942 MatGetInfo(A,MAT_LOCAL,&info); 2943 mal = info.mallocs; 2944 nz_a = info.nz_allocated; 2945 .ve 2946 2947 Fortran users should declare info as a double precision 2948 array of dimension `MAT_INFO_SIZE`, and then extract the parameters 2949 of interest. See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h 2950 a complete list of parameter names. 2951 .vb 2952 double precision info(MAT_INFO_SIZE) 2953 double precision mal, nz_a 2954 Mat A 2955 integer ierr 2956 2957 call MatGetInfo(A,MAT_LOCAL,info,ierr) 2958 mal = info(MAT_INFO_MALLOCS) 2959 nz_a = info(MAT_INFO_NZ_ALLOCATED) 2960 .ve 2961 2962 Level: intermediate 2963 2964 Developer Note: 2965 The Fortran interface is not autogenerated as the 2966 interface definition cannot be generated correctly [due to `MatInfo` argument] 2967 2968 .seealso: [](chapter_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()` 2969 @*/ 2970 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info) 2971 { 2972 PetscFunctionBegin; 2973 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2974 PetscValidType(mat, 1); 2975 PetscValidPointer(info, 3); 2976 MatCheckPreallocated(mat, 1); 2977 PetscUseTypeMethod(mat, getinfo, flag, info); 2978 PetscFunctionReturn(PETSC_SUCCESS); 2979 } 2980 2981 /* 2982 This is used by external packages where it is not easy to get the info from the actual 2983 matrix factorization. 2984 */ 2985 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info) 2986 { 2987 PetscFunctionBegin; 2988 PetscCall(PetscMemzero(info, sizeof(MatInfo))); 2989 PetscFunctionReturn(PETSC_SUCCESS); 2990 } 2991 2992 /*@C 2993 MatLUFactor - Performs in-place LU factorization of matrix. 2994 2995 Collective 2996 2997 Input Parameters: 2998 + mat - the matrix 2999 . row - row permutation 3000 . col - column permutation 3001 - info - options for factorization, includes 3002 .vb 3003 fill - expected fill as ratio of original fill. 3004 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3005 Run with the option -info to determine an optimal value to use 3006 .ve 3007 Level: developer 3008 3009 Notes: 3010 Most users should employ the `KSP` interface for linear solvers 3011 instead of working directly with matrix algebra routines such as this. 3012 See, e.g., `KSPCreate()`. 3013 3014 This changes the state of the matrix to a factored matrix; it cannot be used 3015 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3016 3017 This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()` 3018 when not using `KSP`. 3019 3020 Developer Note: 3021 The Fortran interface is not autogenerated as the 3022 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3023 3024 .seealso: [](chapter_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, 3025 `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3026 @*/ 3027 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3028 { 3029 MatFactorInfo tinfo; 3030 3031 PetscFunctionBegin; 3032 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3033 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3034 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3035 if (info) PetscValidPointer(info, 4); 3036 PetscValidType(mat, 1); 3037 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3038 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3039 MatCheckPreallocated(mat, 1); 3040 if (!info) { 3041 PetscCall(MatFactorInfoInitialize(&tinfo)); 3042 info = &tinfo; 3043 } 3044 3045 PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0)); 3046 PetscUseTypeMethod(mat, lufactor, row, col, info); 3047 PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0)); 3048 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3049 PetscFunctionReturn(PETSC_SUCCESS); 3050 } 3051 3052 /*@C 3053 MatILUFactor - Performs in-place ILU factorization of matrix. 3054 3055 Collective 3056 3057 Input Parameters: 3058 + mat - the matrix 3059 . row - row permutation 3060 . col - column permutation 3061 - info - structure containing 3062 .vb 3063 levels - number of levels of fill. 3064 expected fill - as ratio of original fill. 3065 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 3066 missing diagonal entries) 3067 .ve 3068 3069 Level: developer 3070 3071 Notes: 3072 Most users should employ the `KSP` interface for linear solvers 3073 instead of working directly with matrix algebra routines such as this. 3074 See, e.g., `KSPCreate()`. 3075 3076 Probably really in-place only when level of fill is zero, otherwise allocates 3077 new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()` 3078 when not using `KSP`. 3079 3080 Developer Note: 3081 The Fortran interface is not autogenerated as the 3082 interface definition cannot be generated correctly [due to MatFactorInfo] 3083 3084 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 3085 @*/ 3086 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3087 { 3088 PetscFunctionBegin; 3089 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3090 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3091 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3092 PetscValidPointer(info, 4); 3093 PetscValidType(mat, 1); 3094 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 3095 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3096 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3097 MatCheckPreallocated(mat, 1); 3098 3099 PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0)); 3100 PetscUseTypeMethod(mat, ilufactor, row, col, info); 3101 PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0)); 3102 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3103 PetscFunctionReturn(PETSC_SUCCESS); 3104 } 3105 3106 /*@C 3107 MatLUFactorSymbolic - Performs symbolic LU factorization of matrix. 3108 Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`. 3109 3110 Collective 3111 3112 Input Parameters: 3113 + fact - the factor matrix obtained with `MatGetFactor()` 3114 . mat - the matrix 3115 . row - the row permutation 3116 . col - the column permutation 3117 - info - options for factorization, includes 3118 .vb 3119 fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use 3120 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3121 .ve 3122 3123 Level: developer 3124 3125 Notes: 3126 See [Matrix Factorization](sec_matfactor) for additional information about factorizations 3127 3128 Most users should employ the simplified `KSP` interface for linear solvers 3129 instead of working directly with matrix algebra routines such as this. 3130 See, e.g., `KSPCreate()`. 3131 3132 Developer Note: 3133 The Fortran interface is not autogenerated as the 3134 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3135 3136 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3137 @*/ 3138 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 3139 { 3140 MatFactorInfo tinfo; 3141 3142 PetscFunctionBegin; 3143 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3144 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3145 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 3146 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 3147 if (info) PetscValidPointer(info, 5); 3148 PetscValidType(fact, 1); 3149 PetscValidType(mat, 2); 3150 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3151 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3152 MatCheckPreallocated(mat, 2); 3153 if (!info) { 3154 PetscCall(MatFactorInfoInitialize(&tinfo)); 3155 info = &tinfo; 3156 } 3157 3158 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0)); 3159 PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info); 3160 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0)); 3161 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3162 PetscFunctionReturn(PETSC_SUCCESS); 3163 } 3164 3165 /*@C 3166 MatLUFactorNumeric - Performs numeric LU factorization of a matrix. 3167 Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`. 3168 3169 Collective 3170 3171 Input Parameters: 3172 + fact - the factor matrix obtained with `MatGetFactor()` 3173 . mat - the matrix 3174 - info - options for factorization 3175 3176 Level: developer 3177 3178 Notes: 3179 See `MatLUFactor()` for in-place factorization. See 3180 `MatCholeskyFactorNumeric()` for the symmetric, positive definite case. 3181 3182 Most users should employ the `KSP` interface for linear solvers 3183 instead of working directly with matrix algebra routines such as this. 3184 See, e.g., `KSPCreate()`. 3185 3186 Developer Note: 3187 The Fortran interface is not autogenerated as the 3188 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3189 3190 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()` 3191 @*/ 3192 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3193 { 3194 MatFactorInfo tinfo; 3195 3196 PetscFunctionBegin; 3197 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3198 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3199 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3200 PetscValidType(fact, 1); 3201 PetscValidType(mat, 2); 3202 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3203 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, 3204 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3205 3206 MatCheckPreallocated(mat, 2); 3207 if (!info) { 3208 PetscCall(MatFactorInfoInitialize(&tinfo)); 3209 info = &tinfo; 3210 } 3211 3212 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3213 else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0)); 3214 PetscUseTypeMethod(fact, lufactornumeric, mat, info); 3215 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3216 else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0)); 3217 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3218 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3219 PetscFunctionReturn(PETSC_SUCCESS); 3220 } 3221 3222 /*@C 3223 MatCholeskyFactor - Performs in-place Cholesky factorization of a 3224 symmetric matrix. 3225 3226 Collective 3227 3228 Input Parameters: 3229 + mat - the matrix 3230 . perm - row and column permutations 3231 - f - expected fill as ratio of original fill 3232 3233 Level: developer 3234 3235 Notes: 3236 See `MatLUFactor()` for the nonsymmetric case. See also `MatGetFactor()`, 3237 `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`. 3238 3239 Most users should employ the `KSP` interface for linear solvers 3240 instead of working directly with matrix algebra routines such as this. 3241 See, e.g., `KSPCreate()`. 3242 3243 Developer Note: 3244 The Fortran interface is not autogenerated as the 3245 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3246 3247 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()` 3248 `MatGetOrdering()` 3249 @*/ 3250 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info) 3251 { 3252 MatFactorInfo tinfo; 3253 3254 PetscFunctionBegin; 3255 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3256 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2); 3257 if (info) PetscValidPointer(info, 3); 3258 PetscValidType(mat, 1); 3259 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3260 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3261 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3262 MatCheckPreallocated(mat, 1); 3263 if (!info) { 3264 PetscCall(MatFactorInfoInitialize(&tinfo)); 3265 info = &tinfo; 3266 } 3267 3268 PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0)); 3269 PetscUseTypeMethod(mat, choleskyfactor, perm, info); 3270 PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0)); 3271 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3272 PetscFunctionReturn(PETSC_SUCCESS); 3273 } 3274 3275 /*@C 3276 MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization 3277 of a symmetric matrix. 3278 3279 Collective 3280 3281 Input Parameters: 3282 + fact - the factor matrix obtained with `MatGetFactor()` 3283 . mat - the matrix 3284 . perm - row and column permutations 3285 - info - options for factorization, includes 3286 .vb 3287 fill - expected fill as ratio of original fill. 3288 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3289 Run with the option -info to determine an optimal value to use 3290 .ve 3291 3292 Level: developer 3293 3294 Notes: 3295 See `MatLUFactorSymbolic()` for the nonsymmetric case. See also 3296 `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`. 3297 3298 Most users should employ the `KSP` interface for linear solvers 3299 instead of working directly with matrix algebra routines such as this. 3300 See, e.g., `KSPCreate()`. 3301 3302 Developer Note: 3303 The Fortran interface is not autogenerated as the 3304 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3305 3306 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()` 3307 `MatGetOrdering()` 3308 @*/ 3309 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 3310 { 3311 MatFactorInfo tinfo; 3312 3313 PetscFunctionBegin; 3314 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3315 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3316 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 3317 if (info) PetscValidPointer(info, 4); 3318 PetscValidType(fact, 1); 3319 PetscValidType(mat, 2); 3320 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3321 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3322 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3323 MatCheckPreallocated(mat, 2); 3324 if (!info) { 3325 PetscCall(MatFactorInfoInitialize(&tinfo)); 3326 info = &tinfo; 3327 } 3328 3329 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3330 PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info); 3331 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3332 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3333 PetscFunctionReturn(PETSC_SUCCESS); 3334 } 3335 3336 /*@C 3337 MatCholeskyFactorNumeric - Performs numeric Cholesky factorization 3338 of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and 3339 `MatCholeskyFactorSymbolic()`. 3340 3341 Collective 3342 3343 Input Parameters: 3344 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored 3345 . mat - the initial matrix that is to be factored 3346 - info - options for factorization 3347 3348 Level: developer 3349 3350 Note: 3351 Most users should employ the `KSP` interface for linear solvers 3352 instead of working directly with matrix algebra routines such as this. 3353 See, e.g., `KSPCreate()`. 3354 3355 Developer Note: 3356 The Fortran interface is not autogenerated as the 3357 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3358 3359 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()` 3360 @*/ 3361 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3362 { 3363 MatFactorInfo tinfo; 3364 3365 PetscFunctionBegin; 3366 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3367 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3368 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3369 PetscValidType(fact, 1); 3370 PetscValidType(mat, 2); 3371 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3372 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, 3373 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3374 MatCheckPreallocated(mat, 2); 3375 if (!info) { 3376 PetscCall(MatFactorInfoInitialize(&tinfo)); 3377 info = &tinfo; 3378 } 3379 3380 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3381 else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0)); 3382 PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info); 3383 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3384 else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0)); 3385 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3386 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3387 PetscFunctionReturn(PETSC_SUCCESS); 3388 } 3389 3390 /*@ 3391 MatQRFactor - Performs in-place QR factorization of matrix. 3392 3393 Collective 3394 3395 Input Parameters: 3396 + mat - the matrix 3397 . col - column permutation 3398 - info - options for factorization, includes 3399 .vb 3400 fill - expected fill as ratio of original fill. 3401 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3402 Run with the option -info to determine an optimal value to use 3403 .ve 3404 3405 Level: developer 3406 3407 Notes: 3408 Most users should employ the `KSP` interface for linear solvers 3409 instead of working directly with matrix algebra routines such as this. 3410 See, e.g., `KSPCreate()`. 3411 3412 This changes the state of the matrix to a factored matrix; it cannot be used 3413 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3414 3415 Developer Note: 3416 The Fortran interface is not autogenerated as the 3417 interface definition cannot be generated correctly [due to MatFactorInfo] 3418 3419 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`, 3420 `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3421 @*/ 3422 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info) 3423 { 3424 PetscFunctionBegin; 3425 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3426 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2); 3427 if (info) PetscValidPointer(info, 3); 3428 PetscValidType(mat, 1); 3429 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3430 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3431 MatCheckPreallocated(mat, 1); 3432 PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0)); 3433 PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info)); 3434 PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0)); 3435 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3436 PetscFunctionReturn(PETSC_SUCCESS); 3437 } 3438 3439 /*@ 3440 MatQRFactorSymbolic - Performs symbolic QR factorization of matrix. 3441 Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`. 3442 3443 Collective 3444 3445 Input Parameters: 3446 + fact - the factor matrix obtained with `MatGetFactor()` 3447 . mat - the matrix 3448 . col - column permutation 3449 - info - options for factorization, includes 3450 .vb 3451 fill - expected fill as ratio of original fill. 3452 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3453 Run with the option -info to determine an optimal value to use 3454 .ve 3455 3456 Level: developer 3457 3458 Note: 3459 Most users should employ the `KSP` interface for linear solvers 3460 instead of working directly with matrix algebra routines such as this. 3461 See, e.g., `KSPCreate()`. 3462 3463 Developer Note: 3464 The Fortran interface is not autogenerated as the 3465 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3466 3467 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3468 @*/ 3469 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info) 3470 { 3471 MatFactorInfo tinfo; 3472 3473 PetscFunctionBegin; 3474 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3475 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3476 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3477 if (info) PetscValidPointer(info, 4); 3478 PetscValidType(fact, 1); 3479 PetscValidType(mat, 2); 3480 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3481 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3482 MatCheckPreallocated(mat, 2); 3483 if (!info) { 3484 PetscCall(MatFactorInfoInitialize(&tinfo)); 3485 info = &tinfo; 3486 } 3487 3488 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3489 PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info)); 3490 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3491 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3492 PetscFunctionReturn(PETSC_SUCCESS); 3493 } 3494 3495 /*@ 3496 MatQRFactorNumeric - Performs numeric QR factorization of a matrix. 3497 Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`. 3498 3499 Collective 3500 3501 Input Parameters: 3502 + fact - the factor matrix obtained with `MatGetFactor()` 3503 . mat - the matrix 3504 - info - options for factorization 3505 3506 Level: developer 3507 3508 Notes: 3509 See `MatQRFactor()` for in-place factorization. 3510 3511 Most users should employ the `KSP` interface for linear solvers 3512 instead of working directly with matrix algebra routines such as this. 3513 See, e.g., `KSPCreate()`. 3514 3515 Developer Note: 3516 The Fortran interface is not autogenerated as the 3517 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3518 3519 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()` 3520 @*/ 3521 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3522 { 3523 MatFactorInfo tinfo; 3524 3525 PetscFunctionBegin; 3526 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3527 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3528 PetscValidType(fact, 1); 3529 PetscValidType(mat, 2); 3530 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3531 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, 3532 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3533 3534 MatCheckPreallocated(mat, 2); 3535 if (!info) { 3536 PetscCall(MatFactorInfoInitialize(&tinfo)); 3537 info = &tinfo; 3538 } 3539 3540 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3541 else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0)); 3542 PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info)); 3543 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3544 else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0)); 3545 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3546 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3547 PetscFunctionReturn(PETSC_SUCCESS); 3548 } 3549 3550 /*@ 3551 MatSolve - Solves A x = b, given a factored matrix. 3552 3553 Neighbor-wise Collective 3554 3555 Input Parameters: 3556 + mat - the factored matrix 3557 - b - the right-hand-side vector 3558 3559 Output Parameter: 3560 . x - the result vector 3561 3562 Level: developer 3563 3564 Notes: 3565 The vectors `b` and `x` cannot be the same. I.e., one cannot 3566 call `MatSolve`(A,x,x). 3567 3568 Most users should employ the `KSP` interface for linear solvers 3569 instead of working directly with matrix algebra routines such as this. 3570 See, e.g., `KSPCreate()`. 3571 3572 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3573 @*/ 3574 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x) 3575 { 3576 PetscFunctionBegin; 3577 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3578 PetscValidType(mat, 1); 3579 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3580 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3581 PetscCheckSameComm(mat, 1, b, 2); 3582 PetscCheckSameComm(mat, 1, x, 3); 3583 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3584 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); 3585 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); 3586 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); 3587 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3588 MatCheckPreallocated(mat, 1); 3589 3590 PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0)); 3591 if (mat->factorerrortype) { 3592 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3593 PetscCall(VecSetInf(x)); 3594 } else PetscUseTypeMethod(mat, solve, b, x); 3595 PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0)); 3596 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3597 PetscFunctionReturn(PETSC_SUCCESS); 3598 } 3599 3600 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans) 3601 { 3602 Vec b, x; 3603 PetscInt N, i; 3604 PetscErrorCode (*f)(Mat, Vec, Vec); 3605 PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE; 3606 3607 PetscFunctionBegin; 3608 if (A->factorerrortype) { 3609 PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype)); 3610 PetscCall(MatSetInf(X)); 3611 PetscFunctionReturn(PETSC_SUCCESS); 3612 } 3613 f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose; 3614 PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 3615 PetscCall(MatBoundToCPU(A, &Abound)); 3616 if (!Abound) { 3617 PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3618 PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3619 } 3620 #if PetscDefined(HAVE_CUDA) 3621 if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B)); 3622 if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X)); 3623 #elif PetscDefined(HAVE_HIP) 3624 if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B)); 3625 if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X)); 3626 #endif 3627 PetscCall(MatGetSize(B, NULL, &N)); 3628 for (i = 0; i < N; i++) { 3629 PetscCall(MatDenseGetColumnVecRead(B, i, &b)); 3630 PetscCall(MatDenseGetColumnVecWrite(X, i, &x)); 3631 PetscCall((*f)(A, b, x)); 3632 PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x)); 3633 PetscCall(MatDenseRestoreColumnVecRead(B, i, &b)); 3634 } 3635 if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B)); 3636 if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X)); 3637 PetscFunctionReturn(PETSC_SUCCESS); 3638 } 3639 3640 /*@ 3641 MatMatSolve - Solves A X = B, given a factored matrix. 3642 3643 Neighbor-wise Collective 3644 3645 Input Parameters: 3646 + A - the factored matrix 3647 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS) 3648 3649 Output Parameter: 3650 . X - the result matrix (dense matrix) 3651 3652 Level: developer 3653 3654 Note: 3655 If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`; 3656 otherwise, `B` and `X` cannot be the same. 3657 3658 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3659 @*/ 3660 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X) 3661 { 3662 PetscFunctionBegin; 3663 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3664 PetscValidType(A, 1); 3665 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3666 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3667 PetscCheckSameComm(A, 1, B, 2); 3668 PetscCheckSameComm(A, 1, X, 3); 3669 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); 3670 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); 3671 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"); 3672 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3673 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3674 MatCheckPreallocated(A, 1); 3675 3676 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3677 if (!A->ops->matsolve) { 3678 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name)); 3679 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE)); 3680 } else PetscUseTypeMethod(A, matsolve, B, X); 3681 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3682 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3683 PetscFunctionReturn(PETSC_SUCCESS); 3684 } 3685 3686 /*@ 3687 MatMatSolveTranspose - Solves A^T X = B, given a factored matrix. 3688 3689 Neighbor-wise Collective 3690 3691 Input Parameters: 3692 + A - the factored matrix 3693 - B - the right-hand-side matrix (`MATDENSE` matrix) 3694 3695 Output Parameter: 3696 . X - the result matrix (dense matrix) 3697 3698 Level: developer 3699 3700 Note: 3701 The matrices `B` and `X` cannot be the same. I.e., one cannot 3702 call `MatMatSolveTranspose`(A,X,X). 3703 3704 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()` 3705 @*/ 3706 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X) 3707 { 3708 PetscFunctionBegin; 3709 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3710 PetscValidType(A, 1); 3711 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3712 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3713 PetscCheckSameComm(A, 1, B, 2); 3714 PetscCheckSameComm(A, 1, X, 3); 3715 PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3716 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); 3717 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); 3718 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); 3719 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"); 3720 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3721 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3722 MatCheckPreallocated(A, 1); 3723 3724 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3725 if (!A->ops->matsolvetranspose) { 3726 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name)); 3727 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE)); 3728 } else PetscUseTypeMethod(A, matsolvetranspose, B, X); 3729 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3730 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3731 PetscFunctionReturn(PETSC_SUCCESS); 3732 } 3733 3734 /*@ 3735 MatMatTransposeSolve - Solves A X = B^T, given a factored matrix. 3736 3737 Neighbor-wise Collective 3738 3739 Input Parameters: 3740 + A - the factored matrix 3741 - Bt - the transpose of right-hand-side matrix as a `MATDENSE` 3742 3743 Output Parameter: 3744 . X - the result matrix (dense matrix) 3745 3746 Level: developer 3747 3748 Note: 3749 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 3750 format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`. 3751 3752 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3753 @*/ 3754 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X) 3755 { 3756 PetscFunctionBegin; 3757 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3758 PetscValidType(A, 1); 3759 PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2); 3760 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3761 PetscCheckSameComm(A, 1, Bt, 2); 3762 PetscCheckSameComm(A, 1, X, 3); 3763 3764 PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3765 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); 3766 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); 3767 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"); 3768 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3769 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3770 MatCheckPreallocated(A, 1); 3771 3772 PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0)); 3773 PetscUseTypeMethod(A, mattransposesolve, Bt, X); 3774 PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0)); 3775 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3776 PetscFunctionReturn(PETSC_SUCCESS); 3777 } 3778 3779 /*@ 3780 MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or 3781 U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U, 3782 3783 Neighbor-wise Collective 3784 3785 Input Parameters: 3786 + mat - the factored matrix 3787 - b - the right-hand-side vector 3788 3789 Output Parameter: 3790 . x - the result vector 3791 3792 Level: developer 3793 3794 Notes: 3795 `MatSolve()` should be used for most applications, as it performs 3796 a forward solve followed by a backward solve. 3797 3798 The vectors `b` and `x` cannot be the same, i.e., one cannot 3799 call `MatForwardSolve`(A,x,x). 3800 3801 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3802 the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet. 3803 `MatForwardSolve()` solves U^T*D y = b, and 3804 `MatBackwardSolve()` solves U x = y. 3805 Thus they do not provide a symmetric preconditioner. 3806 3807 .seealso: [](chapter_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatBackwardSolve()` 3808 @*/ 3809 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x) 3810 { 3811 PetscFunctionBegin; 3812 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3813 PetscValidType(mat, 1); 3814 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3815 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3816 PetscCheckSameComm(mat, 1, b, 2); 3817 PetscCheckSameComm(mat, 1, x, 3); 3818 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3819 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); 3820 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); 3821 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); 3822 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3823 MatCheckPreallocated(mat, 1); 3824 3825 PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0)); 3826 PetscUseTypeMethod(mat, forwardsolve, b, x); 3827 PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0)); 3828 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3829 PetscFunctionReturn(PETSC_SUCCESS); 3830 } 3831 3832 /*@ 3833 MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU. 3834 D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U, 3835 3836 Neighbor-wise Collective 3837 3838 Input Parameters: 3839 + mat - the factored matrix 3840 - b - the right-hand-side vector 3841 3842 Output Parameter: 3843 . x - the result vector 3844 3845 Level: developer 3846 3847 Notes: 3848 `MatSolve()` should be used for most applications, as it performs 3849 a forward solve followed by a backward solve. 3850 3851 The vectors `b` and `x` cannot be the same. I.e., one cannot 3852 call `MatBackwardSolve`(A,x,x). 3853 3854 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3855 the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet. 3856 `MatForwardSolve()` solves U^T*D y = b, and 3857 `MatBackwardSolve()` solves U x = y. 3858 Thus they do not provide a symmetric preconditioner. 3859 3860 .seealso: [](chapter_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatForwardSolve()` 3861 @*/ 3862 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x) 3863 { 3864 PetscFunctionBegin; 3865 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3866 PetscValidType(mat, 1); 3867 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3868 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3869 PetscCheckSameComm(mat, 1, b, 2); 3870 PetscCheckSameComm(mat, 1, x, 3); 3871 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3872 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); 3873 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); 3874 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); 3875 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3876 MatCheckPreallocated(mat, 1); 3877 3878 PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0)); 3879 PetscUseTypeMethod(mat, backwardsolve, b, x); 3880 PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0)); 3881 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3882 PetscFunctionReturn(PETSC_SUCCESS); 3883 } 3884 3885 /*@ 3886 MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix. 3887 3888 Neighbor-wise Collective 3889 3890 Input Parameters: 3891 + mat - the factored matrix 3892 . b - the right-hand-side vector 3893 - y - the vector to be added to 3894 3895 Output Parameter: 3896 . x - the result vector 3897 3898 Level: developer 3899 3900 Note: 3901 The vectors `b` and `x` cannot be the same. I.e., one cannot 3902 call `MatSolveAdd`(A,x,y,x). 3903 3904 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3905 @*/ 3906 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x) 3907 { 3908 PetscScalar one = 1.0; 3909 Vec tmp; 3910 3911 PetscFunctionBegin; 3912 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3913 PetscValidType(mat, 1); 3914 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 3915 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3916 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 3917 PetscCheckSameComm(mat, 1, b, 2); 3918 PetscCheckSameComm(mat, 1, y, 3); 3919 PetscCheckSameComm(mat, 1, x, 4); 3920 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3921 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); 3922 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); 3923 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); 3924 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); 3925 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); 3926 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3927 MatCheckPreallocated(mat, 1); 3928 3929 PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y)); 3930 if (mat->factorerrortype) { 3931 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3932 PetscCall(VecSetInf(x)); 3933 } else if (mat->ops->solveadd) { 3934 PetscUseTypeMethod(mat, solveadd, b, y, x); 3935 } else { 3936 /* do the solve then the add manually */ 3937 if (x != y) { 3938 PetscCall(MatSolve(mat, b, x)); 3939 PetscCall(VecAXPY(x, one, y)); 3940 } else { 3941 PetscCall(VecDuplicate(x, &tmp)); 3942 PetscCall(VecCopy(x, tmp)); 3943 PetscCall(MatSolve(mat, b, x)); 3944 PetscCall(VecAXPY(x, one, tmp)); 3945 PetscCall(VecDestroy(&tmp)); 3946 } 3947 } 3948 PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y)); 3949 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3950 PetscFunctionReturn(PETSC_SUCCESS); 3951 } 3952 3953 /*@ 3954 MatSolveTranspose - Solves A' x = b, given a factored matrix. 3955 3956 Neighbor-wise Collective 3957 3958 Input Parameters: 3959 + mat - the factored matrix 3960 - b - the right-hand-side vector 3961 3962 Output Parameter: 3963 . x - the result vector 3964 3965 Level: developer 3966 3967 Notes: 3968 The vectors `b` and `x` cannot be the same. I.e., one cannot 3969 call `MatSolveTranspose`(A,x,x). 3970 3971 Most users should employ the `KSP` interface for linear solvers 3972 instead of working directly with matrix algebra routines such as this. 3973 See, e.g., `KSPCreate()`. 3974 3975 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()` 3976 @*/ 3977 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x) 3978 { 3979 PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose; 3980 3981 PetscFunctionBegin; 3982 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3983 PetscValidType(mat, 1); 3984 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3985 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3986 PetscCheckSameComm(mat, 1, b, 2); 3987 PetscCheckSameComm(mat, 1, x, 3); 3988 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3989 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); 3990 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); 3991 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3992 MatCheckPreallocated(mat, 1); 3993 PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0)); 3994 if (mat->factorerrortype) { 3995 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3996 PetscCall(VecSetInf(x)); 3997 } else { 3998 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name); 3999 PetscCall((*f)(mat, b, x)); 4000 } 4001 PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0)); 4002 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4003 PetscFunctionReturn(PETSC_SUCCESS); 4004 } 4005 4006 /*@ 4007 MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a 4008 factored matrix. 4009 4010 Neighbor-wise Collective 4011 4012 Input Parameters: 4013 + mat - the factored matrix 4014 . b - the right-hand-side vector 4015 - y - the vector to be added to 4016 4017 Output Parameter: 4018 . x - the result vector 4019 4020 Level: developer 4021 4022 Note: 4023 The vectors `b` and `x` cannot be the same. I.e., one cannot 4024 call `MatSolveTransposeAdd`(A,x,y,x). 4025 4026 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()` 4027 @*/ 4028 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x) 4029 { 4030 PetscScalar one = 1.0; 4031 Vec tmp; 4032 PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd; 4033 4034 PetscFunctionBegin; 4035 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4036 PetscValidType(mat, 1); 4037 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4038 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4039 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4040 PetscCheckSameComm(mat, 1, b, 2); 4041 PetscCheckSameComm(mat, 1, y, 3); 4042 PetscCheckSameComm(mat, 1, x, 4); 4043 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4044 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); 4045 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); 4046 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); 4047 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); 4048 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4049 MatCheckPreallocated(mat, 1); 4050 4051 PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y)); 4052 if (mat->factorerrortype) { 4053 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4054 PetscCall(VecSetInf(x)); 4055 } else if (f) { 4056 PetscCall((*f)(mat, b, y, x)); 4057 } else { 4058 /* do the solve then the add manually */ 4059 if (x != y) { 4060 PetscCall(MatSolveTranspose(mat, b, x)); 4061 PetscCall(VecAXPY(x, one, y)); 4062 } else { 4063 PetscCall(VecDuplicate(x, &tmp)); 4064 PetscCall(VecCopy(x, tmp)); 4065 PetscCall(MatSolveTranspose(mat, b, x)); 4066 PetscCall(VecAXPY(x, one, tmp)); 4067 PetscCall(VecDestroy(&tmp)); 4068 } 4069 } 4070 PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y)); 4071 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4072 PetscFunctionReturn(PETSC_SUCCESS); 4073 } 4074 4075 /*@ 4076 MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps. 4077 4078 Neighbor-wise Collective 4079 4080 Input Parameters: 4081 + mat - the matrix 4082 . b - the right hand side 4083 . omega - the relaxation factor 4084 . flag - flag indicating the type of SOR (see below) 4085 . shift - diagonal shift 4086 . its - the number of iterations 4087 - lits - the number of local iterations 4088 4089 Output Parameter: 4090 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess) 4091 4092 SOR Flags: 4093 + `SOR_FORWARD_SWEEP` - forward SOR 4094 . `SOR_BACKWARD_SWEEP` - backward SOR 4095 . `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR) 4096 . `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR 4097 . `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR 4098 . `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR 4099 . `SOR_EISENSTAT` - SOR with Eisenstat trick 4100 . `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies 4101 upper/lower triangular part of matrix to 4102 vector (with omega) 4103 - `SOR_ZERO_INITIAL_GUESS` - zero initial guess 4104 4105 Level: developer 4106 4107 Notes: 4108 `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and 4109 `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings 4110 on each processor. 4111 4112 Application programmers will not generally use `MatSOR()` directly, 4113 but instead will employ the `KSP`/`PC` interface. 4114 4115 For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing 4116 4117 Most users should employ the `KSP` interface for linear solvers 4118 instead of working directly with matrix algebra routines such as this. 4119 See, e.g., `KSPCreate()`. 4120 4121 Vectors `x` and `b` CANNOT be the same 4122 4123 The flags are implemented as bitwise inclusive or operations. 4124 For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`) 4125 to specify a zero initial guess for SSOR. 4126 4127 Developer Note: 4128 We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes 4129 4130 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()` 4131 @*/ 4132 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x) 4133 { 4134 PetscFunctionBegin; 4135 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4136 PetscValidType(mat, 1); 4137 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4138 PetscValidHeaderSpecific(x, VEC_CLASSID, 8); 4139 PetscCheckSameComm(mat, 1, b, 2); 4140 PetscCheckSameComm(mat, 1, x, 8); 4141 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4142 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4143 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); 4144 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); 4145 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); 4146 PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its); 4147 PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits); 4148 PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same"); 4149 4150 MatCheckPreallocated(mat, 1); 4151 PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0)); 4152 PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x); 4153 PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0)); 4154 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4155 PetscFunctionReturn(PETSC_SUCCESS); 4156 } 4157 4158 /* 4159 Default matrix copy routine. 4160 */ 4161 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str) 4162 { 4163 PetscInt i, rstart = 0, rend = 0, nz; 4164 const PetscInt *cwork; 4165 const PetscScalar *vwork; 4166 4167 PetscFunctionBegin; 4168 if (B->assembled) PetscCall(MatZeroEntries(B)); 4169 if (str == SAME_NONZERO_PATTERN) { 4170 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 4171 for (i = rstart; i < rend; i++) { 4172 PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork)); 4173 PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES)); 4174 PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork)); 4175 } 4176 } else { 4177 PetscCall(MatAYPX(B, 0.0, A, str)); 4178 } 4179 PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 4180 PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 4181 PetscFunctionReturn(PETSC_SUCCESS); 4182 } 4183 4184 /*@ 4185 MatCopy - Copies a matrix to another matrix. 4186 4187 Collective 4188 4189 Input Parameters: 4190 + A - the matrix 4191 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN` 4192 4193 Output Parameter: 4194 . B - where the copy is put 4195 4196 Level: intermediate 4197 4198 Notes: 4199 If you use `SAME_NONZERO_PATTERN` then the two matrices must have the same nonzero pattern or the routine will crash. 4200 4201 `MatCopy()` copies the matrix entries of a matrix to another existing 4202 matrix (after first zeroing the second matrix). A related routine is 4203 `MatConvert()`, which first creates a new matrix and then copies the data. 4204 4205 .seealso: [](chapter_matrices), `Mat`, `MatConvert()`, `MatDuplicate()` 4206 @*/ 4207 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str) 4208 { 4209 PetscInt i; 4210 4211 PetscFunctionBegin; 4212 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 4213 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 4214 PetscValidType(A, 1); 4215 PetscValidType(B, 2); 4216 PetscCheckSameComm(A, 1, B, 2); 4217 MatCheckPreallocated(B, 2); 4218 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4219 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4220 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, 4221 A->cmap->N, B->cmap->N); 4222 MatCheckPreallocated(A, 1); 4223 if (A == B) PetscFunctionReturn(PETSC_SUCCESS); 4224 4225 PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0)); 4226 if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str); 4227 else PetscCall(MatCopy_Basic(A, B, str)); 4228 4229 B->stencil.dim = A->stencil.dim; 4230 B->stencil.noc = A->stencil.noc; 4231 for (i = 0; i <= A->stencil.dim; i++) { 4232 B->stencil.dims[i] = A->stencil.dims[i]; 4233 B->stencil.starts[i] = A->stencil.starts[i]; 4234 } 4235 4236 PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0)); 4237 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4238 PetscFunctionReturn(PETSC_SUCCESS); 4239 } 4240 4241 /*@C 4242 MatConvert - Converts a matrix to another matrix, either of the same 4243 or different type. 4244 4245 Collective 4246 4247 Input Parameters: 4248 + mat - the matrix 4249 . newtype - new matrix type. Use `MATSAME` to create a new matrix of the 4250 same type as the original matrix. 4251 - reuse - denotes if the destination matrix is to be created or reused. 4252 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 4253 `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). 4254 4255 Output Parameter: 4256 . M - pointer to place new matrix 4257 4258 Level: intermediate 4259 4260 Notes: 4261 `MatConvert()` first creates a new matrix and then copies the data from 4262 the first matrix. A related routine is `MatCopy()`, which copies the matrix 4263 entries of one matrix to another already existing matrix context. 4264 4265 Cannot be used to convert a sequential matrix to parallel or parallel to sequential, 4266 the MPI communicator of the generated matrix is always the same as the communicator 4267 of the input matrix. 4268 4269 .seealso: [](chapter_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 4270 @*/ 4271 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M) 4272 { 4273 PetscBool sametype, issame, flg; 4274 PetscBool3 issymmetric, ishermitian; 4275 char convname[256], mtype[256]; 4276 Mat B; 4277 4278 PetscFunctionBegin; 4279 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4280 PetscValidType(mat, 1); 4281 PetscValidPointer(M, 4); 4282 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4283 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4284 MatCheckPreallocated(mat, 1); 4285 4286 PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg)); 4287 if (flg) newtype = mtype; 4288 4289 PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype)); 4290 PetscCall(PetscStrcmp(newtype, "same", &issame)); 4291 PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix"); 4292 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"); 4293 4294 if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) { 4295 PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4296 PetscFunctionReturn(PETSC_SUCCESS); 4297 } 4298 4299 /* Cache Mat options because some converters use MatHeaderReplace */ 4300 issymmetric = mat->symmetric; 4301 ishermitian = mat->hermitian; 4302 4303 if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) { 4304 PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4305 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4306 } else { 4307 PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL; 4308 const char *prefix[3] = {"seq", "mpi", ""}; 4309 PetscInt i; 4310 /* 4311 Order of precedence: 4312 0) See if newtype is a superclass of the current matrix. 4313 1) See if a specialized converter is known to the current matrix. 4314 2) See if a specialized converter is known to the desired matrix class. 4315 3) See if a good general converter is registered for the desired class 4316 (as of 6/27/03 only MATMPIADJ falls into this category). 4317 4) See if a good general converter is known for the current matrix. 4318 5) Use a really basic converter. 4319 */ 4320 4321 /* 0) See if newtype is a superclass of the current matrix. 4322 i.e mat is mpiaij and newtype is aij */ 4323 for (i = 0; i < 2; i++) { 4324 PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname))); 4325 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4326 PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg)); 4327 PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg)); 4328 if (flg) { 4329 if (reuse == MAT_INPLACE_MATRIX) { 4330 PetscCall(PetscInfo(mat, "Early return\n")); 4331 PetscFunctionReturn(PETSC_SUCCESS); 4332 } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) { 4333 PetscCall(PetscInfo(mat, "Calling MatDuplicate\n")); 4334 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4335 PetscFunctionReturn(PETSC_SUCCESS); 4336 } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) { 4337 PetscCall(PetscInfo(mat, "Calling MatCopy\n")); 4338 PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN)); 4339 PetscFunctionReturn(PETSC_SUCCESS); 4340 } 4341 } 4342 } 4343 /* 1) See if a specialized converter is known to the current matrix and the desired class */ 4344 for (i = 0; i < 3; i++) { 4345 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4346 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4347 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4348 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4349 PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname))); 4350 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4351 PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv)); 4352 PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv)); 4353 if (conv) goto foundconv; 4354 } 4355 4356 /* 2) See if a specialized converter is known to the desired matrix class. */ 4357 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B)); 4358 PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 4359 PetscCall(MatSetType(B, newtype)); 4360 for (i = 0; i < 3; i++) { 4361 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4362 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4363 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4364 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4365 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4366 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4367 PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv)); 4368 PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv)); 4369 if (conv) { 4370 PetscCall(MatDestroy(&B)); 4371 goto foundconv; 4372 } 4373 } 4374 4375 /* 3) See if a good general converter is registered for the desired class */ 4376 conv = B->ops->convertfrom; 4377 PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv)); 4378 PetscCall(MatDestroy(&B)); 4379 if (conv) goto foundconv; 4380 4381 /* 4) See if a good general converter is known for the current matrix */ 4382 if (mat->ops->convert) conv = mat->ops->convert; 4383 PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv)); 4384 if (conv) goto foundconv; 4385 4386 /* 5) Use a really basic converter. */ 4387 PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n")); 4388 conv = MatConvert_Basic; 4389 4390 foundconv: 4391 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4392 PetscCall((*conv)(mat, newtype, reuse, M)); 4393 if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) { 4394 /* the block sizes must be same if the mappings are copied over */ 4395 (*M)->rmap->bs = mat->rmap->bs; 4396 (*M)->cmap->bs = mat->cmap->bs; 4397 PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping)); 4398 PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping)); 4399 (*M)->rmap->mapping = mat->rmap->mapping; 4400 (*M)->cmap->mapping = mat->cmap->mapping; 4401 } 4402 (*M)->stencil.dim = mat->stencil.dim; 4403 (*M)->stencil.noc = mat->stencil.noc; 4404 for (i = 0; i <= mat->stencil.dim; i++) { 4405 (*M)->stencil.dims[i] = mat->stencil.dims[i]; 4406 (*M)->stencil.starts[i] = mat->stencil.starts[i]; 4407 } 4408 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4409 } 4410 PetscCall(PetscObjectStateIncrease((PetscObject)*M)); 4411 4412 /* Copy Mat options */ 4413 if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE)); 4414 else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE)); 4415 if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE)); 4416 else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE)); 4417 PetscFunctionReturn(PETSC_SUCCESS); 4418 } 4419 4420 /*@C 4421 MatFactorGetSolverType - Returns name of the package providing the factorization routines 4422 4423 Not Collective 4424 4425 Input Parameter: 4426 . mat - the matrix, must be a factored matrix 4427 4428 Output Parameter: 4429 . type - the string name of the package (do not free this string) 4430 4431 Level: intermediate 4432 4433 Fortran Note: 4434 Pass in an empty string and the package name will be copied into it. Make sure the string is long enough. 4435 4436 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()` 4437 @*/ 4438 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type) 4439 { 4440 PetscErrorCode (*conv)(Mat, MatSolverType *); 4441 4442 PetscFunctionBegin; 4443 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4444 PetscValidType(mat, 1); 4445 PetscValidPointer(type, 2); 4446 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 4447 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv)); 4448 if (conv) PetscCall((*conv)(mat, type)); 4449 else *type = MATSOLVERPETSC; 4450 PetscFunctionReturn(PETSC_SUCCESS); 4451 } 4452 4453 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType; 4454 struct _MatSolverTypeForSpecifcType { 4455 MatType mtype; 4456 /* no entry for MAT_FACTOR_NONE */ 4457 PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *); 4458 MatSolverTypeForSpecifcType next; 4459 }; 4460 4461 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder; 4462 struct _MatSolverTypeHolder { 4463 char *name; 4464 MatSolverTypeForSpecifcType handlers; 4465 MatSolverTypeHolder next; 4466 }; 4467 4468 static MatSolverTypeHolder MatSolverTypeHolders = NULL; 4469 4470 /*@C 4471 MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type 4472 4473 Input Parameters: 4474 + package - name of the package, for example petsc or superlu 4475 . mtype - the matrix type that works with this package 4476 . ftype - the type of factorization supported by the package 4477 - createfactor - routine that will create the factored matrix ready to be used 4478 4479 Level: developer 4480 4481 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()` 4482 @*/ 4483 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *)) 4484 { 4485 MatSolverTypeHolder next = MatSolverTypeHolders, prev = NULL; 4486 PetscBool flg; 4487 MatSolverTypeForSpecifcType inext, iprev = NULL; 4488 4489 PetscFunctionBegin; 4490 PetscCall(MatInitializePackage()); 4491 if (!next) { 4492 PetscCall(PetscNew(&MatSolverTypeHolders)); 4493 PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name)); 4494 PetscCall(PetscNew(&MatSolverTypeHolders->handlers)); 4495 PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype)); 4496 MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor; 4497 PetscFunctionReturn(PETSC_SUCCESS); 4498 } 4499 while (next) { 4500 PetscCall(PetscStrcasecmp(package, next->name, &flg)); 4501 if (flg) { 4502 PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers"); 4503 inext = next->handlers; 4504 while (inext) { 4505 PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg)); 4506 if (flg) { 4507 inext->createfactor[(int)ftype - 1] = createfactor; 4508 PetscFunctionReturn(PETSC_SUCCESS); 4509 } 4510 iprev = inext; 4511 inext = inext->next; 4512 } 4513 PetscCall(PetscNew(&iprev->next)); 4514 PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype)); 4515 iprev->next->createfactor[(int)ftype - 1] = createfactor; 4516 PetscFunctionReturn(PETSC_SUCCESS); 4517 } 4518 prev = next; 4519 next = next->next; 4520 } 4521 PetscCall(PetscNew(&prev->next)); 4522 PetscCall(PetscStrallocpy(package, &prev->next->name)); 4523 PetscCall(PetscNew(&prev->next->handlers)); 4524 PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype)); 4525 prev->next->handlers->createfactor[(int)ftype - 1] = createfactor; 4526 PetscFunctionReturn(PETSC_SUCCESS); 4527 } 4528 4529 /*@C 4530 MatSolverTypeGet - Gets the function that creates the factor matrix if it exist 4531 4532 Input Parameters: 4533 + type - name of the package, for example petsc or superlu 4534 . ftype - the type of factorization supported by the type 4535 - mtype - the matrix type that works with this type 4536 4537 Output Parameters: 4538 + foundtype - `PETSC_TRUE` if the type was registered 4539 . foundmtype - `PETSC_TRUE` if the type supports the requested mtype 4540 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found 4541 4542 Level: developer 4543 4544 .seealso: [](chapter_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()` 4545 @*/ 4546 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *)) 4547 { 4548 MatSolverTypeHolder next = MatSolverTypeHolders; 4549 PetscBool flg; 4550 MatSolverTypeForSpecifcType inext; 4551 4552 PetscFunctionBegin; 4553 if (foundtype) *foundtype = PETSC_FALSE; 4554 if (foundmtype) *foundmtype = PETSC_FALSE; 4555 if (createfactor) *createfactor = NULL; 4556 4557 if (type) { 4558 while (next) { 4559 PetscCall(PetscStrcasecmp(type, next->name, &flg)); 4560 if (flg) { 4561 if (foundtype) *foundtype = PETSC_TRUE; 4562 inext = next->handlers; 4563 while (inext) { 4564 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4565 if (flg) { 4566 if (foundmtype) *foundmtype = PETSC_TRUE; 4567 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4568 PetscFunctionReturn(PETSC_SUCCESS); 4569 } 4570 inext = inext->next; 4571 } 4572 } 4573 next = next->next; 4574 } 4575 } else { 4576 while (next) { 4577 inext = next->handlers; 4578 while (inext) { 4579 PetscCall(PetscStrcmp(mtype, inext->mtype, &flg)); 4580 if (flg && inext->createfactor[(int)ftype - 1]) { 4581 if (foundtype) *foundtype = PETSC_TRUE; 4582 if (foundmtype) *foundmtype = PETSC_TRUE; 4583 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4584 PetscFunctionReturn(PETSC_SUCCESS); 4585 } 4586 inext = inext->next; 4587 } 4588 next = next->next; 4589 } 4590 /* try with base classes inext->mtype */ 4591 next = MatSolverTypeHolders; 4592 while (next) { 4593 inext = next->handlers; 4594 while (inext) { 4595 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4596 if (flg && inext->createfactor[(int)ftype - 1]) { 4597 if (foundtype) *foundtype = PETSC_TRUE; 4598 if (foundmtype) *foundmtype = PETSC_TRUE; 4599 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4600 PetscFunctionReturn(PETSC_SUCCESS); 4601 } 4602 inext = inext->next; 4603 } 4604 next = next->next; 4605 } 4606 } 4607 PetscFunctionReturn(PETSC_SUCCESS); 4608 } 4609 4610 PetscErrorCode MatSolverTypeDestroy(void) 4611 { 4612 MatSolverTypeHolder next = MatSolverTypeHolders, prev; 4613 MatSolverTypeForSpecifcType inext, iprev; 4614 4615 PetscFunctionBegin; 4616 while (next) { 4617 PetscCall(PetscFree(next->name)); 4618 inext = next->handlers; 4619 while (inext) { 4620 PetscCall(PetscFree(inext->mtype)); 4621 iprev = inext; 4622 inext = inext->next; 4623 PetscCall(PetscFree(iprev)); 4624 } 4625 prev = next; 4626 next = next->next; 4627 PetscCall(PetscFree(prev)); 4628 } 4629 MatSolverTypeHolders = NULL; 4630 PetscFunctionReturn(PETSC_SUCCESS); 4631 } 4632 4633 /*@C 4634 MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4635 4636 Logically Collective 4637 4638 Input Parameter: 4639 . mat - the matrix 4640 4641 Output Parameter: 4642 . flg - `PETSC_TRUE` if uses the ordering 4643 4644 Level: developer 4645 4646 Note: 4647 Most internal PETSc factorizations use the ordering passed to the factorization routine but external 4648 packages do not, thus we want to skip generating the ordering when it is not needed or used. 4649 4650 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4651 @*/ 4652 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg) 4653 { 4654 PetscFunctionBegin; 4655 *flg = mat->canuseordering; 4656 PetscFunctionReturn(PETSC_SUCCESS); 4657 } 4658 4659 /*@C 4660 MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object 4661 4662 Logically Collective 4663 4664 Input Parameters: 4665 + mat - the matrix obtained with `MatGetFactor()` 4666 - ftype - the factorization type to be used 4667 4668 Output Parameter: 4669 . otype - the preferred ordering type 4670 4671 Level: developer 4672 4673 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4674 @*/ 4675 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype) 4676 { 4677 PetscFunctionBegin; 4678 *otype = mat->preferredordering[ftype]; 4679 PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering"); 4680 PetscFunctionReturn(PETSC_SUCCESS); 4681 } 4682 4683 /*@C 4684 MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic() 4685 4686 Collective 4687 4688 Input Parameters: 4689 + mat - the matrix 4690 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4691 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4692 4693 Output Parameter: 4694 . f - the factor matrix used with MatXXFactorSymbolic() calls 4695 4696 Options Database Key: 4697 . -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory. 4698 One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices. 4699 4700 Level: intermediate 4701 4702 Notes: 4703 Users usually access the factorization solvers via `KSP` 4704 4705 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4706 such as pastix, superlu, mumps etc. 4707 4708 PETSc must have been ./configure to use the external solver, using the option --download-package 4709 4710 Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption 4711 where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set 4712 call `MatSetOptionsPrefixFactor()` on the originating matrix or `MatSetOptionsPrefix()` on the resulting factor matrix. 4713 4714 Developer Note: 4715 This should actually be called `MatCreateFactor()` since it creates a new factor object 4716 4717 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, 4718 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4719 @*/ 4720 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f) 4721 { 4722 PetscBool foundtype, foundmtype; 4723 PetscErrorCode (*conv)(Mat, MatFactorType, Mat *); 4724 4725 PetscFunctionBegin; 4726 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4727 PetscValidType(mat, 1); 4728 4729 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4730 MatCheckPreallocated(mat, 1); 4731 4732 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv)); 4733 if (!foundtype) { 4734 if (type) { 4735 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], 4736 ((PetscObject)mat)->type_name, type); 4737 } else { 4738 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); 4739 } 4740 } 4741 PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name); 4742 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); 4743 4744 PetscCall((*conv)(mat, ftype, f)); 4745 if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix)); 4746 PetscFunctionReturn(PETSC_SUCCESS); 4747 } 4748 4749 /*@C 4750 MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type 4751 4752 Not Collective 4753 4754 Input Parameters: 4755 + mat - the matrix 4756 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4757 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4758 4759 Output Parameter: 4760 . flg - PETSC_TRUE if the factorization is available 4761 4762 Level: intermediate 4763 4764 Notes: 4765 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4766 such as pastix, superlu, mumps etc. 4767 4768 PETSc must have been ./configure to use the external solver, using the option --download-package 4769 4770 Developer Note: 4771 This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object 4772 4773 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactor()`, `MatSolverTypeRegister()`, 4774 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4775 @*/ 4776 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg) 4777 { 4778 PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *); 4779 4780 PetscFunctionBegin; 4781 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4782 PetscValidType(mat, 1); 4783 PetscValidBoolPointer(flg, 4); 4784 4785 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4786 MatCheckPreallocated(mat, 1); 4787 4788 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv)); 4789 *flg = gconv ? PETSC_TRUE : PETSC_FALSE; 4790 PetscFunctionReturn(PETSC_SUCCESS); 4791 } 4792 4793 /*@ 4794 MatDuplicate - Duplicates a matrix including the non-zero structure. 4795 4796 Collective 4797 4798 Input Parameters: 4799 + mat - the matrix 4800 - op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`. 4801 See the manual page for `MatDuplicateOption()` for an explanation of these options. 4802 4803 Output Parameter: 4804 . M - pointer to place new matrix 4805 4806 Level: intermediate 4807 4808 Notes: 4809 You cannot change the nonzero pattern for the parent or child matrix if you use `MAT_SHARE_NONZERO_PATTERN`. 4810 4811 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. 4812 4813 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 4814 is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated. 4815 User should not use `MatDuplicate()` to create new matrix M if M is intended to be reused as the product of matrix operation. 4816 4817 .seealso: [](chapter_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption` 4818 @*/ 4819 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M) 4820 { 4821 Mat B; 4822 VecType vtype; 4823 PetscInt i; 4824 PetscObject dm; 4825 void (*viewf)(void); 4826 4827 PetscFunctionBegin; 4828 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4829 PetscValidType(mat, 1); 4830 PetscValidPointer(M, 3); 4831 PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix"); 4832 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4833 MatCheckPreallocated(mat, 1); 4834 4835 *M = NULL; 4836 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4837 PetscUseTypeMethod(mat, duplicate, op, M); 4838 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4839 B = *M; 4840 4841 PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf)); 4842 if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf)); 4843 PetscCall(MatGetVecType(mat, &vtype)); 4844 PetscCall(MatSetVecType(B, vtype)); 4845 4846 B->stencil.dim = mat->stencil.dim; 4847 B->stencil.noc = mat->stencil.noc; 4848 for (i = 0; i <= mat->stencil.dim; i++) { 4849 B->stencil.dims[i] = mat->stencil.dims[i]; 4850 B->stencil.starts[i] = mat->stencil.starts[i]; 4851 } 4852 4853 B->nooffproczerorows = mat->nooffproczerorows; 4854 B->nooffprocentries = mat->nooffprocentries; 4855 4856 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm)); 4857 if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm)); 4858 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4859 PetscFunctionReturn(PETSC_SUCCESS); 4860 } 4861 4862 /*@ 4863 MatGetDiagonal - Gets the diagonal of a matrix as a `Vec` 4864 4865 Logically Collective 4866 4867 Input Parameter: 4868 . mat - the matrix 4869 4870 Output Parameter: 4871 . v - the diagonal of the matrix 4872 4873 Level: intermediate 4874 4875 Note: 4876 Currently only correct in parallel for square matrices. 4877 4878 .seealso: [](chapter_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()` 4879 @*/ 4880 PetscErrorCode MatGetDiagonal(Mat mat, Vec v) 4881 { 4882 PetscFunctionBegin; 4883 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4884 PetscValidType(mat, 1); 4885 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4886 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4887 MatCheckPreallocated(mat, 1); 4888 4889 PetscUseTypeMethod(mat, getdiagonal, v); 4890 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4891 PetscFunctionReturn(PETSC_SUCCESS); 4892 } 4893 4894 /*@C 4895 MatGetRowMin - Gets the minimum value (of the real part) of each 4896 row of the matrix 4897 4898 Logically Collective 4899 4900 Input Parameter: 4901 . mat - the matrix 4902 4903 Output Parameters: 4904 + v - the vector for storing the maximums 4905 - idx - the indices of the column found for each row (optional) 4906 4907 Level: intermediate 4908 4909 Note: 4910 The result of this call are the same as if one converted the matrix to dense format 4911 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 4912 4913 This code is only implemented for a couple of matrix formats. 4914 4915 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, 4916 `MatGetRowMax()` 4917 @*/ 4918 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[]) 4919 { 4920 PetscFunctionBegin; 4921 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4922 PetscValidType(mat, 1); 4923 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4924 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4925 4926 if (!mat->cmap->N) { 4927 PetscCall(VecSet(v, PETSC_MAX_REAL)); 4928 if (idx) { 4929 PetscInt i, m = mat->rmap->n; 4930 for (i = 0; i < m; i++) idx[i] = -1; 4931 } 4932 } else { 4933 MatCheckPreallocated(mat, 1); 4934 } 4935 PetscUseTypeMethod(mat, getrowmin, v, idx); 4936 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4937 PetscFunctionReturn(PETSC_SUCCESS); 4938 } 4939 4940 /*@C 4941 MatGetRowMinAbs - Gets the minimum value (in absolute value) of each 4942 row of the matrix 4943 4944 Logically Collective 4945 4946 Input Parameter: 4947 . mat - the matrix 4948 4949 Output Parameters: 4950 + v - the vector for storing the minimums 4951 - idx - the indices of the column found for each row (or `NULL` if not needed) 4952 4953 Level: intermediate 4954 4955 Notes: 4956 if a row is completely empty or has only 0.0 values then the idx[] value for that 4957 row is 0 (the first column). 4958 4959 This code is only implemented for a couple of matrix formats. 4960 4961 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()` 4962 @*/ 4963 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[]) 4964 { 4965 PetscFunctionBegin; 4966 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4967 PetscValidType(mat, 1); 4968 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4969 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4970 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4971 4972 if (!mat->cmap->N) { 4973 PetscCall(VecSet(v, 0.0)); 4974 if (idx) { 4975 PetscInt i, m = mat->rmap->n; 4976 for (i = 0; i < m; i++) idx[i] = -1; 4977 } 4978 } else { 4979 MatCheckPreallocated(mat, 1); 4980 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 4981 PetscUseTypeMethod(mat, getrowminabs, v, idx); 4982 } 4983 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4984 PetscFunctionReturn(PETSC_SUCCESS); 4985 } 4986 4987 /*@C 4988 MatGetRowMax - Gets the maximum value (of the real part) of each 4989 row of the matrix 4990 4991 Logically Collective 4992 4993 Input Parameter: 4994 . mat - the matrix 4995 4996 Output Parameters: 4997 + v - the vector for storing the maximums 4998 - idx - the indices of the column found for each row (optional) 4999 5000 Level: intermediate 5001 5002 Notes: 5003 The result of this call are the same as if one converted the matrix to dense format 5004 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5005 5006 This code is only implemented for a couple of matrix formats. 5007 5008 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5009 @*/ 5010 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[]) 5011 { 5012 PetscFunctionBegin; 5013 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5014 PetscValidType(mat, 1); 5015 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5016 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5017 5018 if (!mat->cmap->N) { 5019 PetscCall(VecSet(v, PETSC_MIN_REAL)); 5020 if (idx) { 5021 PetscInt i, m = mat->rmap->n; 5022 for (i = 0; i < m; i++) idx[i] = -1; 5023 } 5024 } else { 5025 MatCheckPreallocated(mat, 1); 5026 PetscUseTypeMethod(mat, getrowmax, v, idx); 5027 } 5028 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5029 PetscFunctionReturn(PETSC_SUCCESS); 5030 } 5031 5032 /*@C 5033 MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each 5034 row of the matrix 5035 5036 Logically Collective 5037 5038 Input Parameter: 5039 . mat - the matrix 5040 5041 Output Parameters: 5042 + v - the vector for storing the maximums 5043 - idx - the indices of the column found for each row (or `NULL` if not needed) 5044 5045 Level: intermediate 5046 5047 Notes: 5048 if a row is completely empty or has only 0.0 values then the idx[] value for that 5049 row is 0 (the first column). 5050 5051 This code is only implemented for a couple of matrix formats. 5052 5053 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5054 @*/ 5055 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[]) 5056 { 5057 PetscFunctionBegin; 5058 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5059 PetscValidType(mat, 1); 5060 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5061 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5062 5063 if (!mat->cmap->N) { 5064 PetscCall(VecSet(v, 0.0)); 5065 if (idx) { 5066 PetscInt i, m = mat->rmap->n; 5067 for (i = 0; i < m; i++) idx[i] = -1; 5068 } 5069 } else { 5070 MatCheckPreallocated(mat, 1); 5071 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5072 PetscUseTypeMethod(mat, getrowmaxabs, v, idx); 5073 } 5074 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5075 PetscFunctionReturn(PETSC_SUCCESS); 5076 } 5077 5078 /*@ 5079 MatGetRowSum - Gets the sum of each row of the matrix 5080 5081 Logically or Neighborhood Collective 5082 5083 Input Parameter: 5084 . mat - the matrix 5085 5086 Output Parameter: 5087 . v - the vector for storing the sum of rows 5088 5089 Level: intermediate 5090 5091 Notes: 5092 This code is slow since it is not currently specialized for different formats 5093 5094 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()` 5095 @*/ 5096 PetscErrorCode MatGetRowSum(Mat mat, Vec v) 5097 { 5098 Vec ones; 5099 5100 PetscFunctionBegin; 5101 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5102 PetscValidType(mat, 1); 5103 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5104 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5105 MatCheckPreallocated(mat, 1); 5106 PetscCall(MatCreateVecs(mat, &ones, NULL)); 5107 PetscCall(VecSet(ones, 1.)); 5108 PetscCall(MatMult(mat, ones, v)); 5109 PetscCall(VecDestroy(&ones)); 5110 PetscFunctionReturn(PETSC_SUCCESS); 5111 } 5112 5113 /*@ 5114 MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) 5115 when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B) 5116 5117 Collective 5118 5119 Input Parameter: 5120 . mat - the matrix to provide the transpose 5121 5122 Output Parameter: 5123 . 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 5124 5125 Level: advanced 5126 5127 Note: 5128 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 5129 routine allows bypassing that call. 5130 5131 .seealso: [](chapter_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5132 @*/ 5133 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B) 5134 { 5135 PetscContainer rB = NULL; 5136 MatParentState *rb = NULL; 5137 5138 PetscFunctionBegin; 5139 PetscCall(PetscNew(&rb)); 5140 rb->id = ((PetscObject)mat)->id; 5141 rb->state = 0; 5142 PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate)); 5143 PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB)); 5144 PetscCall(PetscContainerSetPointer(rB, rb)); 5145 PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault)); 5146 PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB)); 5147 PetscCall(PetscObjectDereference((PetscObject)rB)); 5148 PetscFunctionReturn(PETSC_SUCCESS); 5149 } 5150 5151 /*@ 5152 MatTranspose - Computes an in-place or out-of-place transpose of a matrix. 5153 5154 Collective 5155 5156 Input Parameters: 5157 + mat - the matrix to transpose 5158 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5159 5160 Output Parameter: 5161 . B - the transpose 5162 5163 Level: intermediate 5164 5165 Notes: 5166 If you use `MAT_INPLACE_MATRIX` then you must pass in &mat for B 5167 5168 `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 5169 transpose, call `MatTransposeSetPrecursor`(mat,B) before calling this routine. 5170 5171 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. 5172 5173 Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed. 5174 5175 If mat is unchanged from the last call this function returns immediately without recomputing the result 5176 5177 If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()` 5178 5179 .seealso: [](chapter_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`, 5180 `MatTransposeSymbolic()`, `MatCreateTranspose()` 5181 @*/ 5182 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B) 5183 { 5184 PetscContainer rB = NULL; 5185 MatParentState *rb = NULL; 5186 5187 PetscFunctionBegin; 5188 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5189 PetscValidType(mat, 1); 5190 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5191 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5192 PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first"); 5193 PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX"); 5194 MatCheckPreallocated(mat, 1); 5195 if (reuse == MAT_REUSE_MATRIX) { 5196 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5197 PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor()."); 5198 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5199 PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5200 if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS); 5201 } 5202 5203 PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0)); 5204 if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) { 5205 PetscUseTypeMethod(mat, transpose, reuse, B); 5206 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5207 } 5208 PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0)); 5209 5210 if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B)); 5211 if (reuse != MAT_INPLACE_MATRIX) { 5212 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5213 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5214 rb->state = ((PetscObject)mat)->state; 5215 rb->nonzerostate = mat->nonzerostate; 5216 } 5217 PetscFunctionReturn(PETSC_SUCCESS); 5218 } 5219 5220 /*@ 5221 MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix. 5222 5223 Collective 5224 5225 Input Parameter: 5226 . A - the matrix to transpose 5227 5228 Output Parameter: 5229 . 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 5230 numerical portion. 5231 5232 Level: intermediate 5233 5234 Note: 5235 This is not supported for many matrix types, use `MatTranspose()` in those cases 5236 5237 .seealso: [](chapter_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5238 @*/ 5239 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B) 5240 { 5241 PetscFunctionBegin; 5242 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5243 PetscValidType(A, 1); 5244 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5245 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5246 PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0)); 5247 PetscUseTypeMethod(A, transposesymbolic, B); 5248 PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0)); 5249 5250 PetscCall(MatTransposeSetPrecursor(A, *B)); 5251 PetscFunctionReturn(PETSC_SUCCESS); 5252 } 5253 5254 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B) 5255 { 5256 PetscContainer rB; 5257 MatParentState *rb; 5258 5259 PetscFunctionBegin; 5260 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5261 PetscValidType(A, 1); 5262 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5263 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5264 PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB)); 5265 PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()"); 5266 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5267 PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5268 PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure"); 5269 PetscFunctionReturn(PETSC_SUCCESS); 5270 } 5271 5272 /*@ 5273 MatIsTranspose - Test whether a matrix is another one's transpose, 5274 or its own, in which case it tests symmetry. 5275 5276 Collective 5277 5278 Input Parameters: 5279 + A - the matrix to test 5280 . B - the matrix to test against, this can equal the first parameter 5281 - tol - tolerance, differences between entries smaller than this are counted as zero 5282 5283 Output Parameter: 5284 . flg - the result 5285 5286 Level: intermediate 5287 5288 Notes: 5289 Only available for `MATAIJ` matrices. 5290 5291 The sequential algorithm has a running time of the order of the number of nonzeros; the parallel 5292 test involves parallel copies of the block-offdiagonal parts of the matrix. 5293 5294 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()` 5295 @*/ 5296 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5297 { 5298 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5299 5300 PetscFunctionBegin; 5301 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5302 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5303 PetscValidBoolPointer(flg, 4); 5304 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f)); 5305 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g)); 5306 *flg = PETSC_FALSE; 5307 if (f && g) { 5308 PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test"); 5309 PetscCall((*f)(A, B, tol, flg)); 5310 } else { 5311 MatType mattype; 5312 5313 PetscCall(MatGetType(f ? B : A, &mattype)); 5314 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype); 5315 } 5316 PetscFunctionReturn(PETSC_SUCCESS); 5317 } 5318 5319 /*@ 5320 MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate. 5321 5322 Collective 5323 5324 Input Parameters: 5325 + mat - the matrix to transpose and complex conjugate 5326 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5327 5328 Output Parameter: 5329 . B - the Hermitian transpose 5330 5331 Level: intermediate 5332 5333 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse` 5334 @*/ 5335 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B) 5336 { 5337 PetscFunctionBegin; 5338 PetscCall(MatTranspose(mat, reuse, B)); 5339 #if defined(PETSC_USE_COMPLEX) 5340 PetscCall(MatConjugate(*B)); 5341 #endif 5342 PetscFunctionReturn(PETSC_SUCCESS); 5343 } 5344 5345 /*@ 5346 MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose, 5347 5348 Collective 5349 5350 Input Parameters: 5351 + A - the matrix to test 5352 . B - the matrix to test against, this can equal the first parameter 5353 - tol - tolerance, differences between entries smaller than this are counted as zero 5354 5355 Output Parameter: 5356 . flg - the result 5357 5358 Level: intermediate 5359 5360 Notes: 5361 Only available for `MATAIJ` matrices. 5362 5363 The sequential algorithm 5364 has a running time of the order of the number of nonzeros; the parallel 5365 test involves parallel copies of the block-offdiagonal parts of the matrix. 5366 5367 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()` 5368 @*/ 5369 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5370 { 5371 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5372 5373 PetscFunctionBegin; 5374 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5375 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5376 PetscValidBoolPointer(flg, 4); 5377 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f)); 5378 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g)); 5379 if (f && g) { 5380 PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test"); 5381 PetscCall((*f)(A, B, tol, flg)); 5382 } 5383 PetscFunctionReturn(PETSC_SUCCESS); 5384 } 5385 5386 /*@ 5387 MatPermute - Creates a new matrix with rows and columns permuted from the 5388 original. 5389 5390 Collective 5391 5392 Input Parameters: 5393 + mat - the matrix to permute 5394 . row - row permutation, each processor supplies only the permutation for its rows 5395 - col - column permutation, each processor supplies only the permutation for its columns 5396 5397 Output Parameter: 5398 . B - the permuted matrix 5399 5400 Level: advanced 5401 5402 Note: 5403 The index sets map from row/col of permuted matrix to row/col of original matrix. 5404 The index sets should be on the same communicator as mat and have the same local sizes. 5405 5406 Developer Note: 5407 If you want to implement `MatPermute()` for a matrix type, and your approach doesn't 5408 exploit the fact that row and col are permutations, consider implementing the 5409 more general `MatCreateSubMatrix()` instead. 5410 5411 .seealso: [](chapter_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()` 5412 @*/ 5413 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B) 5414 { 5415 PetscFunctionBegin; 5416 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5417 PetscValidType(mat, 1); 5418 PetscValidHeaderSpecific(row, IS_CLASSID, 2); 5419 PetscValidHeaderSpecific(col, IS_CLASSID, 3); 5420 PetscValidPointer(B, 4); 5421 PetscCheckSameComm(mat, 1, row, 2); 5422 if (row != col) PetscCheckSameComm(row, 2, col, 3); 5423 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5424 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5425 PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name); 5426 MatCheckPreallocated(mat, 1); 5427 5428 if (mat->ops->permute) { 5429 PetscUseTypeMethod(mat, permute, row, col, B); 5430 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5431 } else { 5432 PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B)); 5433 } 5434 PetscFunctionReturn(PETSC_SUCCESS); 5435 } 5436 5437 /*@ 5438 MatEqual - Compares two matrices. 5439 5440 Collective 5441 5442 Input Parameters: 5443 + A - the first matrix 5444 - B - the second matrix 5445 5446 Output Parameter: 5447 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise. 5448 5449 Level: intermediate 5450 5451 .seealso: [](chapter_matrices), `Mat` 5452 @*/ 5453 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg) 5454 { 5455 PetscFunctionBegin; 5456 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5457 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5458 PetscValidType(A, 1); 5459 PetscValidType(B, 2); 5460 PetscValidBoolPointer(flg, 3); 5461 PetscCheckSameComm(A, 1, B, 2); 5462 MatCheckPreallocated(A, 1); 5463 MatCheckPreallocated(B, 2); 5464 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5465 PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5466 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, 5467 B->cmap->N); 5468 if (A->ops->equal && A->ops->equal == B->ops->equal) { 5469 PetscUseTypeMethod(A, equal, B, flg); 5470 } else { 5471 PetscCall(MatMultEqual(A, B, 10, flg)); 5472 } 5473 PetscFunctionReturn(PETSC_SUCCESS); 5474 } 5475 5476 /*@ 5477 MatDiagonalScale - Scales a matrix on the left and right by diagonal 5478 matrices that are stored as vectors. Either of the two scaling 5479 matrices can be `NULL`. 5480 5481 Collective 5482 5483 Input Parameters: 5484 + mat - the matrix to be scaled 5485 . l - the left scaling vector (or `NULL`) 5486 - r - the right scaling vector (or `NULL`) 5487 5488 Level: intermediate 5489 5490 Note: 5491 `MatDiagonalScale()` computes A = LAR, where 5492 L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector) 5493 The L scales the rows of the matrix, the R scales the columns of the matrix. 5494 5495 .seealso: [](chapter_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()` 5496 @*/ 5497 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r) 5498 { 5499 PetscFunctionBegin; 5500 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5501 PetscValidType(mat, 1); 5502 if (l) { 5503 PetscValidHeaderSpecific(l, VEC_CLASSID, 2); 5504 PetscCheckSameComm(mat, 1, l, 2); 5505 } 5506 if (r) { 5507 PetscValidHeaderSpecific(r, VEC_CLASSID, 3); 5508 PetscCheckSameComm(mat, 1, r, 3); 5509 } 5510 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5511 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5512 MatCheckPreallocated(mat, 1); 5513 if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS); 5514 5515 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5516 PetscUseTypeMethod(mat, diagonalscale, l, r); 5517 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5518 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5519 if (l != r) mat->symmetric = PETSC_BOOL3_FALSE; 5520 PetscFunctionReturn(PETSC_SUCCESS); 5521 } 5522 5523 /*@ 5524 MatScale - Scales all elements of a matrix by a given number. 5525 5526 Logically Collective 5527 5528 Input Parameters: 5529 + mat - the matrix to be scaled 5530 - a - the scaling value 5531 5532 Level: intermediate 5533 5534 .seealso: [](chapter_matrices), `Mat`, `MatDiagonalScale()` 5535 @*/ 5536 PetscErrorCode MatScale(Mat mat, PetscScalar a) 5537 { 5538 PetscFunctionBegin; 5539 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5540 PetscValidType(mat, 1); 5541 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5542 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5543 PetscValidLogicalCollectiveScalar(mat, a, 2); 5544 MatCheckPreallocated(mat, 1); 5545 5546 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5547 if (a != (PetscScalar)1.0) { 5548 PetscUseTypeMethod(mat, scale, a); 5549 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5550 } 5551 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5552 PetscFunctionReturn(PETSC_SUCCESS); 5553 } 5554 5555 /*@ 5556 MatNorm - Calculates various norms of a matrix. 5557 5558 Collective 5559 5560 Input Parameters: 5561 + mat - the matrix 5562 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY` 5563 5564 Output Parameter: 5565 . nrm - the resulting norm 5566 5567 Level: intermediate 5568 5569 .seealso: [](chapter_matrices), `Mat` 5570 @*/ 5571 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm) 5572 { 5573 PetscFunctionBegin; 5574 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5575 PetscValidType(mat, 1); 5576 PetscValidRealPointer(nrm, 3); 5577 5578 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5579 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5580 MatCheckPreallocated(mat, 1); 5581 5582 PetscUseTypeMethod(mat, norm, type, nrm); 5583 PetscFunctionReturn(PETSC_SUCCESS); 5584 } 5585 5586 /* 5587 This variable is used to prevent counting of MatAssemblyBegin() that 5588 are called from within a MatAssemblyEnd(). 5589 */ 5590 static PetscInt MatAssemblyEnd_InUse = 0; 5591 /*@ 5592 MatAssemblyBegin - Begins assembling the matrix. This routine should 5593 be called after completing all calls to `MatSetValues()`. 5594 5595 Collective 5596 5597 Input Parameters: 5598 + mat - the matrix 5599 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5600 5601 Level: beginner 5602 5603 Notes: 5604 `MatSetValues()` generally caches the values that belong to other MPI ranks. The matrix is ready to 5605 use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called. 5606 5607 Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES` 5608 in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before 5609 using the matrix. 5610 5611 ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the 5612 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 5613 a global collective operation requiring all processes that share the matrix. 5614 5615 Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed 5616 out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros 5617 before `MAT_FINAL_ASSEMBLY` so the space is not compressed out. 5618 5619 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()` 5620 @*/ 5621 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type) 5622 { 5623 PetscFunctionBegin; 5624 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5625 PetscValidType(mat, 1); 5626 MatCheckPreallocated(mat, 1); 5627 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?"); 5628 if (mat->assembled) { 5629 mat->was_assembled = PETSC_TRUE; 5630 mat->assembled = PETSC_FALSE; 5631 } 5632 5633 if (!MatAssemblyEnd_InUse) { 5634 PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0)); 5635 PetscTryTypeMethod(mat, assemblybegin, type); 5636 PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0)); 5637 } else PetscTryTypeMethod(mat, assemblybegin, type); 5638 PetscFunctionReturn(PETSC_SUCCESS); 5639 } 5640 5641 /*@ 5642 MatAssembled - Indicates if a matrix has been assembled and is ready for 5643 use; for example, in matrix-vector product. 5644 5645 Not Collective 5646 5647 Input Parameter: 5648 . mat - the matrix 5649 5650 Output Parameter: 5651 . assembled - `PETSC_TRUE` or `PETSC_FALSE` 5652 5653 Level: advanced 5654 5655 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()` 5656 @*/ 5657 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled) 5658 { 5659 PetscFunctionBegin; 5660 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5661 PetscValidBoolPointer(assembled, 2); 5662 *assembled = mat->assembled; 5663 PetscFunctionReturn(PETSC_SUCCESS); 5664 } 5665 5666 /*@ 5667 MatAssemblyEnd - Completes assembling the matrix. This routine should 5668 be called after `MatAssemblyBegin()`. 5669 5670 Collective 5671 5672 Input Parameters: 5673 + mat - the matrix 5674 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5675 5676 Options Database Keys: 5677 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatEndAssembly()` 5678 . -mat_view ::ascii_info_detail - Prints more detailed info 5679 . -mat_view - Prints matrix in ASCII format 5680 . -mat_view ::ascii_matlab - Prints matrix in Matlab format 5681 . -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 5682 . -display <name> - Sets display name (default is host) 5683 . -draw_pause <sec> - Sets number of seconds to pause after display 5684 . -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See [Using MATLAB with PETSc](ch_matlab)) 5685 . -viewer_socket_machine <machine> - Machine to use for socket 5686 . -viewer_socket_port <port> - Port number to use for socket 5687 - -mat_view binary:filename[:append] - Save matrix to file in binary format 5688 5689 Level: beginner 5690 5691 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()` 5692 @*/ 5693 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type) 5694 { 5695 static PetscInt inassm = 0; 5696 PetscBool flg = PETSC_FALSE; 5697 5698 PetscFunctionBegin; 5699 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5700 PetscValidType(mat, 1); 5701 5702 inassm++; 5703 MatAssemblyEnd_InUse++; 5704 if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */ 5705 PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0)); 5706 PetscTryTypeMethod(mat, assemblyend, type); 5707 PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0)); 5708 } else PetscTryTypeMethod(mat, assemblyend, type); 5709 5710 /* Flush assembly is not a true assembly */ 5711 if (type != MAT_FLUSH_ASSEMBLY) { 5712 if (mat->num_ass) { 5713 if (!mat->symmetry_eternal) { 5714 mat->symmetric = PETSC_BOOL3_UNKNOWN; 5715 mat->hermitian = PETSC_BOOL3_UNKNOWN; 5716 } 5717 if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN; 5718 if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN; 5719 } 5720 mat->num_ass++; 5721 mat->assembled = PETSC_TRUE; 5722 mat->ass_nonzerostate = mat->nonzerostate; 5723 } 5724 5725 mat->insertmode = NOT_SET_VALUES; 5726 MatAssemblyEnd_InUse--; 5727 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5728 if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) { 5729 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 5730 5731 if (mat->checksymmetryonassembly) { 5732 PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg)); 5733 if (flg) { 5734 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5735 } else { 5736 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5737 } 5738 } 5739 if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL)); 5740 } 5741 inassm--; 5742 PetscFunctionReturn(PETSC_SUCCESS); 5743 } 5744 5745 /*@ 5746 MatSetOption - Sets a parameter option for a matrix. Some options 5747 may be specific to certain storage formats. Some options 5748 determine how values will be inserted (or added). Sorted, 5749 row-oriented input will generally assemble the fastest. The default 5750 is row-oriented. 5751 5752 Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption` 5753 5754 Input Parameters: 5755 + mat - the matrix 5756 . option - the option, one of those listed below (and possibly others), 5757 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5758 5759 Options Describing Matrix Structure: 5760 + `MAT_SPD` - symmetric positive definite 5761 . `MAT_SYMMETRIC` - symmetric in terms of both structure and value 5762 . `MAT_HERMITIAN` - transpose is the complex conjugation 5763 . `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure 5764 . `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix 5765 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix 5766 - `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix 5767 5768 These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they 5769 do not need to be computed (usually at a high cost) 5770 5771 Options For Use with `MatSetValues()`: 5772 Insert a logically dense subblock, which can be 5773 . `MAT_ROW_ORIENTED` - row-oriented (default) 5774 5775 These options reflect the data you pass in with `MatSetValues()`; it has 5776 nothing to do with how the data is stored internally in the matrix 5777 data structure. 5778 5779 When (re)assembling a matrix, we can restrict the input for 5780 efficiency/debugging purposes. These options include 5781 + `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow) 5782 . `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated 5783 . `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries 5784 . `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry 5785 . `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly 5786 . `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if 5787 any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves 5788 performance for very large process counts. 5789 - `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset 5790 of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly 5791 functions, instead sending only neighbor messages. 5792 5793 Level: intermediate 5794 5795 Notes: 5796 Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg! 5797 5798 Some options are relevant only for particular matrix types and 5799 are thus ignored by others. Other options are not supported by 5800 certain matrix types and will generate an error message if set. 5801 5802 If using Fortran to compute a matrix, one may need to 5803 use the column-oriented option (or convert to the row-oriented 5804 format). 5805 5806 `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion 5807 that would generate a new entry in the nonzero structure is instead 5808 ignored. Thus, if memory has not already been allocated for this particular 5809 data, then the insertion is ignored. For dense matrices, in which 5810 the entire array is allocated, no entries are ever ignored. 5811 Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction 5812 5813 `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion 5814 that would generate a new entry in the nonzero structure instead produces 5815 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 5816 5817 `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion 5818 that would generate a new entry that has not been preallocated will 5819 instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats 5820 only.) This is a useful flag when debugging matrix memory preallocation. 5821 If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 5822 5823 `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for 5824 other processors should be dropped, rather than stashed. 5825 This is useful if you know that the "owning" processor is also 5826 always generating the correct matrix entries, so that PETSc need 5827 not transfer duplicate entries generated on another processor. 5828 5829 `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the 5830 searches during matrix assembly. When this flag is set, the hash table 5831 is created during the first matrix assembly. This hash table is 5832 used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()` 5833 to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag 5834 should be used with `MAT_USE_HASH_TABLE` flag. This option is currently 5835 supported by `MATMPIBAIJ` format only. 5836 5837 `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries 5838 are kept in the nonzero structure 5839 5840 `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating 5841 a zero location in the matrix 5842 5843 `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types 5844 5845 `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the 5846 zero row routines and thus improves performance for very large process counts. 5847 5848 `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular 5849 part of the matrix (since they should match the upper triangular part). 5850 5851 `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a 5852 single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common 5853 with finite difference schemes with non-periodic boundary conditions. 5854 5855 Developer Note: 5856 `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other 5857 places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRIC` or `MAT_SPD` would need to be changed back 5858 to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had 5859 not changed. 5860 5861 .seealso: [](chapter_matrices), `MatOption`, `Mat`, `MatGetOption()` 5862 @*/ 5863 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg) 5864 { 5865 PetscFunctionBegin; 5866 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5867 if (op > 0) { 5868 PetscValidLogicalCollectiveEnum(mat, op, 2); 5869 PetscValidLogicalCollectiveBool(mat, flg, 3); 5870 } 5871 5872 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); 5873 5874 switch (op) { 5875 case MAT_FORCE_DIAGONAL_ENTRIES: 5876 mat->force_diagonals = flg; 5877 PetscFunctionReturn(PETSC_SUCCESS); 5878 case MAT_NO_OFF_PROC_ENTRIES: 5879 mat->nooffprocentries = flg; 5880 PetscFunctionReturn(PETSC_SUCCESS); 5881 case MAT_SUBSET_OFF_PROC_ENTRIES: 5882 mat->assembly_subset = flg; 5883 if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */ 5884 #if !defined(PETSC_HAVE_MPIUNI) 5885 PetscCall(MatStashScatterDestroy_BTS(&mat->stash)); 5886 #endif 5887 mat->stash.first_assembly_done = PETSC_FALSE; 5888 } 5889 PetscFunctionReturn(PETSC_SUCCESS); 5890 case MAT_NO_OFF_PROC_ZERO_ROWS: 5891 mat->nooffproczerorows = flg; 5892 PetscFunctionReturn(PETSC_SUCCESS); 5893 case MAT_SPD: 5894 if (flg) { 5895 mat->spd = PETSC_BOOL3_TRUE; 5896 mat->symmetric = PETSC_BOOL3_TRUE; 5897 mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5898 } else { 5899 mat->spd = PETSC_BOOL3_FALSE; 5900 } 5901 break; 5902 case MAT_SYMMETRIC: 5903 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5904 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5905 #if !defined(PETSC_USE_COMPLEX) 5906 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5907 #endif 5908 break; 5909 case MAT_HERMITIAN: 5910 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5911 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5912 #if !defined(PETSC_USE_COMPLEX) 5913 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5914 #endif 5915 break; 5916 case MAT_STRUCTURALLY_SYMMETRIC: 5917 mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5918 break; 5919 case MAT_SYMMETRY_ETERNAL: 5920 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"); 5921 mat->symmetry_eternal = flg; 5922 if (flg) mat->structural_symmetry_eternal = PETSC_TRUE; 5923 break; 5924 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 5925 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"); 5926 mat->structural_symmetry_eternal = flg; 5927 break; 5928 case MAT_SPD_ETERNAL: 5929 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"); 5930 mat->spd_eternal = flg; 5931 if (flg) { 5932 mat->structural_symmetry_eternal = PETSC_TRUE; 5933 mat->symmetry_eternal = PETSC_TRUE; 5934 } 5935 break; 5936 case MAT_STRUCTURE_ONLY: 5937 mat->structure_only = flg; 5938 break; 5939 case MAT_SORTED_FULL: 5940 mat->sortedfull = flg; 5941 break; 5942 default: 5943 break; 5944 } 5945 PetscTryTypeMethod(mat, setoption, op, flg); 5946 PetscFunctionReturn(PETSC_SUCCESS); 5947 } 5948 5949 /*@ 5950 MatGetOption - Gets a parameter option that has been set for a matrix. 5951 5952 Logically Collective 5953 5954 Input Parameters: 5955 + mat - the matrix 5956 - option - the option, this only responds to certain options, check the code for which ones 5957 5958 Output Parameter: 5959 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5960 5961 Level: intermediate 5962 5963 Notes: 5964 Can only be called after `MatSetSizes()` and `MatSetType()` have been set. 5965 5966 Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or 5967 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 5968 5969 .seealso: [](chapter_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, 5970 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 5971 @*/ 5972 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg) 5973 { 5974 PetscFunctionBegin; 5975 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5976 PetscValidType(mat, 1); 5977 5978 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); 5979 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()"); 5980 5981 switch (op) { 5982 case MAT_NO_OFF_PROC_ENTRIES: 5983 *flg = mat->nooffprocentries; 5984 break; 5985 case MAT_NO_OFF_PROC_ZERO_ROWS: 5986 *flg = mat->nooffproczerorows; 5987 break; 5988 case MAT_SYMMETRIC: 5989 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()"); 5990 break; 5991 case MAT_HERMITIAN: 5992 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()"); 5993 break; 5994 case MAT_STRUCTURALLY_SYMMETRIC: 5995 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()"); 5996 break; 5997 case MAT_SPD: 5998 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()"); 5999 break; 6000 case MAT_SYMMETRY_ETERNAL: 6001 *flg = mat->symmetry_eternal; 6002 break; 6003 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6004 *flg = mat->symmetry_eternal; 6005 break; 6006 default: 6007 break; 6008 } 6009 PetscFunctionReturn(PETSC_SUCCESS); 6010 } 6011 6012 /*@ 6013 MatZeroEntries - Zeros all entries of a matrix. For sparse matrices 6014 this routine retains the old nonzero structure. 6015 6016 Logically Collective 6017 6018 Input Parameter: 6019 . mat - the matrix 6020 6021 Level: intermediate 6022 6023 Note: 6024 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. 6025 See the Performance chapter of the users manual for information on preallocating matrices. 6026 6027 .seealso: [](chapter_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()` 6028 @*/ 6029 PetscErrorCode MatZeroEntries(Mat mat) 6030 { 6031 PetscFunctionBegin; 6032 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6033 PetscValidType(mat, 1); 6034 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6035 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"); 6036 MatCheckPreallocated(mat, 1); 6037 6038 PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0)); 6039 PetscUseTypeMethod(mat, zeroentries); 6040 PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0)); 6041 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6042 PetscFunctionReturn(PETSC_SUCCESS); 6043 } 6044 6045 /*@ 6046 MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal) 6047 of a set of rows and columns of a matrix. 6048 6049 Collective 6050 6051 Input Parameters: 6052 + mat - the matrix 6053 . numRows - the number of rows/columns to zero 6054 . rows - the global row indices 6055 . diag - value put in the diagonal of the eliminated rows 6056 . x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call 6057 - b - optional vector of the right hand side, that will be adjusted by provided solution entries 6058 6059 Level: intermediate 6060 6061 Notes: 6062 This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6063 6064 For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`. 6065 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 6066 6067 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6068 Krylov method to take advantage of the known solution on the zeroed rows. 6069 6070 For the parallel case, all processes that share the matrix (i.e., 6071 those in the communicator used for matrix creation) MUST call this 6072 routine, regardless of whether any rows being zeroed are owned by 6073 them. 6074 6075 Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix. 6076 6077 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6078 list only rows local to itself). 6079 6080 The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine. 6081 6082 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6083 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6084 @*/ 6085 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6086 { 6087 PetscFunctionBegin; 6088 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6089 PetscValidType(mat, 1); 6090 if (numRows) PetscValidIntPointer(rows, 3); 6091 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6092 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6093 MatCheckPreallocated(mat, 1); 6094 6095 PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b); 6096 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6097 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6098 PetscFunctionReturn(PETSC_SUCCESS); 6099 } 6100 6101 /*@ 6102 MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal) 6103 of a set of rows and columns of a matrix. 6104 6105 Collective 6106 6107 Input Parameters: 6108 + mat - the matrix 6109 . is - the rows to zero 6110 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6111 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6112 - b - optional vector of right hand side, that will be adjusted by provided solution 6113 6114 Level: intermediate 6115 6116 Note: 6117 See `MatZeroRowsColumns()` for details on how this routine operates. 6118 6119 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6120 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()` 6121 @*/ 6122 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6123 { 6124 PetscInt numRows; 6125 const PetscInt *rows; 6126 6127 PetscFunctionBegin; 6128 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6129 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6130 PetscValidType(mat, 1); 6131 PetscValidType(is, 2); 6132 PetscCall(ISGetLocalSize(is, &numRows)); 6133 PetscCall(ISGetIndices(is, &rows)); 6134 PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b)); 6135 PetscCall(ISRestoreIndices(is, &rows)); 6136 PetscFunctionReturn(PETSC_SUCCESS); 6137 } 6138 6139 /*@ 6140 MatZeroRows - Zeros all entries (except possibly the main diagonal) 6141 of a set of rows of a matrix. 6142 6143 Collective 6144 6145 Input Parameters: 6146 + mat - the matrix 6147 . numRows - the number of rows to zero 6148 . rows - the global row indices 6149 . diag - value put in the diagonal of the zeroed rows 6150 . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call 6151 - b - optional vector of right hand side, that will be adjusted by provided solution entries 6152 6153 Level: intermediate 6154 6155 Notes: 6156 This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6157 6158 For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`. 6159 6160 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6161 Krylov method to take advantage of the known solution on the zeroed rows. 6162 6163 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) 6164 from the matrix. 6165 6166 Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix 6167 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 6168 formats this does not alter the nonzero structure. 6169 6170 If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure 6171 of the matrix is not changed the values are 6172 merely zeroed. 6173 6174 The user can set a value in the diagonal entry (or for the `MATAIJ` format 6175 formats can optionally remove the main diagonal entry from the 6176 nonzero structure as well, by passing 0.0 as the final argument). 6177 6178 For the parallel case, all processes that share the matrix (i.e., 6179 those in the communicator used for matrix creation) MUST call this 6180 routine, regardless of whether any rows being zeroed are owned by 6181 them. 6182 6183 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6184 list only rows local to itself). 6185 6186 You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it 6187 owns that are to be zeroed. This saves a global synchronization in the implementation. 6188 6189 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6190 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE` 6191 @*/ 6192 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6193 { 6194 PetscFunctionBegin; 6195 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6196 PetscValidType(mat, 1); 6197 if (numRows) PetscValidIntPointer(rows, 3); 6198 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6199 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6200 MatCheckPreallocated(mat, 1); 6201 6202 PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b); 6203 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6204 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6205 PetscFunctionReturn(PETSC_SUCCESS); 6206 } 6207 6208 /*@ 6209 MatZeroRowsIS - Zeros all entries (except possibly the main diagonal) 6210 of a set of rows of a matrix. 6211 6212 Collective 6213 6214 Input Parameters: 6215 + mat - the matrix 6216 . is - index set of rows to remove (if `NULL` then no row is removed) 6217 . diag - value put in all diagonals of eliminated rows 6218 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6219 - b - optional vector of right hand side, that will be adjusted by provided solution 6220 6221 Level: intermediate 6222 6223 Note: 6224 See `MatZeroRows()` for details on how this routine operates. 6225 6226 .seealso: [](chapter_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6227 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6228 @*/ 6229 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6230 { 6231 PetscInt numRows = 0; 6232 const PetscInt *rows = NULL; 6233 6234 PetscFunctionBegin; 6235 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6236 PetscValidType(mat, 1); 6237 if (is) { 6238 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6239 PetscCall(ISGetLocalSize(is, &numRows)); 6240 PetscCall(ISGetIndices(is, &rows)); 6241 } 6242 PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b)); 6243 if (is) PetscCall(ISRestoreIndices(is, &rows)); 6244 PetscFunctionReturn(PETSC_SUCCESS); 6245 } 6246 6247 /*@ 6248 MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal) 6249 of a set of rows of a matrix. These rows must be local to the process. 6250 6251 Collective 6252 6253 Input Parameters: 6254 + mat - the matrix 6255 . numRows - the number of rows to remove 6256 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6257 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6258 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6259 - b - optional vector of right hand side, that will be adjusted by provided solution 6260 6261 Level: intermediate 6262 6263 Notes: 6264 See `MatZeroRows()` for details on how this routine operates. 6265 6266 The grid coordinates are across the entire grid, not just the local portion 6267 6268 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6269 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6270 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6271 `DM_BOUNDARY_PERIODIC` boundary type. 6272 6273 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 6274 a single value per point) you can skip filling those indices. 6275 6276 Fortran Note: 6277 `idxm` and `idxn` should be declared as 6278 $ MatStencil idxm(4,m) 6279 and the values inserted using 6280 .vb 6281 idxm(MatStencil_i,1) = i 6282 idxm(MatStencil_j,1) = j 6283 idxm(MatStencil_k,1) = k 6284 idxm(MatStencil_c,1) = c 6285 etc 6286 .ve 6287 6288 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6289 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6290 @*/ 6291 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6292 { 6293 PetscInt dim = mat->stencil.dim; 6294 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6295 PetscInt *dims = mat->stencil.dims + 1; 6296 PetscInt *starts = mat->stencil.starts; 6297 PetscInt *dxm = (PetscInt *)rows; 6298 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6299 6300 PetscFunctionBegin; 6301 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6302 PetscValidType(mat, 1); 6303 if (numRows) PetscValidPointer(rows, 3); 6304 6305 PetscCall(PetscMalloc1(numRows, &jdxm)); 6306 for (i = 0; i < numRows; ++i) { 6307 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6308 for (j = 0; j < 3 - sdim; ++j) dxm++; 6309 /* Local index in X dir */ 6310 tmp = *dxm++ - starts[0]; 6311 /* Loop over remaining dimensions */ 6312 for (j = 0; j < dim - 1; ++j) { 6313 /* If nonlocal, set index to be negative */ 6314 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6315 /* Update local index */ 6316 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6317 } 6318 /* Skip component slot if necessary */ 6319 if (mat->stencil.noc) dxm++; 6320 /* Local row number */ 6321 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6322 } 6323 PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b)); 6324 PetscCall(PetscFree(jdxm)); 6325 PetscFunctionReturn(PETSC_SUCCESS); 6326 } 6327 6328 /*@ 6329 MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal) 6330 of a set of rows and columns of a matrix. 6331 6332 Collective 6333 6334 Input Parameters: 6335 + mat - the matrix 6336 . numRows - the number of rows/columns to remove 6337 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6338 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6339 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6340 - b - optional vector of right hand side, that will be adjusted by provided solution 6341 6342 Level: intermediate 6343 6344 Notes: 6345 See `MatZeroRowsColumns()` for details on how this routine operates. 6346 6347 The grid coordinates are across the entire grid, not just the local portion 6348 6349 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6350 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6351 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6352 `DM_BOUNDARY_PERIODIC` boundary type. 6353 6354 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 6355 a single value per point) you can skip filling those indices. 6356 6357 Fortran Note: 6358 `idxm` and `idxn` should be declared as 6359 $ MatStencil idxm(4,m) 6360 and the values inserted using 6361 .vb 6362 idxm(MatStencil_i,1) = i 6363 idxm(MatStencil_j,1) = j 6364 idxm(MatStencil_k,1) = k 6365 idxm(MatStencil_c,1) = c 6366 etc 6367 .ve 6368 6369 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6370 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()` 6371 @*/ 6372 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6373 { 6374 PetscInt dim = mat->stencil.dim; 6375 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6376 PetscInt *dims = mat->stencil.dims + 1; 6377 PetscInt *starts = mat->stencil.starts; 6378 PetscInt *dxm = (PetscInt *)rows; 6379 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6380 6381 PetscFunctionBegin; 6382 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6383 PetscValidType(mat, 1); 6384 if (numRows) PetscValidPointer(rows, 3); 6385 6386 PetscCall(PetscMalloc1(numRows, &jdxm)); 6387 for (i = 0; i < numRows; ++i) { 6388 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6389 for (j = 0; j < 3 - sdim; ++j) dxm++; 6390 /* Local index in X dir */ 6391 tmp = *dxm++ - starts[0]; 6392 /* Loop over remaining dimensions */ 6393 for (j = 0; j < dim - 1; ++j) { 6394 /* If nonlocal, set index to be negative */ 6395 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6396 /* Update local index */ 6397 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6398 } 6399 /* Skip component slot if necessary */ 6400 if (mat->stencil.noc) dxm++; 6401 /* Local row number */ 6402 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6403 } 6404 PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b)); 6405 PetscCall(PetscFree(jdxm)); 6406 PetscFunctionReturn(PETSC_SUCCESS); 6407 } 6408 6409 /*@C 6410 MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal) 6411 of a set of rows of a matrix; using local numbering of rows. 6412 6413 Collective 6414 6415 Input Parameters: 6416 + mat - the matrix 6417 . numRows - the number of rows to remove 6418 . rows - the local row indices 6419 . diag - value put in all diagonals of eliminated rows 6420 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6421 - b - optional vector of right hand side, that will be adjusted by provided solution 6422 6423 Level: intermediate 6424 6425 Notes: 6426 Before calling `MatZeroRowsLocal()`, the user must first set the 6427 local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`. 6428 6429 See `MatZeroRows()` for details on how this routine operates. 6430 6431 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`, 6432 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6433 @*/ 6434 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6435 { 6436 PetscFunctionBegin; 6437 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6438 PetscValidType(mat, 1); 6439 if (numRows) PetscValidIntPointer(rows, 3); 6440 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6441 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6442 MatCheckPreallocated(mat, 1); 6443 6444 if (mat->ops->zerorowslocal) { 6445 PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b); 6446 } else { 6447 IS is, newis; 6448 const PetscInt *newRows; 6449 6450 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6451 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6452 PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis)); 6453 PetscCall(ISGetIndices(newis, &newRows)); 6454 PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b); 6455 PetscCall(ISRestoreIndices(newis, &newRows)); 6456 PetscCall(ISDestroy(&newis)); 6457 PetscCall(ISDestroy(&is)); 6458 } 6459 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6460 PetscFunctionReturn(PETSC_SUCCESS); 6461 } 6462 6463 /*@ 6464 MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal) 6465 of a set of rows of a matrix; using local numbering of rows. 6466 6467 Collective 6468 6469 Input Parameters: 6470 + mat - the matrix 6471 . is - index set of rows to remove 6472 . diag - value put in all diagonals of eliminated rows 6473 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6474 - b - optional vector of right hand side, that will be adjusted by provided solution 6475 6476 Level: intermediate 6477 6478 Notes: 6479 Before calling `MatZeroRowsLocalIS()`, the user must first set the 6480 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6481 6482 See `MatZeroRows()` for details on how this routine operates. 6483 6484 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6485 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6486 @*/ 6487 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6488 { 6489 PetscInt numRows; 6490 const PetscInt *rows; 6491 6492 PetscFunctionBegin; 6493 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6494 PetscValidType(mat, 1); 6495 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6496 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6497 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6498 MatCheckPreallocated(mat, 1); 6499 6500 PetscCall(ISGetLocalSize(is, &numRows)); 6501 PetscCall(ISGetIndices(is, &rows)); 6502 PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b)); 6503 PetscCall(ISRestoreIndices(is, &rows)); 6504 PetscFunctionReturn(PETSC_SUCCESS); 6505 } 6506 6507 /*@ 6508 MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal) 6509 of a set of rows and columns of a matrix; using local numbering of rows. 6510 6511 Collective 6512 6513 Input Parameters: 6514 + mat - the matrix 6515 . numRows - the number of rows to remove 6516 . rows - the global row indices 6517 . diag - value put in all diagonals of eliminated rows 6518 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6519 - b - optional vector of right hand side, that will be adjusted by provided solution 6520 6521 Level: intermediate 6522 6523 Notes: 6524 Before calling `MatZeroRowsColumnsLocal()`, the user must first set the 6525 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6526 6527 See `MatZeroRowsColumns()` for details on how this routine operates. 6528 6529 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6530 `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6531 @*/ 6532 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6533 { 6534 IS is, newis; 6535 const PetscInt *newRows; 6536 6537 PetscFunctionBegin; 6538 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6539 PetscValidType(mat, 1); 6540 if (numRows) PetscValidIntPointer(rows, 3); 6541 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6542 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6543 MatCheckPreallocated(mat, 1); 6544 6545 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6546 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6547 PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis)); 6548 PetscCall(ISGetIndices(newis, &newRows)); 6549 PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b); 6550 PetscCall(ISRestoreIndices(newis, &newRows)); 6551 PetscCall(ISDestroy(&newis)); 6552 PetscCall(ISDestroy(&is)); 6553 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6554 PetscFunctionReturn(PETSC_SUCCESS); 6555 } 6556 6557 /*@ 6558 MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal) 6559 of a set of rows and columns of a matrix; using local numbering of rows. 6560 6561 Collective 6562 6563 Input Parameters: 6564 + mat - the matrix 6565 . is - index set of rows to remove 6566 . diag - value put in all diagonals of eliminated rows 6567 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6568 - b - optional vector of right hand side, that will be adjusted by provided solution 6569 6570 Level: intermediate 6571 6572 Notes: 6573 Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the 6574 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6575 6576 See `MatZeroRowsColumns()` for details on how this routine operates. 6577 6578 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6579 `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6580 @*/ 6581 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6582 { 6583 PetscInt numRows; 6584 const PetscInt *rows; 6585 6586 PetscFunctionBegin; 6587 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6588 PetscValidType(mat, 1); 6589 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6590 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6591 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6592 MatCheckPreallocated(mat, 1); 6593 6594 PetscCall(ISGetLocalSize(is, &numRows)); 6595 PetscCall(ISGetIndices(is, &rows)); 6596 PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b)); 6597 PetscCall(ISRestoreIndices(is, &rows)); 6598 PetscFunctionReturn(PETSC_SUCCESS); 6599 } 6600 6601 /*@C 6602 MatGetSize - Returns the numbers of rows and columns in a matrix. 6603 6604 Not Collective 6605 6606 Input Parameter: 6607 . mat - the matrix 6608 6609 Output Parameters: 6610 + m - the number of global rows 6611 - n - the number of global columns 6612 6613 Level: beginner 6614 6615 Note: 6616 Both output parameters can be `NULL` on input. 6617 6618 .seealso: [](chapter_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()` 6619 @*/ 6620 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n) 6621 { 6622 PetscFunctionBegin; 6623 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6624 if (m) *m = mat->rmap->N; 6625 if (n) *n = mat->cmap->N; 6626 PetscFunctionReturn(PETSC_SUCCESS); 6627 } 6628 6629 /*@C 6630 MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns 6631 of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`. 6632 6633 Not Collective 6634 6635 Input Parameter: 6636 . mat - the matrix 6637 6638 Output Parameters: 6639 + m - the number of local rows, use `NULL` to not obtain this value 6640 - n - the number of local columns, use `NULL` to not obtain this value 6641 6642 Level: beginner 6643 6644 .seealso: [](chapter_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()` 6645 @*/ 6646 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n) 6647 { 6648 PetscFunctionBegin; 6649 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6650 if (m) PetscValidIntPointer(m, 2); 6651 if (n) PetscValidIntPointer(n, 3); 6652 if (m) *m = mat->rmap->n; 6653 if (n) *n = mat->cmap->n; 6654 PetscFunctionReturn(PETSC_SUCCESS); 6655 } 6656 6657 /*@C 6658 MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by 6659 this processor. (The columns of the "diagonal block" for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts. 6660 6661 Not Collective, unless matrix has not been allocated, then collective 6662 6663 Input Parameter: 6664 . mat - the matrix 6665 6666 Output Parameters: 6667 + m - the global index of the first local column, use `NULL` to not obtain this value 6668 - n - one more than the global index of the last local column, use `NULL` to not obtain this value 6669 6670 Level: developer 6671 6672 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout` 6673 @*/ 6674 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n) 6675 { 6676 PetscFunctionBegin; 6677 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6678 PetscValidType(mat, 1); 6679 if (m) PetscValidIntPointer(m, 2); 6680 if (n) PetscValidIntPointer(n, 3); 6681 MatCheckPreallocated(mat, 1); 6682 if (m) *m = mat->cmap->rstart; 6683 if (n) *n = mat->cmap->rend; 6684 PetscFunctionReturn(PETSC_SUCCESS); 6685 } 6686 6687 /*@C 6688 MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6689 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 6690 vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts 6691 6692 Not Collective 6693 6694 Input Parameter: 6695 . mat - the matrix 6696 6697 Output Parameters: 6698 + m - the global index of the first local row, use `NULL` to not obtain this value 6699 - n - one more than the global index of the last local row, use `NULL` to not obtain this value 6700 6701 Level: beginner 6702 6703 Note: 6704 This function requires that the matrix be preallocated. If you have not preallocated, consider using 6705 `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N) 6706 and then `MPI_Scan()` to calculate prefix sums of the local sizes. 6707 6708 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, 6709 `PetscLayout` 6710 @*/ 6711 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n) 6712 { 6713 PetscFunctionBegin; 6714 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6715 PetscValidType(mat, 1); 6716 if (m) PetscValidIntPointer(m, 2); 6717 if (n) PetscValidIntPointer(n, 3); 6718 MatCheckPreallocated(mat, 1); 6719 if (m) *m = mat->rmap->rstart; 6720 if (n) *n = mat->rmap->rend; 6721 PetscFunctionReturn(PETSC_SUCCESS); 6722 } 6723 6724 /*@C 6725 MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6726 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 6727 vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts 6728 6729 Not Collective, unless matrix has not been allocated 6730 6731 Input Parameter: 6732 . mat - the matrix 6733 6734 Output Parameter: 6735 . ranges - start of each processors portion plus one more than the total length at the end 6736 6737 Level: beginner 6738 6739 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout` 6740 @*/ 6741 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges) 6742 { 6743 PetscFunctionBegin; 6744 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6745 PetscValidType(mat, 1); 6746 MatCheckPreallocated(mat, 1); 6747 PetscCall(PetscLayoutGetRanges(mat->rmap, ranges)); 6748 PetscFunctionReturn(PETSC_SUCCESS); 6749 } 6750 6751 /*@C 6752 MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by 6753 each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts. 6754 6755 Not Collective, unless matrix has not been allocated 6756 6757 Input Parameter: 6758 . mat - the matrix 6759 6760 Output Parameter: 6761 . ranges - start of each processors portion plus one more then the total length at the end 6762 6763 Level: beginner 6764 6765 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()` 6766 @*/ 6767 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges) 6768 { 6769 PetscFunctionBegin; 6770 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6771 PetscValidType(mat, 1); 6772 MatCheckPreallocated(mat, 1); 6773 PetscCall(PetscLayoutGetRanges(mat->cmap, ranges)); 6774 PetscFunctionReturn(PETSC_SUCCESS); 6775 } 6776 6777 /*@C 6778 MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this 6779 corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership 6780 is more complicated. See :any:`<sec_matlayout>` for details on matrix layouts. 6781 6782 Not Collective 6783 6784 Input Parameter: 6785 . A - matrix 6786 6787 Output Parameters: 6788 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value 6789 - cols - columns in which this process owns elements, use `NULL` to not obtain this value 6790 6791 Level: intermediate 6792 6793 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK`` 6794 @*/ 6795 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols) 6796 { 6797 PetscErrorCode (*f)(Mat, IS *, IS *); 6798 6799 PetscFunctionBegin; 6800 MatCheckPreallocated(A, 1); 6801 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f)); 6802 if (f) { 6803 PetscCall((*f)(A, rows, cols)); 6804 } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */ 6805 if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows)); 6806 if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols)); 6807 } 6808 PetscFunctionReturn(PETSC_SUCCESS); 6809 } 6810 6811 /*@C 6812 MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()` 6813 Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()` 6814 to complete the factorization. 6815 6816 Collective 6817 6818 Input Parameters: 6819 + fact - the factorized matrix obtained with `MatGetFactor()` 6820 . mat - the matrix 6821 . row - row permutation 6822 . col - column permutation 6823 - info - structure containing 6824 .vb 6825 levels - number of levels of fill. 6826 expected fill - as ratio of original fill. 6827 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 6828 missing diagonal entries) 6829 .ve 6830 6831 Level: developer 6832 6833 Notes: 6834 See [Matrix Factorization](sec_matfactor) for additional information. 6835 6836 Most users should employ the `KSP` interface for linear solvers 6837 instead of working directly with matrix algebra routines such as this. 6838 See, e.g., `KSPCreate()`. 6839 6840 Uses the definition of level of fill as in Y. Saad, 2003 6841 6842 Developer Note: 6843 The Fortran interface is not autogenerated as the 6844 interface definition cannot be generated correctly [due to `MatFactorInfo`] 6845 6846 References: 6847 . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003 6848 6849 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 6850 `MatGetOrdering()`, `MatFactorInfo` 6851 @*/ 6852 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 6853 { 6854 PetscFunctionBegin; 6855 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 6856 PetscValidType(mat, 2); 6857 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 6858 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 6859 PetscValidPointer(info, 5); 6860 PetscValidPointer(fact, 1); 6861 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels); 6862 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 6863 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6864 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6865 MatCheckPreallocated(mat, 2); 6866 6867 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0)); 6868 PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info); 6869 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0)); 6870 PetscFunctionReturn(PETSC_SUCCESS); 6871 } 6872 6873 /*@C 6874 MatICCFactorSymbolic - Performs symbolic incomplete 6875 Cholesky factorization for a symmetric matrix. Use 6876 `MatCholeskyFactorNumeric()` to complete the factorization. 6877 6878 Collective 6879 6880 Input Parameters: 6881 + fact - the factorized matrix obtained with `MatGetFactor()` 6882 . mat - the matrix to be factored 6883 . perm - row and column permutation 6884 - info - structure containing 6885 .vb 6886 levels - number of levels of fill. 6887 expected fill - as ratio of original fill. 6888 .ve 6889 6890 Level: developer 6891 6892 Notes: 6893 Most users should employ the `KSP` interface for linear solvers 6894 instead of working directly with matrix algebra routines such as this. 6895 See, e.g., `KSPCreate()`. 6896 6897 This uses the definition of level of fill as in Y. Saad, 2003 6898 6899 Developer Note: 6900 The Fortran interface is not autogenerated as the 6901 interface definition cannot be generated correctly [due to `MatFactorInfo`] 6902 6903 References: 6904 . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003 6905 6906 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 6907 @*/ 6908 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 6909 { 6910 PetscFunctionBegin; 6911 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 6912 PetscValidType(mat, 2); 6913 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 6914 PetscValidPointer(info, 4); 6915 PetscValidPointer(fact, 1); 6916 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6917 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels); 6918 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 6919 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6920 MatCheckPreallocated(mat, 2); 6921 6922 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 6923 PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info); 6924 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 6925 PetscFunctionReturn(PETSC_SUCCESS); 6926 } 6927 6928 /*@C 6929 MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat 6930 points to an array of valid matrices, they may be reused to store the new 6931 submatrices. 6932 6933 Collective 6934 6935 Input Parameters: 6936 + mat - the matrix 6937 . n - the number of submatrixes to be extracted (on this processor, may be zero) 6938 . irow - index set of rows to extract 6939 . icol - index set of columns to extract 6940 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 6941 6942 Output Parameter: 6943 . submat - the array of submatrices 6944 6945 Level: advanced 6946 6947 Notes: 6948 `MatCreateSubMatrices()` can extract ONLY sequential submatrices 6949 (from both sequential and parallel matrices). Use `MatCreateSubMatrix()` 6950 to extract a parallel submatrix. 6951 6952 Some matrix types place restrictions on the row and column 6953 indices, such as that they be sorted or that they be equal to each other. 6954 6955 The index sets may not have duplicate entries. 6956 6957 When extracting submatrices from a parallel matrix, each processor can 6958 form a different submatrix by setting the rows and columns of its 6959 individual index sets according to the local submatrix desired. 6960 6961 When finished using the submatrices, the user should destroy 6962 them with `MatDestroySubMatrices()`. 6963 6964 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 6965 original matrix has not changed from that last call to `MatCreateSubMatrices()`. 6966 6967 This routine creates the matrices in submat; you should NOT create them before 6968 calling it. It also allocates the array of matrix pointers submat. 6969 6970 For `MATBAIJ` matrices the index sets must respect the block structure, that is if they 6971 request one row/column in a block, they must request all rows/columns that are in 6972 that block. For example, if the block size is 2 you cannot request just row 0 and 6973 column 0. 6974 6975 Fortran Note: 6976 The Fortran interface is slightly different from that given below; it 6977 requires one to pass in as `submat` a `Mat` (integer) array of size at least n+1. 6978 6979 .seealso: [](chapter_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 6980 @*/ 6981 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 6982 { 6983 PetscInt i; 6984 PetscBool eq; 6985 6986 PetscFunctionBegin; 6987 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6988 PetscValidType(mat, 1); 6989 if (n) { 6990 PetscValidPointer(irow, 3); 6991 for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3); 6992 PetscValidPointer(icol, 4); 6993 for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4); 6994 } 6995 PetscValidPointer(submat, 6); 6996 if (n && scall == MAT_REUSE_MATRIX) { 6997 PetscValidPointer(*submat, 6); 6998 for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6); 6999 } 7000 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7001 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7002 MatCheckPreallocated(mat, 1); 7003 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7004 PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat); 7005 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7006 for (i = 0; i < n; i++) { 7007 (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */ 7008 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7009 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7010 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 7011 if (mat->boundtocpu && mat->bindingpropagates) { 7012 PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE)); 7013 PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE)); 7014 } 7015 #endif 7016 } 7017 PetscFunctionReturn(PETSC_SUCCESS); 7018 } 7019 7020 /*@C 7021 MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms). 7022 7023 Collective 7024 7025 Input Parameters: 7026 + mat - the matrix 7027 . n - the number of submatrixes to be extracted 7028 . irow - index set of rows to extract 7029 . icol - index set of columns to extract 7030 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7031 7032 Output Parameter: 7033 . submat - the array of submatrices 7034 7035 Level: advanced 7036 7037 Note: 7038 This is used by `PCGASM` 7039 7040 .seealso: [](chapter_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7041 @*/ 7042 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7043 { 7044 PetscInt i; 7045 PetscBool eq; 7046 7047 PetscFunctionBegin; 7048 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7049 PetscValidType(mat, 1); 7050 if (n) { 7051 PetscValidPointer(irow, 3); 7052 PetscValidHeaderSpecific(*irow, IS_CLASSID, 3); 7053 PetscValidPointer(icol, 4); 7054 PetscValidHeaderSpecific(*icol, IS_CLASSID, 4); 7055 } 7056 PetscValidPointer(submat, 6); 7057 if (n && scall == MAT_REUSE_MATRIX) { 7058 PetscValidPointer(*submat, 6); 7059 PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6); 7060 } 7061 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7062 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7063 MatCheckPreallocated(mat, 1); 7064 7065 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7066 PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat); 7067 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7068 for (i = 0; i < n; i++) { 7069 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7070 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7071 } 7072 PetscFunctionReturn(PETSC_SUCCESS); 7073 } 7074 7075 /*@C 7076 MatDestroyMatrices - Destroys an array of matrices. 7077 7078 Collective 7079 7080 Input Parameters: 7081 + n - the number of local matrices 7082 - mat - the matrices (this is a pointer to the array of matrices) 7083 7084 Level: advanced 7085 7086 Note: 7087 Frees not only the matrices, but also the array that contains the matrices 7088 7089 Fortran Note: 7090 This does not free the array. 7091 7092 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()` 7093 @*/ 7094 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[]) 7095 { 7096 PetscInt i; 7097 7098 PetscFunctionBegin; 7099 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7100 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7101 PetscValidPointer(mat, 2); 7102 7103 for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i])); 7104 7105 /* memory is allocated even if n = 0 */ 7106 PetscCall(PetscFree(*mat)); 7107 PetscFunctionReturn(PETSC_SUCCESS); 7108 } 7109 7110 /*@C 7111 MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`. 7112 7113 Collective 7114 7115 Input Parameters: 7116 + n - the number of local matrices 7117 - mat - the matrices (this is a pointer to the array of matrices, just to match the calling 7118 sequence of `MatCreateSubMatrices()`) 7119 7120 Level: advanced 7121 7122 Note: 7123 Frees not only the matrices, but also the array that contains the matrices 7124 7125 Fortran Note: 7126 This does not free the array. 7127 7128 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7129 @*/ 7130 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[]) 7131 { 7132 Mat mat0; 7133 7134 PetscFunctionBegin; 7135 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7136 /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */ 7137 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7138 PetscValidPointer(mat, 2); 7139 7140 mat0 = (*mat)[0]; 7141 if (mat0 && mat0->ops->destroysubmatrices) { 7142 PetscCall((*mat0->ops->destroysubmatrices)(n, mat)); 7143 } else { 7144 PetscCall(MatDestroyMatrices(n, mat)); 7145 } 7146 PetscFunctionReturn(PETSC_SUCCESS); 7147 } 7148 7149 /*@C 7150 MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process 7151 7152 Collective 7153 7154 Input Parameter: 7155 . mat - the matrix 7156 7157 Output Parameter: 7158 . matstruct - the sequential matrix with the nonzero structure of mat 7159 7160 Level: developer 7161 7162 .seealso: [](chapter_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7163 @*/ 7164 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct) 7165 { 7166 PetscFunctionBegin; 7167 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7168 PetscValidPointer(matstruct, 2); 7169 7170 PetscValidType(mat, 1); 7171 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7172 MatCheckPreallocated(mat, 1); 7173 7174 PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7175 PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct); 7176 PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7177 PetscFunctionReturn(PETSC_SUCCESS); 7178 } 7179 7180 /*@C 7181 MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`. 7182 7183 Collective 7184 7185 Input Parameter: 7186 . mat - the matrix (this is a pointer to the array of matrices, just to match the calling 7187 sequence of `MatGetSeqNonzeroStructure()`) 7188 7189 Level: advanced 7190 7191 Note: 7192 Frees not only the matrices, but also the array that contains the matrices 7193 7194 .seealso: [](chapter_matrices), `Mat`, `MatGetSeqNonzeroStructure()` 7195 @*/ 7196 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat) 7197 { 7198 PetscFunctionBegin; 7199 PetscValidPointer(mat, 1); 7200 PetscCall(MatDestroy(mat)); 7201 PetscFunctionReturn(PETSC_SUCCESS); 7202 } 7203 7204 /*@ 7205 MatIncreaseOverlap - Given a set of submatrices indicated by index sets, 7206 replaces the index sets by larger ones that represent submatrices with 7207 additional overlap. 7208 7209 Collective 7210 7211 Input Parameters: 7212 + mat - the matrix 7213 . n - the number of index sets 7214 . is - the array of index sets (these index sets will changed during the call) 7215 - ov - the additional overlap requested 7216 7217 Options Database Key: 7218 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7219 7220 Level: developer 7221 7222 Note: 7223 The computed overlap preserves the matrix block sizes when the blocks are square. 7224 That is: if a matrix nonzero for a given block would increase the overlap all columns associated with 7225 that block are included in the overlap regardless of whether each specific column would increase the overlap. 7226 7227 .seealso: [](chapter_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()` 7228 @*/ 7229 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov) 7230 { 7231 PetscInt i, bs, cbs; 7232 7233 PetscFunctionBegin; 7234 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7235 PetscValidType(mat, 1); 7236 PetscValidLogicalCollectiveInt(mat, n, 2); 7237 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7238 if (n) { 7239 PetscValidPointer(is, 3); 7240 for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3); 7241 } 7242 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7243 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7244 MatCheckPreallocated(mat, 1); 7245 7246 if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS); 7247 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7248 PetscUseTypeMethod(mat, increaseoverlap, n, is, ov); 7249 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7250 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 7251 if (bs == cbs) { 7252 for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs)); 7253 } 7254 PetscFunctionReturn(PETSC_SUCCESS); 7255 } 7256 7257 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt); 7258 7259 /*@ 7260 MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across 7261 a sub communicator, replaces the index sets by larger ones that represent submatrices with 7262 additional overlap. 7263 7264 Collective 7265 7266 Input Parameters: 7267 + mat - the matrix 7268 . n - the number of index sets 7269 . is - the array of index sets (these index sets will changed during the call) 7270 - ov - the additional overlap requested 7271 7272 ` Options Database Key: 7273 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7274 7275 Level: developer 7276 7277 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()` 7278 @*/ 7279 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov) 7280 { 7281 PetscInt i; 7282 7283 PetscFunctionBegin; 7284 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7285 PetscValidType(mat, 1); 7286 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7287 if (n) { 7288 PetscValidPointer(is, 3); 7289 PetscValidHeaderSpecific(*is, IS_CLASSID, 3); 7290 } 7291 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7292 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7293 MatCheckPreallocated(mat, 1); 7294 if (!ov) PetscFunctionReturn(PETSC_SUCCESS); 7295 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7296 for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov)); 7297 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7298 PetscFunctionReturn(PETSC_SUCCESS); 7299 } 7300 7301 /*@ 7302 MatGetBlockSize - Returns the matrix block size. 7303 7304 Not Collective 7305 7306 Input Parameter: 7307 . mat - the matrix 7308 7309 Output Parameter: 7310 . bs - block size 7311 7312 Level: intermediate 7313 7314 Notes: 7315 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7316 7317 If the block size has not been set yet this routine returns 1. 7318 7319 .seealso: [](chapter_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()` 7320 @*/ 7321 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs) 7322 { 7323 PetscFunctionBegin; 7324 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7325 PetscValidIntPointer(bs, 2); 7326 *bs = PetscAbs(mat->rmap->bs); 7327 PetscFunctionReturn(PETSC_SUCCESS); 7328 } 7329 7330 /*@ 7331 MatGetBlockSizes - Returns the matrix block row and column sizes. 7332 7333 Not Collective 7334 7335 Input Parameter: 7336 . mat - the matrix 7337 7338 Output Parameters: 7339 + rbs - row block size 7340 - cbs - column block size 7341 7342 Level: intermediate 7343 7344 Notes: 7345 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7346 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7347 7348 If a block size has not been set yet this routine returns 1. 7349 7350 .seealso: [](chapter_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()` 7351 @*/ 7352 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs) 7353 { 7354 PetscFunctionBegin; 7355 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7356 if (rbs) PetscValidIntPointer(rbs, 2); 7357 if (cbs) PetscValidIntPointer(cbs, 3); 7358 if (rbs) *rbs = PetscAbs(mat->rmap->bs); 7359 if (cbs) *cbs = PetscAbs(mat->cmap->bs); 7360 PetscFunctionReturn(PETSC_SUCCESS); 7361 } 7362 7363 /*@ 7364 MatSetBlockSize - Sets the matrix block size. 7365 7366 Logically Collective 7367 7368 Input Parameters: 7369 + mat - the matrix 7370 - bs - block size 7371 7372 Level: intermediate 7373 7374 Notes: 7375 Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix. 7376 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7377 7378 For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size 7379 is compatible with the matrix local sizes. 7380 7381 .seealso: [](chapter_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()` 7382 @*/ 7383 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs) 7384 { 7385 PetscFunctionBegin; 7386 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7387 PetscValidLogicalCollectiveInt(mat, bs, 2); 7388 PetscCall(MatSetBlockSizes(mat, bs, bs)); 7389 PetscFunctionReturn(PETSC_SUCCESS); 7390 } 7391 7392 typedef struct { 7393 PetscInt n; 7394 IS *is; 7395 Mat *mat; 7396 PetscObjectState nonzerostate; 7397 Mat C; 7398 } EnvelopeData; 7399 7400 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata) 7401 { 7402 for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i])); 7403 PetscCall(PetscFree(edata->is)); 7404 PetscCall(PetscFree(edata)); 7405 return PETSC_SUCCESS; 7406 } 7407 7408 /* 7409 MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores 7410 the sizes of these blocks in the matrix. An individual block may lie over several processes. 7411 7412 Collective 7413 7414 Input Parameter: 7415 . mat - the matrix 7416 7417 Notes: 7418 There can be zeros within the blocks 7419 7420 The blocks can overlap between processes, including laying on more than two processes 7421 7422 .seealso: [](chapter_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()` 7423 */ 7424 static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat) 7425 { 7426 PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend; 7427 PetscInt *diag, *odiag, sc; 7428 VecScatter scatter; 7429 PetscScalar *seqv; 7430 const PetscScalar *parv; 7431 const PetscInt *ia, *ja; 7432 PetscBool set, flag, done; 7433 Mat AA = mat, A; 7434 MPI_Comm comm; 7435 PetscMPIInt rank, size, tag; 7436 MPI_Status status; 7437 PetscContainer container; 7438 EnvelopeData *edata; 7439 Vec seq, par; 7440 IS isglobal; 7441 7442 PetscFunctionBegin; 7443 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7444 PetscCall(MatIsSymmetricKnown(mat, &set, &flag)); 7445 if (!set || !flag) { 7446 /* TOO: only needs nonzero structure of transpose */ 7447 PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA)); 7448 PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN)); 7449 } 7450 PetscCall(MatAIJGetLocalMat(AA, &A)); 7451 PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7452 PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix"); 7453 7454 PetscCall(MatGetLocalSize(mat, &n, NULL)); 7455 PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag)); 7456 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 7457 PetscCallMPI(MPI_Comm_size(comm, &size)); 7458 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7459 7460 PetscCall(PetscMalloc2(n, &sizes, n, &starts)); 7461 7462 if (rank > 0) { 7463 PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7464 PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7465 } 7466 PetscCall(MatGetOwnershipRange(mat, &rstart, NULL)); 7467 for (i = 0; i < n; i++) { 7468 env = PetscMax(env, ja[ia[i + 1] - 1]); 7469 II = rstart + i; 7470 if (env == II) { 7471 starts[lblocks] = tbs; 7472 sizes[lblocks++] = 1 + II - tbs; 7473 tbs = 1 + II; 7474 } 7475 } 7476 if (rank < size - 1) { 7477 PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm)); 7478 PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm)); 7479 } 7480 7481 PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7482 if (!set || !flag) PetscCall(MatDestroy(&AA)); 7483 PetscCall(MatDestroy(&A)); 7484 7485 PetscCall(PetscNew(&edata)); 7486 PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate)); 7487 edata->n = lblocks; 7488 /* create IS needed for extracting blocks from the original matrix */ 7489 PetscCall(PetscMalloc1(lblocks, &edata->is)); 7490 for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i])); 7491 7492 /* Create the resulting inverse matrix structure with preallocation information */ 7493 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C)); 7494 PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 7495 PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat)); 7496 PetscCall(MatSetType(edata->C, MATAIJ)); 7497 7498 /* Communicate the start and end of each row, from each block to the correct rank */ 7499 /* TODO: Use PetscSF instead of VecScatter */ 7500 for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i]; 7501 PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq)); 7502 PetscCall(VecGetArrayWrite(seq, &seqv)); 7503 for (PetscInt i = 0; i < lblocks; i++) { 7504 for (PetscInt j = 0; j < sizes[i]; j++) { 7505 seqv[cnt] = starts[i]; 7506 seqv[cnt + 1] = starts[i] + sizes[i]; 7507 cnt += 2; 7508 } 7509 } 7510 PetscCall(VecRestoreArrayWrite(seq, &seqv)); 7511 PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 7512 sc -= cnt; 7513 PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par)); 7514 PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal)); 7515 PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter)); 7516 PetscCall(ISDestroy(&isglobal)); 7517 PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7518 PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7519 PetscCall(VecScatterDestroy(&scatter)); 7520 PetscCall(VecDestroy(&seq)); 7521 PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend)); 7522 PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag)); 7523 PetscCall(VecGetArrayRead(par, &parv)); 7524 cnt = 0; 7525 PetscCall(MatGetSize(mat, NULL, &n)); 7526 for (PetscInt i = 0; i < mat->rmap->n; i++) { 7527 PetscInt start, end, d = 0, od = 0; 7528 7529 start = (PetscInt)PetscRealPart(parv[cnt]); 7530 end = (PetscInt)PetscRealPart(parv[cnt + 1]); 7531 cnt += 2; 7532 7533 if (start < cstart) { 7534 od += cstart - start + n - cend; 7535 d += cend - cstart; 7536 } else if (start < cend) { 7537 od += n - cend; 7538 d += cend - start; 7539 } else od += n - start; 7540 if (end <= cstart) { 7541 od -= cstart - end + n - cend; 7542 d -= cend - cstart; 7543 } else if (end < cend) { 7544 od -= n - cend; 7545 d -= cend - end; 7546 } else od -= n - end; 7547 7548 odiag[i] = od; 7549 diag[i] = d; 7550 } 7551 PetscCall(VecRestoreArrayRead(par, &parv)); 7552 PetscCall(VecDestroy(&par)); 7553 PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL)); 7554 PetscCall(PetscFree2(diag, odiag)); 7555 PetscCall(PetscFree2(sizes, starts)); 7556 7557 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container)); 7558 PetscCall(PetscContainerSetPointer(container, edata)); 7559 PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy)); 7560 PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container)); 7561 PetscCall(PetscObjectDereference((PetscObject)container)); 7562 PetscFunctionReturn(PETSC_SUCCESS); 7563 } 7564 7565 /*@ 7566 MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A 7567 7568 Collective 7569 7570 Input Parameters: 7571 + A - the matrix 7572 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine 7573 7574 Output Parameter: 7575 . C - matrix with inverted block diagonal of `A` 7576 7577 Level: advanced 7578 7579 Note: 7580 For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal. 7581 7582 .seealso: [](chapter_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()` 7583 @*/ 7584 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C) 7585 { 7586 PetscContainer container; 7587 EnvelopeData *edata; 7588 PetscObjectState nonzerostate; 7589 7590 PetscFunctionBegin; 7591 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7592 if (!container) { 7593 PetscCall(MatComputeVariableBlockEnvelope(A)); 7594 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7595 } 7596 PetscCall(PetscContainerGetPointer(container, (void **)&edata)); 7597 PetscCall(MatGetNonzeroState(A, &nonzerostate)); 7598 PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure"); 7599 PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output"); 7600 7601 PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat)); 7602 *C = edata->C; 7603 7604 for (PetscInt i = 0; i < edata->n; i++) { 7605 Mat D; 7606 PetscScalar *dvalues; 7607 7608 PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D)); 7609 PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE)); 7610 PetscCall(MatSeqDenseInvert(D)); 7611 PetscCall(MatDenseGetArray(D, &dvalues)); 7612 PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES)); 7613 PetscCall(MatDestroy(&D)); 7614 } 7615 PetscCall(MatDestroySubMatrices(edata->n, &edata->mat)); 7616 PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY)); 7617 PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY)); 7618 PetscFunctionReturn(PETSC_SUCCESS); 7619 } 7620 7621 /*@ 7622 MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size 7623 7624 Logically Collective 7625 7626 Input Parameters: 7627 + mat - the matrix 7628 . nblocks - the number of blocks on this process, each block can only exist on a single process 7629 - bsizes - the block sizes 7630 7631 Level: intermediate 7632 7633 Notes: 7634 Currently used by `PCVPBJACOBI` for `MATAIJ` matrices 7635 7636 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. 7637 7638 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, 7639 `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI` 7640 @*/ 7641 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes) 7642 { 7643 PetscInt i, ncnt = 0, nlocal; 7644 7645 PetscFunctionBegin; 7646 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7647 PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero"); 7648 PetscCall(MatGetLocalSize(mat, &nlocal, NULL)); 7649 for (i = 0; i < nblocks; i++) ncnt += bsizes[i]; 7650 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); 7651 PetscCall(PetscFree(mat->bsizes)); 7652 mat->nblocks = nblocks; 7653 PetscCall(PetscMalloc1(nblocks, &mat->bsizes)); 7654 PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks)); 7655 PetscFunctionReturn(PETSC_SUCCESS); 7656 } 7657 7658 /*@C 7659 MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size 7660 7661 Logically Collective; No Fortran Support 7662 7663 Input Parameter: 7664 . mat - the matrix 7665 7666 Output Parameters: 7667 + nblocks - the number of blocks on this process 7668 - bsizes - the block sizes 7669 7670 Level: intermediate 7671 7672 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()` 7673 @*/ 7674 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes) 7675 { 7676 PetscFunctionBegin; 7677 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7678 *nblocks = mat->nblocks; 7679 *bsizes = mat->bsizes; 7680 PetscFunctionReturn(PETSC_SUCCESS); 7681 } 7682 7683 /*@ 7684 MatSetBlockSizes - Sets the matrix block row and column sizes. 7685 7686 Logically Collective 7687 7688 Input Parameters: 7689 + mat - the matrix 7690 . rbs - row block size 7691 - cbs - column block size 7692 7693 Level: intermediate 7694 7695 Notes: 7696 Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix. 7697 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7698 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7699 7700 For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes 7701 are compatible with the matrix local sizes. 7702 7703 The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`. 7704 7705 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()` 7706 @*/ 7707 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs) 7708 { 7709 PetscFunctionBegin; 7710 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7711 PetscValidLogicalCollectiveInt(mat, rbs, 2); 7712 PetscValidLogicalCollectiveInt(mat, cbs, 3); 7713 PetscTryTypeMethod(mat, setblocksizes, rbs, cbs); 7714 if (mat->rmap->refcnt) { 7715 ISLocalToGlobalMapping l2g = NULL; 7716 PetscLayout nmap = NULL; 7717 7718 PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap)); 7719 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g)); 7720 PetscCall(PetscLayoutDestroy(&mat->rmap)); 7721 mat->rmap = nmap; 7722 mat->rmap->mapping = l2g; 7723 } 7724 if (mat->cmap->refcnt) { 7725 ISLocalToGlobalMapping l2g = NULL; 7726 PetscLayout nmap = NULL; 7727 7728 PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap)); 7729 if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g)); 7730 PetscCall(PetscLayoutDestroy(&mat->cmap)); 7731 mat->cmap = nmap; 7732 mat->cmap->mapping = l2g; 7733 } 7734 PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs)); 7735 PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs)); 7736 PetscFunctionReturn(PETSC_SUCCESS); 7737 } 7738 7739 /*@ 7740 MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices 7741 7742 Logically Collective 7743 7744 Input Parameters: 7745 + mat - the matrix 7746 . fromRow - matrix from which to copy row block size 7747 - fromCol - matrix from which to copy column block size (can be same as fromRow) 7748 7749 Level: developer 7750 7751 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()` 7752 @*/ 7753 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol) 7754 { 7755 PetscFunctionBegin; 7756 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7757 PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2); 7758 PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3); 7759 if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs)); 7760 if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs)); 7761 PetscFunctionReturn(PETSC_SUCCESS); 7762 } 7763 7764 /*@ 7765 MatResidual - Default routine to calculate the residual r = b - Ax 7766 7767 Collective 7768 7769 Input Parameters: 7770 + mat - the matrix 7771 . b - the right-hand-side 7772 - x - the approximate solution 7773 7774 Output Parameter: 7775 . r - location to store the residual 7776 7777 Level: developer 7778 7779 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()` 7780 @*/ 7781 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r) 7782 { 7783 PetscFunctionBegin; 7784 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7785 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 7786 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 7787 PetscValidHeaderSpecific(r, VEC_CLASSID, 4); 7788 PetscValidType(mat, 1); 7789 MatCheckPreallocated(mat, 1); 7790 PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0)); 7791 if (!mat->ops->residual) { 7792 PetscCall(MatMult(mat, x, r)); 7793 PetscCall(VecAYPX(r, -1.0, b)); 7794 } else { 7795 PetscUseTypeMethod(mat, residual, b, x, r); 7796 } 7797 PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0)); 7798 PetscFunctionReturn(PETSC_SUCCESS); 7799 } 7800 7801 /*MC 7802 MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix 7803 7804 Synopsis: 7805 MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 7806 7807 Not Collective 7808 7809 Input Parameters: 7810 + A - the matrix 7811 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7812 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7813 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7814 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7815 always used. 7816 7817 Output Parameters: 7818 + n - number of local rows in the (possibly compressed) matrix 7819 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 7820 . ja - the column indices 7821 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7822 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7823 7824 Level: developer 7825 7826 Note: 7827 Use `MatRestoreRowIJF90()` when you no longer need access to the data 7828 7829 .seealso: [](chapter_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()` 7830 M*/ 7831 7832 /*MC 7833 MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()` 7834 7835 Synopsis: 7836 MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 7837 7838 Not Collective 7839 7840 Input Parameters: 7841 + A - the matrix 7842 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7843 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7844 inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7845 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7846 always used. 7847 . n - number of local rows in the (possibly compressed) matrix 7848 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 7849 . ja - the column indices 7850 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7851 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7852 7853 Level: developer 7854 7855 .seealso: [](chapter_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()` 7856 M*/ 7857 7858 /*@C 7859 MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix 7860 7861 Collective 7862 7863 Input Parameters: 7864 + mat - the matrix 7865 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7866 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7867 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7868 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7869 always used. 7870 7871 Output Parameters: 7872 + n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed 7873 . 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 7874 . ja - the column indices, use `NULL` if not needed 7875 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7876 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7877 7878 Level: developer 7879 7880 Notes: 7881 You CANNOT change any of the ia[] or ja[] values. 7882 7883 Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values. 7884 7885 Fortran Notes: 7886 Use 7887 .vb 7888 PetscInt, pointer :: ia(:),ja(:) 7889 call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr) 7890 ! Access the ith and jth entries via ia(i) and ja(j) 7891 .ve 7892 `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()` 7893 7894 .seealso: [](chapter_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()` 7895 @*/ 7896 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7897 { 7898 PetscFunctionBegin; 7899 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7900 PetscValidType(mat, 1); 7901 if (n) PetscValidIntPointer(n, 5); 7902 if (ia) PetscValidPointer(ia, 6); 7903 if (ja) PetscValidPointer(ja, 7); 7904 if (done) PetscValidBoolPointer(done, 8); 7905 MatCheckPreallocated(mat, 1); 7906 if (!mat->ops->getrowij && done) *done = PETSC_FALSE; 7907 else { 7908 if (done) *done = PETSC_TRUE; 7909 PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0)); 7910 PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done); 7911 PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0)); 7912 } 7913 PetscFunctionReturn(PETSC_SUCCESS); 7914 } 7915 7916 /*@C 7917 MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices. 7918 7919 Collective 7920 7921 Input Parameters: 7922 + mat - the matrix 7923 . shift - 1 or zero indicating we want the indices starting at 0 or 1 7924 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be 7925 symmetrized 7926 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7927 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7928 always used. 7929 . n - number of columns in the (possibly compressed) matrix 7930 . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix 7931 - ja - the row indices 7932 7933 Output Parameter: 7934 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned 7935 7936 Level: developer 7937 7938 .seealso: [](chapter_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 7939 @*/ 7940 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7941 { 7942 PetscFunctionBegin; 7943 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7944 PetscValidType(mat, 1); 7945 PetscValidIntPointer(n, 5); 7946 if (ia) PetscValidPointer(ia, 6); 7947 if (ja) PetscValidPointer(ja, 7); 7948 PetscValidBoolPointer(done, 8); 7949 MatCheckPreallocated(mat, 1); 7950 if (!mat->ops->getcolumnij) *done = PETSC_FALSE; 7951 else { 7952 *done = PETSC_TRUE; 7953 PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 7954 } 7955 PetscFunctionReturn(PETSC_SUCCESS); 7956 } 7957 7958 /*@C 7959 MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`. 7960 7961 Collective 7962 7963 Input Parameters: 7964 + mat - the matrix 7965 . shift - 1 or zero indicating we want the indices starting at 0 or 1 7966 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7967 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7968 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7969 always used. 7970 . n - size of (possibly compressed) matrix 7971 . ia - the row pointers 7972 - ja - the column indices 7973 7974 Output Parameter: 7975 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 7976 7977 Level: developer 7978 7979 Note: 7980 This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental 7981 us of the array after it has been restored. If you pass `NULL`, it will 7982 not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid. 7983 7984 Fortran Note: 7985 `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()` 7986 7987 .seealso: [](chapter_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()` 7988 @*/ 7989 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7990 { 7991 PetscFunctionBegin; 7992 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7993 PetscValidType(mat, 1); 7994 if (ia) PetscValidPointer(ia, 6); 7995 if (ja) PetscValidPointer(ja, 7); 7996 if (done) PetscValidBoolPointer(done, 8); 7997 MatCheckPreallocated(mat, 1); 7998 7999 if (!mat->ops->restorerowij && done) *done = PETSC_FALSE; 8000 else { 8001 if (done) *done = PETSC_TRUE; 8002 PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8003 if (n) *n = 0; 8004 if (ia) *ia = NULL; 8005 if (ja) *ja = NULL; 8006 } 8007 PetscFunctionReturn(PETSC_SUCCESS); 8008 } 8009 8010 /*@C 8011 MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`. 8012 8013 Collective 8014 8015 Input Parameters: 8016 + mat - the matrix 8017 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8018 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8019 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8020 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8021 always used. 8022 8023 Output Parameters: 8024 + n - size of (possibly compressed) matrix 8025 . ia - the column pointers 8026 . ja - the row indices 8027 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8028 8029 Level: developer 8030 8031 .seealso: [](chapter_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()` 8032 @*/ 8033 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8034 { 8035 PetscFunctionBegin; 8036 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8037 PetscValidType(mat, 1); 8038 if (ia) PetscValidPointer(ia, 6); 8039 if (ja) PetscValidPointer(ja, 7); 8040 PetscValidBoolPointer(done, 8); 8041 MatCheckPreallocated(mat, 1); 8042 8043 if (!mat->ops->restorecolumnij) *done = PETSC_FALSE; 8044 else { 8045 *done = PETSC_TRUE; 8046 PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8047 if (n) *n = 0; 8048 if (ia) *ia = NULL; 8049 if (ja) *ja = NULL; 8050 } 8051 PetscFunctionReturn(PETSC_SUCCESS); 8052 } 8053 8054 /*@C 8055 MatColoringPatch -Used inside matrix coloring routines that use `MatGetRowIJ()` and/or `MatGetColumnIJ()`. 8056 8057 Collective 8058 8059 Input Parameters: 8060 + mat - the matrix 8061 . ncolors - maximum color value 8062 . n - number of entries in colorarray 8063 - colorarray - array indicating color for each column 8064 8065 Output Parameter: 8066 . iscoloring - coloring generated using colorarray information 8067 8068 Level: developer 8069 8070 .seealso: [](chapter_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()` 8071 @*/ 8072 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring) 8073 { 8074 PetscFunctionBegin; 8075 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8076 PetscValidType(mat, 1); 8077 PetscValidIntPointer(colorarray, 4); 8078 PetscValidPointer(iscoloring, 5); 8079 MatCheckPreallocated(mat, 1); 8080 8081 if (!mat->ops->coloringpatch) { 8082 PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring)); 8083 } else { 8084 PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring); 8085 } 8086 PetscFunctionReturn(PETSC_SUCCESS); 8087 } 8088 8089 /*@ 8090 MatSetUnfactored - Resets a factored matrix to be treated as unfactored. 8091 8092 Logically Collective 8093 8094 Input Parameter: 8095 . mat - the factored matrix to be reset 8096 8097 Level: developer 8098 8099 Notes: 8100 This routine should be used only with factored matrices formed by in-place 8101 factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE` 8102 format). This option can save memory, for example, when solving nonlinear 8103 systems with a matrix-free Newton-Krylov method and a matrix-based, in-place 8104 ILU(0) preconditioner. 8105 8106 One can specify in-place ILU(0) factorization by calling 8107 .vb 8108 PCType(pc,PCILU); 8109 PCFactorSeUseInPlace(pc); 8110 .ve 8111 or by using the options -pc_type ilu -pc_factor_in_place 8112 8113 In-place factorization ILU(0) can also be used as a local 8114 solver for the blocks within the block Jacobi or additive Schwarz 8115 methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc 8116 for details on setting local solver options. 8117 8118 Most users should employ the `KSP` interface for linear solvers 8119 instead of working directly with matrix algebra routines such as this. 8120 See, e.g., `KSPCreate()`. 8121 8122 .seealso: [](chapter_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()` 8123 @*/ 8124 PetscErrorCode MatSetUnfactored(Mat mat) 8125 { 8126 PetscFunctionBegin; 8127 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8128 PetscValidType(mat, 1); 8129 MatCheckPreallocated(mat, 1); 8130 mat->factortype = MAT_FACTOR_NONE; 8131 if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS); 8132 PetscUseTypeMethod(mat, setunfactored); 8133 PetscFunctionReturn(PETSC_SUCCESS); 8134 } 8135 8136 /*MC 8137 MatDenseGetArrayF90 - Accesses a matrix array from Fortran 8138 8139 Synopsis: 8140 MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8141 8142 Not Collective 8143 8144 Input Parameter: 8145 . x - matrix 8146 8147 Output Parameters: 8148 + xx_v - the Fortran pointer to the array 8149 - ierr - error code 8150 8151 Example of Usage: 8152 .vb 8153 PetscScalar, pointer xx_v(:,:) 8154 .... 8155 call MatDenseGetArrayF90(x,xx_v,ierr) 8156 a = xx_v(3) 8157 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8158 .ve 8159 8160 Level: advanced 8161 8162 .seealso: [](chapter_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()` 8163 M*/ 8164 8165 /*MC 8166 MatDenseRestoreArrayF90 - Restores a matrix array that has been 8167 accessed with `MatDenseGetArrayF90()`. 8168 8169 Synopsis: 8170 MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8171 8172 Not Collective 8173 8174 Input Parameters: 8175 + x - matrix 8176 - xx_v - the Fortran90 pointer to the array 8177 8178 Output Parameter: 8179 . ierr - error code 8180 8181 Example of Usage: 8182 .vb 8183 PetscScalar, pointer xx_v(:,:) 8184 .... 8185 call MatDenseGetArrayF90(x,xx_v,ierr) 8186 a = xx_v(3) 8187 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8188 .ve 8189 8190 Level: advanced 8191 8192 .seealso: [](chapter_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()` 8193 M*/ 8194 8195 /*MC 8196 MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran. 8197 8198 Synopsis: 8199 MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8200 8201 Not Collective 8202 8203 Input Parameter: 8204 . x - matrix 8205 8206 Output Parameters: 8207 + xx_v - the Fortran pointer to the array 8208 - ierr - error code 8209 8210 Example of Usage: 8211 .vb 8212 PetscScalar, pointer xx_v(:) 8213 .... 8214 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8215 a = xx_v(3) 8216 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8217 .ve 8218 8219 Level: advanced 8220 8221 .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()` 8222 M*/ 8223 8224 /*MC 8225 MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been 8226 accessed with `MatSeqAIJGetArrayF90()`. 8227 8228 Synopsis: 8229 MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8230 8231 Not Collective 8232 8233 Input Parameters: 8234 + x - matrix 8235 - xx_v - the Fortran90 pointer to the array 8236 8237 Output Parameter: 8238 . ierr - error code 8239 8240 Example of Usage: 8241 .vb 8242 PetscScalar, pointer xx_v(:) 8243 .... 8244 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8245 a = xx_v(3) 8246 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8247 .ve 8248 8249 Level: advanced 8250 8251 .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()` 8252 M*/ 8253 8254 /*@ 8255 MatCreateSubMatrix - Gets a single submatrix on the same number of processors 8256 as the original matrix. 8257 8258 Collective 8259 8260 Input Parameters: 8261 + mat - the original matrix 8262 . isrow - parallel `IS` containing the rows this processor should obtain 8263 . 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. 8264 - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 8265 8266 Output Parameter: 8267 . newmat - the new submatrix, of the same type as the original matrix 8268 8269 Level: advanced 8270 8271 Notes: 8272 The submatrix will be able to be multiplied with vectors using the same layout as `iscol`. 8273 8274 Some matrix types place restrictions on the row and column indices, such 8275 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; 8276 for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row. 8277 8278 The index sets may not have duplicate entries. 8279 8280 The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`, 8281 the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls 8282 to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX` 8283 will reuse the matrix generated the first time. You should call `MatDestroy()` on `newmat` when 8284 you are finished using it. 8285 8286 The communicator of the newly obtained matrix is ALWAYS the same as the communicator of 8287 the input matrix. 8288 8289 If `iscol` is `NULL` then all columns are obtained (not supported in Fortran). 8290 8291 Example usage: 8292 Consider the following 8x8 matrix with 34 non-zero values, that is 8293 assembled across 3 processors. Let's assume that proc0 owns 3 rows, 8294 proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 8295 as follows 8296 .vb 8297 1 2 0 | 0 3 0 | 0 4 8298 Proc0 0 5 6 | 7 0 0 | 8 0 8299 9 0 10 | 11 0 0 | 12 0 8300 ------------------------------------- 8301 13 0 14 | 15 16 17 | 0 0 8302 Proc1 0 18 0 | 19 20 21 | 0 0 8303 0 0 0 | 22 23 0 | 24 0 8304 ------------------------------------- 8305 Proc2 25 26 27 | 0 0 28 | 29 0 8306 30 0 0 | 31 32 33 | 0 34 8307 .ve 8308 8309 Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6]. The resulting submatrix is 8310 8311 .vb 8312 2 0 | 0 3 0 | 0 8313 Proc0 5 6 | 7 0 0 | 8 8314 ------------------------------- 8315 Proc1 18 0 | 19 20 21 | 0 8316 ------------------------------- 8317 Proc2 26 27 | 0 0 28 | 29 8318 0 0 | 31 32 33 | 0 8319 .ve 8320 8321 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()` 8322 @*/ 8323 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat) 8324 { 8325 PetscMPIInt size; 8326 Mat *local; 8327 IS iscoltmp; 8328 PetscBool flg; 8329 8330 PetscFunctionBegin; 8331 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8332 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 8333 if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 8334 PetscValidPointer(newmat, 5); 8335 if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5); 8336 PetscValidType(mat, 1); 8337 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8338 PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX"); 8339 8340 MatCheckPreallocated(mat, 1); 8341 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8342 8343 if (!iscol || isrow == iscol) { 8344 PetscBool stride; 8345 PetscMPIInt grabentirematrix = 0, grab; 8346 PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride)); 8347 if (stride) { 8348 PetscInt first, step, n, rstart, rend; 8349 PetscCall(ISStrideGetInfo(isrow, &first, &step)); 8350 if (step == 1) { 8351 PetscCall(MatGetOwnershipRange(mat, &rstart, &rend)); 8352 if (rstart == first) { 8353 PetscCall(ISGetLocalSize(isrow, &n)); 8354 if (n == rend - rstart) grabentirematrix = 1; 8355 } 8356 } 8357 } 8358 PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat))); 8359 if (grab) { 8360 PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n")); 8361 if (cll == MAT_INITIAL_MATRIX) { 8362 *newmat = mat; 8363 PetscCall(PetscObjectReference((PetscObject)mat)); 8364 } 8365 PetscFunctionReturn(PETSC_SUCCESS); 8366 } 8367 } 8368 8369 if (!iscol) { 8370 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp)); 8371 } else { 8372 iscoltmp = iscol; 8373 } 8374 8375 /* if original matrix is on just one processor then use submatrix generated */ 8376 if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) { 8377 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat)); 8378 goto setproperties; 8379 } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) { 8380 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local)); 8381 *newmat = *local; 8382 PetscCall(PetscFree(local)); 8383 goto setproperties; 8384 } else if (!mat->ops->createsubmatrix) { 8385 /* Create a new matrix type that implements the operation using the full matrix */ 8386 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8387 switch (cll) { 8388 case MAT_INITIAL_MATRIX: 8389 PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat)); 8390 break; 8391 case MAT_REUSE_MATRIX: 8392 PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp)); 8393 break; 8394 default: 8395 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX"); 8396 } 8397 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8398 goto setproperties; 8399 } 8400 8401 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8402 PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat); 8403 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8404 8405 setproperties: 8406 PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg)); 8407 if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat)); 8408 if (!iscol) PetscCall(ISDestroy(&iscoltmp)); 8409 if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat)); 8410 PetscFunctionReturn(PETSC_SUCCESS); 8411 } 8412 8413 /*@ 8414 MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix 8415 8416 Not Collective 8417 8418 Input Parameters: 8419 + A - the matrix we wish to propagate options from 8420 - B - the matrix we wish to propagate options to 8421 8422 Level: beginner 8423 8424 Note: 8425 Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL` 8426 8427 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, MatIsStructurallySymmetricKnown()` 8428 @*/ 8429 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B) 8430 { 8431 PetscFunctionBegin; 8432 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8433 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 8434 B->symmetry_eternal = A->symmetry_eternal; 8435 B->structural_symmetry_eternal = A->structural_symmetry_eternal; 8436 B->symmetric = A->symmetric; 8437 B->structurally_symmetric = A->structurally_symmetric; 8438 B->spd = A->spd; 8439 B->hermitian = A->hermitian; 8440 PetscFunctionReturn(PETSC_SUCCESS); 8441 } 8442 8443 /*@ 8444 MatStashSetInitialSize - sets the sizes of the matrix stash, that is 8445 used during the assembly process to store values that belong to 8446 other processors. 8447 8448 Not Collective 8449 8450 Input Parameters: 8451 + mat - the matrix 8452 . size - the initial size of the stash. 8453 - bsize - the initial size of the block-stash(if used). 8454 8455 Options Database Keys: 8456 + -matstash_initial_size <size> or <size0,size1,...sizep-1> 8457 - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1> 8458 8459 Level: intermediate 8460 8461 Notes: 8462 The block-stash is used for values set with `MatSetValuesBlocked()` while 8463 the stash is used for values set with `MatSetValues()` 8464 8465 Run with the option -info and look for output of the form 8466 MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs. 8467 to determine the appropriate value, MM, to use for size and 8468 MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs. 8469 to determine the value, BMM to use for bsize 8470 8471 .seealso: [](chapter_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()` 8472 @*/ 8473 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize) 8474 { 8475 PetscFunctionBegin; 8476 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8477 PetscValidType(mat, 1); 8478 PetscCall(MatStashSetInitialSize_Private(&mat->stash, size)); 8479 PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize)); 8480 PetscFunctionReturn(PETSC_SUCCESS); 8481 } 8482 8483 /*@ 8484 MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of 8485 the matrix 8486 8487 Neighbor-wise Collective 8488 8489 Input Parameters: 8490 + mat - the matrix 8491 . x - the vector to be multiplied by the interpolation operator 8492 - y - the vector to be added to the result 8493 8494 Output Parameter: 8495 . w - the resulting vector 8496 8497 Level: intermediate 8498 8499 Notes: 8500 `w` may be the same vector as `y`. 8501 8502 This allows one to use either the restriction or interpolation (its transpose) 8503 matrix to do the interpolation 8504 8505 .seealso: [](chapter_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8506 @*/ 8507 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w) 8508 { 8509 PetscInt M, N, Ny; 8510 8511 PetscFunctionBegin; 8512 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8513 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8514 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8515 PetscValidHeaderSpecific(w, VEC_CLASSID, 4); 8516 PetscCall(MatGetSize(A, &M, &N)); 8517 PetscCall(VecGetSize(y, &Ny)); 8518 if (M == Ny) { 8519 PetscCall(MatMultAdd(A, x, y, w)); 8520 } else { 8521 PetscCall(MatMultTransposeAdd(A, x, y, w)); 8522 } 8523 PetscFunctionReturn(PETSC_SUCCESS); 8524 } 8525 8526 /*@ 8527 MatInterpolate - y = A*x or A'*x depending on the shape of 8528 the matrix 8529 8530 Neighbor-wise Collective 8531 8532 Input Parameters: 8533 + mat - the matrix 8534 - x - the vector to be interpolated 8535 8536 Output Parameter: 8537 . y - the resulting vector 8538 8539 Level: intermediate 8540 8541 Note: 8542 This allows one to use either the restriction or interpolation (its transpose) 8543 matrix to do the interpolation 8544 8545 .seealso: [](chapter_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8546 @*/ 8547 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y) 8548 { 8549 PetscInt M, N, Ny; 8550 8551 PetscFunctionBegin; 8552 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8553 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8554 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8555 PetscCall(MatGetSize(A, &M, &N)); 8556 PetscCall(VecGetSize(y, &Ny)); 8557 if (M == Ny) { 8558 PetscCall(MatMult(A, x, y)); 8559 } else { 8560 PetscCall(MatMultTranspose(A, x, y)); 8561 } 8562 PetscFunctionReturn(PETSC_SUCCESS); 8563 } 8564 8565 /*@ 8566 MatRestrict - y = A*x or A'*x 8567 8568 Neighbor-wise Collective 8569 8570 Input Parameters: 8571 + mat - the matrix 8572 - x - the vector to be restricted 8573 8574 Output Parameter: 8575 . y - the resulting vector 8576 8577 Level: intermediate 8578 8579 Note: 8580 This allows one to use either the restriction or interpolation (its transpose) 8581 matrix to do the restriction 8582 8583 .seealso: [](chapter_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG` 8584 @*/ 8585 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y) 8586 { 8587 PetscInt M, N, Ny; 8588 8589 PetscFunctionBegin; 8590 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8591 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8592 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8593 PetscCall(MatGetSize(A, &M, &N)); 8594 PetscCall(VecGetSize(y, &Ny)); 8595 if (M == Ny) { 8596 PetscCall(MatMult(A, x, y)); 8597 } else { 8598 PetscCall(MatMultTranspose(A, x, y)); 8599 } 8600 PetscFunctionReturn(PETSC_SUCCESS); 8601 } 8602 8603 /*@ 8604 MatMatInterpolateAdd - Y = W + A*X or W + A'*X 8605 8606 Neighbor-wise Collective 8607 8608 Input Parameters: 8609 + mat - the matrix 8610 . x - the input dense matrix to be multiplied 8611 - w - the input dense matrix to be added to the result 8612 8613 Output Parameter: 8614 . y - the output dense matrix 8615 8616 Level: intermediate 8617 8618 Note: 8619 This allows one to use either the restriction or interpolation (its transpose) 8620 matrix to do the interpolation. y matrix can be reused if already created with the proper sizes, 8621 otherwise it will be recreated. y must be initialized to `NULL` if not supplied. 8622 8623 .seealso: [](chapter_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG` 8624 @*/ 8625 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y) 8626 { 8627 PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0; 8628 PetscBool trans = PETSC_TRUE; 8629 MatReuse reuse = MAT_INITIAL_MATRIX; 8630 8631 PetscFunctionBegin; 8632 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8633 PetscValidHeaderSpecific(x, MAT_CLASSID, 2); 8634 PetscValidType(x, 2); 8635 if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3); 8636 if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4); 8637 PetscCall(MatGetSize(A, &M, &N)); 8638 PetscCall(MatGetSize(x, &Mx, &Nx)); 8639 if (N == Mx) trans = PETSC_FALSE; 8640 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); 8641 Mo = trans ? N : M; 8642 if (*y) { 8643 PetscCall(MatGetSize(*y, &My, &Ny)); 8644 if (Mo == My && Nx == Ny) { 8645 reuse = MAT_REUSE_MATRIX; 8646 } else { 8647 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); 8648 PetscCall(MatDestroy(y)); 8649 } 8650 } 8651 8652 if (w && *y == w) { /* this is to minimize changes in PCMG */ 8653 PetscBool flg; 8654 8655 PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w)); 8656 if (w) { 8657 PetscInt My, Ny, Mw, Nw; 8658 8659 PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg)); 8660 PetscCall(MatGetSize(*y, &My, &Ny)); 8661 PetscCall(MatGetSize(w, &Mw, &Nw)); 8662 if (!flg || My != Mw || Ny != Nw) w = NULL; 8663 } 8664 if (!w) { 8665 PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w)); 8666 PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w)); 8667 PetscCall(PetscObjectDereference((PetscObject)w)); 8668 } else { 8669 PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN)); 8670 } 8671 } 8672 if (!trans) { 8673 PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8674 } else { 8675 PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8676 } 8677 if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN)); 8678 PetscFunctionReturn(PETSC_SUCCESS); 8679 } 8680 8681 /*@ 8682 MatMatInterpolate - Y = A*X or A'*X 8683 8684 Neighbor-wise Collective 8685 8686 Input Parameters: 8687 + mat - the matrix 8688 - x - the input dense matrix 8689 8690 Output Parameter: 8691 . y - the output dense matrix 8692 8693 Level: intermediate 8694 8695 Note: 8696 This allows one to use either the restriction or interpolation (its transpose) 8697 matrix to do the interpolation. y matrix can be reused if already created with the proper sizes, 8698 otherwise it will be recreated. y must be initialized to `NULL` if not supplied. 8699 8700 .seealso: [](chapter_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG` 8701 @*/ 8702 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y) 8703 { 8704 PetscFunctionBegin; 8705 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8706 PetscFunctionReturn(PETSC_SUCCESS); 8707 } 8708 8709 /*@ 8710 MatMatRestrict - Y = A*X or A'*X 8711 8712 Neighbor-wise Collective 8713 8714 Input Parameters: 8715 + mat - the matrix 8716 - x - the input dense matrix 8717 8718 Output Parameter: 8719 . y - the output dense matrix 8720 8721 Level: intermediate 8722 8723 Note: 8724 This allows one to use either the restriction or interpolation (its transpose) 8725 matrix to do the restriction. y matrix can be reused if already created with the proper sizes, 8726 otherwise it will be recreated. y must be initialized to `NULL` if not supplied. 8727 8728 .seealso: [](chapter_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG` 8729 @*/ 8730 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y) 8731 { 8732 PetscFunctionBegin; 8733 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8734 PetscFunctionReturn(PETSC_SUCCESS); 8735 } 8736 8737 /*@ 8738 MatGetNullSpace - retrieves the null space of a matrix. 8739 8740 Logically Collective 8741 8742 Input Parameters: 8743 + mat - the matrix 8744 - nullsp - the null space object 8745 8746 Level: developer 8747 8748 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace` 8749 @*/ 8750 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp) 8751 { 8752 PetscFunctionBegin; 8753 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8754 PetscValidPointer(nullsp, 2); 8755 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp; 8756 PetscFunctionReturn(PETSC_SUCCESS); 8757 } 8758 8759 /*@ 8760 MatSetNullSpace - attaches a null space to a matrix. 8761 8762 Logically Collective 8763 8764 Input Parameters: 8765 + mat - the matrix 8766 - nullsp - the null space object 8767 8768 Level: advanced 8769 8770 Notes: 8771 This null space is used by the `KSP` linear solvers to solve singular systems. 8772 8773 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` 8774 8775 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 8776 to zero but the linear system will still be solved in a least squares sense. 8777 8778 The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that 8779 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). 8780 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 8781 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 8782 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). 8783 This \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix. 8784 8785 If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called 8786 `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this 8787 routine also automatically calls `MatSetTransposeNullSpace()`. 8788 8789 The user should call `MatNullSpaceDestroy()`. 8790 8791 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, 8792 `KSPSetPCSide()` 8793 @*/ 8794 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp) 8795 { 8796 PetscFunctionBegin; 8797 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8798 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8799 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8800 PetscCall(MatNullSpaceDestroy(&mat->nullsp)); 8801 mat->nullsp = nullsp; 8802 if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp)); 8803 PetscFunctionReturn(PETSC_SUCCESS); 8804 } 8805 8806 /*@ 8807 MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix. 8808 8809 Logically Collective 8810 8811 Input Parameters: 8812 + mat - the matrix 8813 - nullsp - the null space object 8814 8815 Level: developer 8816 8817 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()` 8818 @*/ 8819 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp) 8820 { 8821 PetscFunctionBegin; 8822 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8823 PetscValidType(mat, 1); 8824 PetscValidPointer(nullsp, 2); 8825 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp; 8826 PetscFunctionReturn(PETSC_SUCCESS); 8827 } 8828 8829 /*@ 8830 MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix 8831 8832 Logically Collective 8833 8834 Input Parameters: 8835 + mat - the matrix 8836 - nullsp - the null space object 8837 8838 Level: advanced 8839 8840 Notes: 8841 This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning. 8842 8843 See `MatSetNullSpace()` 8844 8845 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()` 8846 @*/ 8847 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp) 8848 { 8849 PetscFunctionBegin; 8850 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8851 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8852 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8853 PetscCall(MatNullSpaceDestroy(&mat->transnullsp)); 8854 mat->transnullsp = nullsp; 8855 PetscFunctionReturn(PETSC_SUCCESS); 8856 } 8857 8858 /*@ 8859 MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions 8860 This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix. 8861 8862 Logically Collective 8863 8864 Input Parameters: 8865 + mat - the matrix 8866 - nullsp - the null space object 8867 8868 Level: advanced 8869 8870 Notes: 8871 Overwrites any previous near null space that may have been attached 8872 8873 You can remove the null space by calling this routine with an nullsp of `NULL` 8874 8875 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()` 8876 @*/ 8877 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp) 8878 { 8879 PetscFunctionBegin; 8880 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8881 PetscValidType(mat, 1); 8882 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8883 MatCheckPreallocated(mat, 1); 8884 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8885 PetscCall(MatNullSpaceDestroy(&mat->nearnullsp)); 8886 mat->nearnullsp = nullsp; 8887 PetscFunctionReturn(PETSC_SUCCESS); 8888 } 8889 8890 /*@ 8891 MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()` 8892 8893 Not Collective 8894 8895 Input Parameter: 8896 . mat - the matrix 8897 8898 Output Parameter: 8899 . nullsp - the null space object, `NULL` if not set 8900 8901 Level: advanced 8902 8903 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()` 8904 @*/ 8905 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp) 8906 { 8907 PetscFunctionBegin; 8908 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8909 PetscValidType(mat, 1); 8910 PetscValidPointer(nullsp, 2); 8911 MatCheckPreallocated(mat, 1); 8912 *nullsp = mat->nearnullsp; 8913 PetscFunctionReturn(PETSC_SUCCESS); 8914 } 8915 8916 /*@C 8917 MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix. 8918 8919 Collective 8920 8921 Input Parameters: 8922 + mat - the matrix 8923 . row - row/column permutation 8924 - info - information on desired factorization process 8925 8926 Level: developer 8927 8928 Notes: 8929 Probably really in-place only when level of fill is zero, otherwise allocates 8930 new space to store factored matrix and deletes previous memory. 8931 8932 Most users should employ the `KSP` interface for linear solvers 8933 instead of working directly with matrix algebra routines such as this. 8934 See, e.g., `KSPCreate()`. 8935 8936 Developer Note: 8937 The Fortran interface is not autogenerated as the 8938 interface definition cannot be generated correctly [due to `MatFactorInfo`] 8939 8940 .seealso: [](chapter_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 8941 @*/ 8942 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info) 8943 { 8944 PetscFunctionBegin; 8945 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8946 PetscValidType(mat, 1); 8947 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 8948 PetscValidPointer(info, 3); 8949 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 8950 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 8951 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8952 MatCheckPreallocated(mat, 1); 8953 PetscUseTypeMethod(mat, iccfactor, row, info); 8954 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 8955 PetscFunctionReturn(PETSC_SUCCESS); 8956 } 8957 8958 /*@ 8959 MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the 8960 ghosted ones. 8961 8962 Not Collective 8963 8964 Input Parameters: 8965 + mat - the matrix 8966 - diag - the diagonal values, including ghost ones 8967 8968 Level: developer 8969 8970 Notes: 8971 Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices 8972 8973 This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()` 8974 8975 .seealso: [](chapter_matrices), `Mat`, `MatDiagonalScale()` 8976 @*/ 8977 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag) 8978 { 8979 PetscMPIInt size; 8980 8981 PetscFunctionBegin; 8982 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8983 PetscValidHeaderSpecific(diag, VEC_CLASSID, 2); 8984 PetscValidType(mat, 1); 8985 8986 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled"); 8987 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 8988 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8989 if (size == 1) { 8990 PetscInt n, m; 8991 PetscCall(VecGetSize(diag, &n)); 8992 PetscCall(MatGetSize(mat, NULL, &m)); 8993 PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions"); 8994 PetscCall(MatDiagonalScale(mat, NULL, diag)); 8995 } else { 8996 PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag)); 8997 } 8998 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 8999 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9000 PetscFunctionReturn(PETSC_SUCCESS); 9001 } 9002 9003 /*@ 9004 MatGetInertia - Gets the inertia from a factored matrix 9005 9006 Collective 9007 9008 Input Parameter: 9009 . mat - the matrix 9010 9011 Output Parameters: 9012 + nneg - number of negative eigenvalues 9013 . nzero - number of zero eigenvalues 9014 - npos - number of positive eigenvalues 9015 9016 Level: advanced 9017 9018 Note: 9019 Matrix must have been factored by `MatCholeskyFactor()` 9020 9021 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()` 9022 @*/ 9023 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos) 9024 { 9025 PetscFunctionBegin; 9026 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9027 PetscValidType(mat, 1); 9028 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9029 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled"); 9030 PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos); 9031 PetscFunctionReturn(PETSC_SUCCESS); 9032 } 9033 9034 /*@C 9035 MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors 9036 9037 Neighbor-wise Collective 9038 9039 Input Parameters: 9040 + mat - the factored matrix obtained with `MatGetFactor()` 9041 - b - the right-hand-side vectors 9042 9043 Output Parameter: 9044 . x - the result vectors 9045 9046 Level: developer 9047 9048 Note: 9049 The vectors `b` and `x` cannot be the same. I.e., one cannot 9050 call `MatSolves`(A,x,x). 9051 9052 .seealso: [](chapter_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()` 9053 @*/ 9054 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x) 9055 { 9056 PetscFunctionBegin; 9057 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9058 PetscValidType(mat, 1); 9059 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 9060 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9061 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 9062 9063 MatCheckPreallocated(mat, 1); 9064 PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0)); 9065 PetscUseTypeMethod(mat, solves, b, x); 9066 PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0)); 9067 PetscFunctionReturn(PETSC_SUCCESS); 9068 } 9069 9070 /*@ 9071 MatIsSymmetric - Test whether a matrix is symmetric 9072 9073 Collective 9074 9075 Input Parameters: 9076 + A - the matrix to test 9077 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose) 9078 9079 Output Parameter: 9080 . flg - the result 9081 9082 Level: intermediate 9083 9084 Notes: 9085 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9086 9087 If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()` 9088 9089 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9090 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9091 9092 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`, 9093 `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()` 9094 @*/ 9095 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg) 9096 { 9097 PetscFunctionBegin; 9098 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9099 PetscValidBoolPointer(flg, 3); 9100 9101 if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE; 9102 else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE; 9103 else { 9104 PetscUseTypeMethod(A, issymmetric, tol, flg); 9105 if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg)); 9106 } 9107 PetscFunctionReturn(PETSC_SUCCESS); 9108 } 9109 9110 /*@ 9111 MatIsHermitian - Test whether a matrix is Hermitian 9112 9113 Collective 9114 9115 Input Parameters: 9116 + A - the matrix to test 9117 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian) 9118 9119 Output Parameter: 9120 . flg - the result 9121 9122 Level: intermediate 9123 9124 Notes: 9125 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9126 9127 If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()` 9128 9129 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9130 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`) 9131 9132 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, 9133 `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()` 9134 @*/ 9135 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg) 9136 { 9137 PetscFunctionBegin; 9138 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9139 PetscValidBoolPointer(flg, 3); 9140 9141 if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE; 9142 else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE; 9143 else { 9144 PetscUseTypeMethod(A, ishermitian, tol, flg); 9145 if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg)); 9146 } 9147 PetscFunctionReturn(PETSC_SUCCESS); 9148 } 9149 9150 /*@ 9151 MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state 9152 9153 Not Collective 9154 9155 Input Parameter: 9156 . A - the matrix to check 9157 9158 Output Parameters: 9159 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid) 9160 - flg - the result (only valid if set is `PETSC_TRUE`) 9161 9162 Level: advanced 9163 9164 Notes: 9165 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()` 9166 if you want it explicitly checked 9167 9168 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9169 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9170 9171 .seealso: [](chapter_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9172 @*/ 9173 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9174 { 9175 PetscFunctionBegin; 9176 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9177 PetscValidBoolPointer(set, 2); 9178 PetscValidBoolPointer(flg, 3); 9179 if (A->symmetric != PETSC_BOOL3_UNKNOWN) { 9180 *set = PETSC_TRUE; 9181 *flg = PetscBool3ToBool(A->symmetric); 9182 } else { 9183 *set = PETSC_FALSE; 9184 } 9185 PetscFunctionReturn(PETSC_SUCCESS); 9186 } 9187 9188 /*@ 9189 MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state 9190 9191 Not Collective 9192 9193 Input Parameter: 9194 . A - the matrix to check 9195 9196 Output Parameters: 9197 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid) 9198 - flg - the result (only valid if set is `PETSC_TRUE`) 9199 9200 Level: advanced 9201 9202 Notes: 9203 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). 9204 9205 One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD 9206 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`) 9207 9208 .seealso: [](chapter_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9209 @*/ 9210 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg) 9211 { 9212 PetscFunctionBegin; 9213 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9214 PetscValidBoolPointer(set, 2); 9215 PetscValidBoolPointer(flg, 3); 9216 if (A->spd != PETSC_BOOL3_UNKNOWN) { 9217 *set = PETSC_TRUE; 9218 *flg = PetscBool3ToBool(A->spd); 9219 } else { 9220 *set = PETSC_FALSE; 9221 } 9222 PetscFunctionReturn(PETSC_SUCCESS); 9223 } 9224 9225 /*@ 9226 MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state 9227 9228 Not Collective 9229 9230 Input Parameter: 9231 . A - the matrix to check 9232 9233 Output Parameters: 9234 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid) 9235 - flg - the result (only valid if set is `PETSC_TRUE`) 9236 9237 Level: advanced 9238 9239 Notes: 9240 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()` 9241 if you want it explicitly checked 9242 9243 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9244 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9245 9246 .seealso: [](chapter_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()` 9247 @*/ 9248 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg) 9249 { 9250 PetscFunctionBegin; 9251 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9252 PetscValidBoolPointer(set, 2); 9253 PetscValidBoolPointer(flg, 3); 9254 if (A->hermitian != PETSC_BOOL3_UNKNOWN) { 9255 *set = PETSC_TRUE; 9256 *flg = PetscBool3ToBool(A->hermitian); 9257 } else { 9258 *set = PETSC_FALSE; 9259 } 9260 PetscFunctionReturn(PETSC_SUCCESS); 9261 } 9262 9263 /*@ 9264 MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric 9265 9266 Collective 9267 9268 Input Parameter: 9269 . A - the matrix to test 9270 9271 Output Parameter: 9272 . flg - the result 9273 9274 Level: intermediate 9275 9276 Notes: 9277 If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()` 9278 9279 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 9280 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9281 9282 .seealso: [](chapter_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()` 9283 @*/ 9284 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg) 9285 { 9286 PetscFunctionBegin; 9287 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9288 PetscValidBoolPointer(flg, 2); 9289 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9290 *flg = PetscBool3ToBool(A->structurally_symmetric); 9291 } else { 9292 PetscUseTypeMethod(A, isstructurallysymmetric, flg); 9293 PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg)); 9294 } 9295 PetscFunctionReturn(PETSC_SUCCESS); 9296 } 9297 9298 /*@ 9299 MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state 9300 9301 Not Collective 9302 9303 Input Parameter: 9304 . A - the matrix to check 9305 9306 Output Parameters: 9307 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid) 9308 - flg - the result (only valid if set is PETSC_TRUE) 9309 9310 Level: advanced 9311 9312 Notes: 9313 One can declare that a matrix is structurally symmetric with `MatSetOption`(mat,`MAT_STRUCTURALLY_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain structurally 9314 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9315 9316 Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation) 9317 9318 .seealso: [](chapter_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9319 @*/ 9320 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9321 { 9322 PetscFunctionBegin; 9323 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9324 PetscValidBoolPointer(set, 2); 9325 PetscValidBoolPointer(flg, 3); 9326 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9327 *set = PETSC_TRUE; 9328 *flg = PetscBool3ToBool(A->structurally_symmetric); 9329 } else { 9330 *set = PETSC_FALSE; 9331 } 9332 PetscFunctionReturn(PETSC_SUCCESS); 9333 } 9334 9335 /*@ 9336 MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need 9337 to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process 9338 9339 Not Collective 9340 9341 Input Parameter: 9342 . mat - the matrix 9343 9344 Output Parameters: 9345 + nstash - the size of the stash 9346 . reallocs - the number of additional mallocs incurred. 9347 . bnstash - the size of the block stash 9348 - breallocs - the number of additional mallocs incurred.in the block stash 9349 9350 Level: advanced 9351 9352 .seealso: [](chapter_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()` 9353 @*/ 9354 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs) 9355 { 9356 PetscFunctionBegin; 9357 PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs)); 9358 PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs)); 9359 PetscFunctionReturn(PETSC_SUCCESS); 9360 } 9361 9362 /*@C 9363 MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same 9364 parallel layout, `PetscLayout` for rows and columns 9365 9366 Collective 9367 9368 Input Parameter: 9369 . mat - the matrix 9370 9371 Output Parameters: 9372 + right - (optional) vector that the matrix can be multiplied against 9373 - left - (optional) vector that the matrix vector product can be stored in 9374 9375 Level: advanced 9376 9377 Notes: 9378 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()`. 9379 9380 These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed 9381 9382 .seealso: [](chapter_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()` 9383 @*/ 9384 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left) 9385 { 9386 PetscFunctionBegin; 9387 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9388 PetscValidType(mat, 1); 9389 if (mat->ops->getvecs) { 9390 PetscUseTypeMethod(mat, getvecs, right, left); 9391 } else { 9392 PetscInt rbs, cbs; 9393 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 9394 if (right) { 9395 PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup"); 9396 PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), right)); 9397 PetscCall(VecSetSizes(*right, mat->cmap->n, PETSC_DETERMINE)); 9398 PetscCall(VecSetBlockSize(*right, cbs)); 9399 PetscCall(VecSetType(*right, mat->defaultvectype)); 9400 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9401 if (mat->boundtocpu && mat->bindingpropagates) { 9402 PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE)); 9403 PetscCall(VecBindToCPU(*right, PETSC_TRUE)); 9404 } 9405 #endif 9406 PetscCall(PetscLayoutReference(mat->cmap, &(*right)->map)); 9407 } 9408 if (left) { 9409 PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup"); 9410 PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), left)); 9411 PetscCall(VecSetSizes(*left, mat->rmap->n, PETSC_DETERMINE)); 9412 PetscCall(VecSetBlockSize(*left, rbs)); 9413 PetscCall(VecSetType(*left, mat->defaultvectype)); 9414 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9415 if (mat->boundtocpu && mat->bindingpropagates) { 9416 PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE)); 9417 PetscCall(VecBindToCPU(*left, PETSC_TRUE)); 9418 } 9419 #endif 9420 PetscCall(PetscLayoutReference(mat->rmap, &(*left)->map)); 9421 } 9422 } 9423 PetscFunctionReturn(PETSC_SUCCESS); 9424 } 9425 9426 /*@C 9427 MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure 9428 with default values. 9429 9430 Not Collective 9431 9432 Input Parameter: 9433 . info - the `MatFactorInfo` data structure 9434 9435 Level: developer 9436 9437 Notes: 9438 The solvers are generally used through the `KSP` and `PC` objects, for example 9439 `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC` 9440 9441 Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed 9442 9443 Developer Note: 9444 The Fortran interface is not autogenerated as the 9445 interface definition cannot be generated correctly [due to `MatFactorInfo`] 9446 9447 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo` 9448 @*/ 9449 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info) 9450 { 9451 PetscFunctionBegin; 9452 PetscCall(PetscMemzero(info, sizeof(MatFactorInfo))); 9453 PetscFunctionReturn(PETSC_SUCCESS); 9454 } 9455 9456 /*@ 9457 MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed 9458 9459 Collective 9460 9461 Input Parameters: 9462 + mat - the factored matrix 9463 - is - the index set defining the Schur indices (0-based) 9464 9465 Level: advanced 9466 9467 Notes: 9468 Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system. 9469 9470 You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call. 9471 9472 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9473 9474 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`, 9475 `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9476 @*/ 9477 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is) 9478 { 9479 PetscErrorCode (*f)(Mat, IS); 9480 9481 PetscFunctionBegin; 9482 PetscValidType(mat, 1); 9483 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9484 PetscValidType(is, 2); 9485 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 9486 PetscCheckSameComm(mat, 1, is, 2); 9487 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 9488 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f)); 9489 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO"); 9490 PetscCall(MatDestroy(&mat->schur)); 9491 PetscCall((*f)(mat, is)); 9492 PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created"); 9493 PetscFunctionReturn(PETSC_SUCCESS); 9494 } 9495 9496 /*@ 9497 MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step 9498 9499 Logically Collective 9500 9501 Input Parameters: 9502 + F - the factored matrix obtained by calling `MatGetFactor()` 9503 . S - location where to return the Schur complement, can be `NULL` 9504 - status - the status of the Schur complement matrix, can be `NULL` 9505 9506 Level: advanced 9507 9508 Notes: 9509 You must call `MatFactorSetSchurIS()` before calling this routine. 9510 9511 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9512 9513 The routine provides a copy of the Schur matrix stored within the solver data structures. 9514 The caller must destroy the object when it is no longer needed. 9515 If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse. 9516 9517 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) 9518 9519 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9520 9521 Developer Note: 9522 The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc 9523 matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix. 9524 9525 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9526 @*/ 9527 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9528 { 9529 PetscFunctionBegin; 9530 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9531 if (S) PetscValidPointer(S, 2); 9532 if (status) PetscValidPointer(status, 3); 9533 if (S) { 9534 PetscErrorCode (*f)(Mat, Mat *); 9535 9536 PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f)); 9537 if (f) { 9538 PetscCall((*f)(F, S)); 9539 } else { 9540 PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S)); 9541 } 9542 } 9543 if (status) *status = F->schur_status; 9544 PetscFunctionReturn(PETSC_SUCCESS); 9545 } 9546 9547 /*@ 9548 MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix 9549 9550 Logically Collective 9551 9552 Input Parameters: 9553 + F - the factored matrix obtained by calling `MatGetFactor()` 9554 . *S - location where to return the Schur complement, can be `NULL` 9555 - status - the status of the Schur complement matrix, can be `NULL` 9556 9557 Level: advanced 9558 9559 Notes: 9560 You must call `MatFactorSetSchurIS()` before calling this routine. 9561 9562 Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS` 9563 9564 The routine returns a the Schur Complement stored within the data structures of the solver. 9565 9566 If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement. 9567 9568 The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed. 9569 9570 Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix 9571 9572 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9573 9574 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9575 @*/ 9576 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9577 { 9578 PetscFunctionBegin; 9579 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9580 if (S) PetscValidPointer(S, 2); 9581 if (status) PetscValidPointer(status, 3); 9582 if (S) *S = F->schur; 9583 if (status) *status = F->schur_status; 9584 PetscFunctionReturn(PETSC_SUCCESS); 9585 } 9586 9587 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F) 9588 { 9589 Mat S = F->schur; 9590 9591 PetscFunctionBegin; 9592 switch (F->schur_status) { 9593 case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through 9594 case MAT_FACTOR_SCHUR_INVERTED: 9595 if (S) { 9596 S->ops->solve = NULL; 9597 S->ops->matsolve = NULL; 9598 S->ops->solvetranspose = NULL; 9599 S->ops->matsolvetranspose = NULL; 9600 S->ops->solveadd = NULL; 9601 S->ops->solvetransposeadd = NULL; 9602 S->factortype = MAT_FACTOR_NONE; 9603 PetscCall(PetscFree(S->solvertype)); 9604 } 9605 case MAT_FACTOR_SCHUR_FACTORED: // fall-through 9606 break; 9607 default: 9608 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9609 } 9610 PetscFunctionReturn(PETSC_SUCCESS); 9611 } 9612 9613 /*@ 9614 MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()` 9615 9616 Logically Collective 9617 9618 Input Parameters: 9619 + F - the factored matrix obtained by calling `MatGetFactor()` 9620 . *S - location where the Schur complement is stored 9621 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`) 9622 9623 Level: advanced 9624 9625 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9626 @*/ 9627 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status) 9628 { 9629 PetscFunctionBegin; 9630 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9631 if (S) { 9632 PetscValidHeaderSpecific(*S, MAT_CLASSID, 2); 9633 *S = NULL; 9634 } 9635 F->schur_status = status; 9636 PetscCall(MatFactorUpdateSchurStatus_Private(F)); 9637 PetscFunctionReturn(PETSC_SUCCESS); 9638 } 9639 9640 /*@ 9641 MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step 9642 9643 Logically Collective 9644 9645 Input Parameters: 9646 + F - the factored matrix obtained by calling `MatGetFactor()` 9647 . rhs - location where the right hand side of the Schur complement system is stored 9648 - sol - location where the solution of the Schur complement system has to be returned 9649 9650 Level: advanced 9651 9652 Notes: 9653 The sizes of the vectors should match the size of the Schur complement 9654 9655 Must be called after `MatFactorSetSchurIS()` 9656 9657 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()` 9658 @*/ 9659 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol) 9660 { 9661 PetscFunctionBegin; 9662 PetscValidType(F, 1); 9663 PetscValidType(rhs, 2); 9664 PetscValidType(sol, 3); 9665 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9666 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9667 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9668 PetscCheckSameComm(F, 1, rhs, 2); 9669 PetscCheckSameComm(F, 1, sol, 3); 9670 PetscCall(MatFactorFactorizeSchurComplement(F)); 9671 switch (F->schur_status) { 9672 case MAT_FACTOR_SCHUR_FACTORED: 9673 PetscCall(MatSolveTranspose(F->schur, rhs, sol)); 9674 break; 9675 case MAT_FACTOR_SCHUR_INVERTED: 9676 PetscCall(MatMultTranspose(F->schur, rhs, sol)); 9677 break; 9678 default: 9679 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9680 } 9681 PetscFunctionReturn(PETSC_SUCCESS); 9682 } 9683 9684 /*@ 9685 MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step 9686 9687 Logically Collective 9688 9689 Input Parameters: 9690 + F - the factored matrix obtained by calling `MatGetFactor()` 9691 . rhs - location where the right hand side of the Schur complement system is stored 9692 - sol - location where the solution of the Schur complement system has to be returned 9693 9694 Level: advanced 9695 9696 Notes: 9697 The sizes of the vectors should match the size of the Schur complement 9698 9699 Must be called after `MatFactorSetSchurIS()` 9700 9701 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()` 9702 @*/ 9703 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol) 9704 { 9705 PetscFunctionBegin; 9706 PetscValidType(F, 1); 9707 PetscValidType(rhs, 2); 9708 PetscValidType(sol, 3); 9709 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9710 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9711 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9712 PetscCheckSameComm(F, 1, rhs, 2); 9713 PetscCheckSameComm(F, 1, sol, 3); 9714 PetscCall(MatFactorFactorizeSchurComplement(F)); 9715 switch (F->schur_status) { 9716 case MAT_FACTOR_SCHUR_FACTORED: 9717 PetscCall(MatSolve(F->schur, rhs, sol)); 9718 break; 9719 case MAT_FACTOR_SCHUR_INVERTED: 9720 PetscCall(MatMult(F->schur, rhs, sol)); 9721 break; 9722 default: 9723 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9724 } 9725 PetscFunctionReturn(PETSC_SUCCESS); 9726 } 9727 9728 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat); 9729 #if PetscDefined(HAVE_CUDA) 9730 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat); 9731 #endif 9732 9733 /* Schur status updated in the interface */ 9734 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F) 9735 { 9736 Mat S = F->schur; 9737 9738 PetscFunctionBegin; 9739 if (S) { 9740 PetscMPIInt size; 9741 PetscBool isdense, isdensecuda; 9742 9743 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size)); 9744 PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented"); 9745 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense)); 9746 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda)); 9747 PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name); 9748 PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0)); 9749 if (isdense) { 9750 PetscCall(MatSeqDenseInvertFactors_Private(S)); 9751 } else if (isdensecuda) { 9752 #if defined(PETSC_HAVE_CUDA) 9753 PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S)); 9754 #endif 9755 } 9756 // HIP?????????????? 9757 PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0)); 9758 } 9759 PetscFunctionReturn(PETSC_SUCCESS); 9760 } 9761 9762 /*@ 9763 MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step 9764 9765 Logically Collective 9766 9767 Input Parameter: 9768 . F - the factored matrix obtained by calling `MatGetFactor()` 9769 9770 Level: advanced 9771 9772 Notes: 9773 Must be called after `MatFactorSetSchurIS()`. 9774 9775 Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it. 9776 9777 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()` 9778 @*/ 9779 PetscErrorCode MatFactorInvertSchurComplement(Mat F) 9780 { 9781 PetscFunctionBegin; 9782 PetscValidType(F, 1); 9783 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9784 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS); 9785 PetscCall(MatFactorFactorizeSchurComplement(F)); 9786 PetscCall(MatFactorInvertSchurComplement_Private(F)); 9787 F->schur_status = MAT_FACTOR_SCHUR_INVERTED; 9788 PetscFunctionReturn(PETSC_SUCCESS); 9789 } 9790 9791 /*@ 9792 MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step 9793 9794 Logically Collective 9795 9796 Input Parameter: 9797 . F - the factored matrix obtained by calling `MatGetFactor()` 9798 9799 Level: advanced 9800 9801 Note: 9802 Must be called after `MatFactorSetSchurIS()` 9803 9804 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()` 9805 @*/ 9806 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F) 9807 { 9808 MatFactorInfo info; 9809 9810 PetscFunctionBegin; 9811 PetscValidType(F, 1); 9812 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9813 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS); 9814 PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0)); 9815 PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo))); 9816 if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */ 9817 PetscCall(MatCholeskyFactor(F->schur, NULL, &info)); 9818 } else { 9819 PetscCall(MatLUFactor(F->schur, NULL, NULL, &info)); 9820 } 9821 PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0)); 9822 F->schur_status = MAT_FACTOR_SCHUR_FACTORED; 9823 PetscFunctionReturn(PETSC_SUCCESS); 9824 } 9825 9826 /*@ 9827 MatPtAP - Creates the matrix product C = P^T * A * P 9828 9829 Neighbor-wise Collective 9830 9831 Input Parameters: 9832 + A - the matrix 9833 . P - the projection matrix 9834 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9835 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate 9836 if the result is a dense matrix this is irrelevant 9837 9838 Output Parameter: 9839 . C - the product matrix 9840 9841 Level: intermediate 9842 9843 Notes: 9844 C will be created and must be destroyed by the user with `MatDestroy()`. 9845 9846 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9847 9848 Developer Note: 9849 For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`. 9850 9851 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()` 9852 @*/ 9853 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C) 9854 { 9855 PetscFunctionBegin; 9856 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 9857 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9858 9859 if (scall == MAT_INITIAL_MATRIX) { 9860 PetscCall(MatProductCreate(A, P, NULL, C)); 9861 PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP)); 9862 PetscCall(MatProductSetAlgorithm(*C, "default")); 9863 PetscCall(MatProductSetFill(*C, fill)); 9864 9865 (*C)->product->api_user = PETSC_TRUE; 9866 PetscCall(MatProductSetFromOptions(*C)); 9867 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); 9868 PetscCall(MatProductSymbolic(*C)); 9869 } else { /* scall == MAT_REUSE_MATRIX */ 9870 PetscCall(MatProductReplaceMats(A, P, NULL, *C)); 9871 } 9872 9873 PetscCall(MatProductNumeric(*C)); 9874 (*C)->symmetric = A->symmetric; 9875 (*C)->spd = A->spd; 9876 PetscFunctionReturn(PETSC_SUCCESS); 9877 } 9878 9879 /*@ 9880 MatRARt - Creates the matrix product C = R * A * R^T 9881 9882 Neighbor-wise Collective 9883 9884 Input Parameters: 9885 + A - the matrix 9886 . R - the projection matrix 9887 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9888 - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate 9889 if the result is a dense matrix this is irrelevant 9890 9891 Output Parameter: 9892 . C - the product matrix 9893 9894 Level: intermediate 9895 9896 Notes: 9897 C will be created and must be destroyed by the user with `MatDestroy()`. 9898 9899 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9900 9901 This routine is currently only implemented for pairs of `MATAIJ` matrices and classes 9902 which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes, 9903 parallel MatRARt is implemented via explicit transpose of R, which could be very expensive. 9904 We recommend using MatPtAP(). 9905 9906 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()` 9907 @*/ 9908 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C) 9909 { 9910 PetscFunctionBegin; 9911 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 9912 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9913 9914 if (scall == MAT_INITIAL_MATRIX) { 9915 PetscCall(MatProductCreate(A, R, NULL, C)); 9916 PetscCall(MatProductSetType(*C, MATPRODUCT_RARt)); 9917 PetscCall(MatProductSetAlgorithm(*C, "default")); 9918 PetscCall(MatProductSetFill(*C, fill)); 9919 9920 (*C)->product->api_user = PETSC_TRUE; 9921 PetscCall(MatProductSetFromOptions(*C)); 9922 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); 9923 PetscCall(MatProductSymbolic(*C)); 9924 } else { /* scall == MAT_REUSE_MATRIX */ 9925 PetscCall(MatProductReplaceMats(A, R, NULL, *C)); 9926 } 9927 9928 PetscCall(MatProductNumeric(*C)); 9929 if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 9930 PetscFunctionReturn(PETSC_SUCCESS); 9931 } 9932 9933 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C) 9934 { 9935 PetscFunctionBegin; 9936 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9937 9938 if (scall == MAT_INITIAL_MATRIX) { 9939 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype])); 9940 PetscCall(MatProductCreate(A, B, NULL, C)); 9941 PetscCall(MatProductSetType(*C, ptype)); 9942 PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT)); 9943 PetscCall(MatProductSetFill(*C, fill)); 9944 9945 (*C)->product->api_user = PETSC_TRUE; 9946 PetscCall(MatProductSetFromOptions(*C)); 9947 PetscCall(MatProductSymbolic(*C)); 9948 } else { /* scall == MAT_REUSE_MATRIX */ 9949 Mat_Product *product = (*C)->product; 9950 PetscBool isdense; 9951 9952 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, "")); 9953 if (isdense && product && product->type != ptype) { 9954 PetscCall(MatProductClear(*C)); 9955 product = NULL; 9956 } 9957 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype])); 9958 if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */ 9959 PetscCheck(isdense, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first"); 9960 PetscCall(MatProductCreate_Private(A, B, NULL, *C)); 9961 product = (*C)->product; 9962 product->fill = fill; 9963 product->api_user = PETSC_TRUE; 9964 product->clear = PETSC_TRUE; 9965 9966 PetscCall(MatProductSetType(*C, ptype)); 9967 PetscCall(MatProductSetFromOptions(*C)); 9968 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); 9969 PetscCall(MatProductSymbolic(*C)); 9970 } else { /* user may change input matrices A or B when REUSE */ 9971 PetscCall(MatProductReplaceMats(A, B, NULL, *C)); 9972 } 9973 } 9974 PetscCall(MatProductNumeric(*C)); 9975 PetscFunctionReturn(PETSC_SUCCESS); 9976 } 9977 9978 /*@ 9979 MatMatMult - Performs matrix-matrix multiplication C=A*B. 9980 9981 Neighbor-wise Collective 9982 9983 Input Parameters: 9984 + A - the left matrix 9985 . B - the right matrix 9986 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9987 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate 9988 if the result is a dense matrix this is irrelevant 9989 9990 Output Parameter: 9991 . C - the product matrix 9992 9993 Notes: 9994 Unless scall is `MAT_REUSE_MATRIX` C will be created. 9995 9996 `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 9997 call to this function with `MAT_INITIAL_MATRIX`. 9998 9999 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed. 10000 10001 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`, 10002 rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse. 10003 10004 Example of Usage: 10005 .vb 10006 MatProductCreate(A,B,NULL,&C); 10007 MatProductSetType(C,MATPRODUCT_AB); 10008 MatProductSymbolic(C); 10009 MatProductNumeric(C); // compute C=A * B 10010 MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1 10011 MatProductNumeric(C); 10012 MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1 10013 MatProductNumeric(C); 10014 .ve 10015 10016 Level: intermediate 10017 10018 .seealso: [](chapter_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()` 10019 @*/ 10020 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10021 { 10022 PetscFunctionBegin; 10023 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C)); 10024 PetscFunctionReturn(PETSC_SUCCESS); 10025 } 10026 10027 /*@ 10028 MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T. 10029 10030 Neighbor-wise Collective 10031 10032 Input Parameters: 10033 + A - the left matrix 10034 . B - the right matrix 10035 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10036 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 10037 10038 Output Parameter: 10039 . C - the product matrix 10040 10041 Level: intermediate 10042 10043 Notes: 10044 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10045 10046 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call 10047 10048 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10049 actually needed. 10050 10051 This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class, 10052 and for pairs of `MATMPIDENSE` matrices. 10053 10054 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt` 10055 10056 Options Database Keys: 10057 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the 10058 first redundantly copies the transposed B matrix on each process and requiers O(log P) communication complexity; 10059 the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity. 10060 10061 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductCreate()`, `MatProductAlgorithm`, `MatProductType`, `MATPRODUCT_ABt` 10062 @*/ 10063 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10064 { 10065 PetscFunctionBegin; 10066 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C)); 10067 if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10068 PetscFunctionReturn(PETSC_SUCCESS); 10069 } 10070 10071 /*@ 10072 MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B. 10073 10074 Neighbor-wise Collective 10075 10076 Input Parameters: 10077 + A - the left matrix 10078 . B - the right matrix 10079 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10080 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 10081 10082 Output Parameter: 10083 . C - the product matrix 10084 10085 Level: intermediate 10086 10087 Notes: 10088 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10089 10090 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call. 10091 10092 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB` 10093 10094 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10095 actually needed. 10096 10097 This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes 10098 which inherit from `MATSEQAIJ`. C will be of the same type as the input matrices. 10099 10100 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()` 10101 @*/ 10102 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10103 { 10104 PetscFunctionBegin; 10105 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C)); 10106 PetscFunctionReturn(PETSC_SUCCESS); 10107 } 10108 10109 /*@ 10110 MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C. 10111 10112 Neighbor-wise Collective 10113 10114 Input Parameters: 10115 + A - the left matrix 10116 . B - the middle matrix 10117 . C - the right matrix 10118 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10119 - 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 10120 if the result is a dense matrix this is irrelevant 10121 10122 Output Parameter: 10123 . D - the product matrix 10124 10125 Level: intermediate 10126 10127 Notes: 10128 Unless scall is `MAT_REUSE_MATRIX` D will be created. 10129 10130 `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call 10131 10132 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC` 10133 10134 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10135 actually needed. 10136 10137 If you have many matrices with the same non-zero structure to multiply, you 10138 should use `MAT_REUSE_MATRIX` in all calls but the first 10139 10140 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()` 10141 @*/ 10142 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D) 10143 { 10144 PetscFunctionBegin; 10145 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6); 10146 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10147 10148 if (scall == MAT_INITIAL_MATRIX) { 10149 PetscCall(MatProductCreate(A, B, C, D)); 10150 PetscCall(MatProductSetType(*D, MATPRODUCT_ABC)); 10151 PetscCall(MatProductSetAlgorithm(*D, "default")); 10152 PetscCall(MatProductSetFill(*D, fill)); 10153 10154 (*D)->product->api_user = PETSC_TRUE; 10155 PetscCall(MatProductSetFromOptions(*D)); 10156 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, 10157 ((PetscObject)C)->type_name); 10158 PetscCall(MatProductSymbolic(*D)); 10159 } else { /* user may change input matrices when REUSE */ 10160 PetscCall(MatProductReplaceMats(A, B, C, *D)); 10161 } 10162 PetscCall(MatProductNumeric(*D)); 10163 PetscFunctionReturn(PETSC_SUCCESS); 10164 } 10165 10166 /*@ 10167 MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators. 10168 10169 Collective 10170 10171 Input Parameters: 10172 + mat - the matrix 10173 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices) 10174 . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used) 10175 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10176 10177 Output Parameter: 10178 . matredundant - redundant matrix 10179 10180 Level: advanced 10181 10182 Notes: 10183 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 10184 original matrix has not changed from that last call to MatCreateRedundantMatrix(). 10185 10186 This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before 10187 calling it. 10188 10189 `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be. 10190 10191 .seealso: [](chapter_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubComm` 10192 @*/ 10193 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant) 10194 { 10195 MPI_Comm comm; 10196 PetscMPIInt size; 10197 PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs; 10198 Mat_Redundant *redund = NULL; 10199 PetscSubcomm psubcomm = NULL; 10200 MPI_Comm subcomm_in = subcomm; 10201 Mat *matseq; 10202 IS isrow, iscol; 10203 PetscBool newsubcomm = PETSC_FALSE; 10204 10205 PetscFunctionBegin; 10206 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10207 if (nsubcomm && reuse == MAT_REUSE_MATRIX) { 10208 PetscValidPointer(*matredundant, 5); 10209 PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5); 10210 } 10211 10212 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10213 if (size == 1 || nsubcomm == 1) { 10214 if (reuse == MAT_INITIAL_MATRIX) { 10215 PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant)); 10216 } else { 10217 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"); 10218 PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN)); 10219 } 10220 PetscFunctionReturn(PETSC_SUCCESS); 10221 } 10222 10223 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10224 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10225 MatCheckPreallocated(mat, 1); 10226 10227 PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0)); 10228 if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */ 10229 /* create psubcomm, then get subcomm */ 10230 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10231 PetscCallMPI(MPI_Comm_size(comm, &size)); 10232 PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size); 10233 10234 PetscCall(PetscSubcommCreate(comm, &psubcomm)); 10235 PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm)); 10236 PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS)); 10237 PetscCall(PetscSubcommSetFromOptions(psubcomm)); 10238 PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL)); 10239 newsubcomm = PETSC_TRUE; 10240 PetscCall(PetscSubcommDestroy(&psubcomm)); 10241 } 10242 10243 /* get isrow, iscol and a local sequential matrix matseq[0] */ 10244 if (reuse == MAT_INITIAL_MATRIX) { 10245 mloc_sub = PETSC_DECIDE; 10246 nloc_sub = PETSC_DECIDE; 10247 if (bs < 1) { 10248 PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M)); 10249 PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N)); 10250 } else { 10251 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M)); 10252 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N)); 10253 } 10254 PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm)); 10255 rstart = rend - mloc_sub; 10256 PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow)); 10257 PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol)); 10258 } else { /* reuse == MAT_REUSE_MATRIX */ 10259 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"); 10260 /* retrieve subcomm */ 10261 PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm)); 10262 redund = (*matredundant)->redundant; 10263 isrow = redund->isrow; 10264 iscol = redund->iscol; 10265 matseq = redund->matseq; 10266 } 10267 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq)); 10268 10269 /* get matredundant over subcomm */ 10270 if (reuse == MAT_INITIAL_MATRIX) { 10271 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant)); 10272 10273 /* create a supporting struct and attach it to C for reuse */ 10274 PetscCall(PetscNew(&redund)); 10275 (*matredundant)->redundant = redund; 10276 redund->isrow = isrow; 10277 redund->iscol = iscol; 10278 redund->matseq = matseq; 10279 if (newsubcomm) { 10280 redund->subcomm = subcomm; 10281 } else { 10282 redund->subcomm = MPI_COMM_NULL; 10283 } 10284 } else { 10285 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant)); 10286 } 10287 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 10288 if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) { 10289 PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE)); 10290 PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE)); 10291 } 10292 #endif 10293 PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0)); 10294 PetscFunctionReturn(PETSC_SUCCESS); 10295 } 10296 10297 /*@C 10298 MatGetMultiProcBlock - Create multiple 'parallel submatrices' from 10299 a given `Mat`. Each submatrix can span multiple procs. 10300 10301 Collective 10302 10303 Input Parameters: 10304 + mat - the matrix 10305 . subcomm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))` 10306 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10307 10308 Output Parameter: 10309 . subMat - parallel sub-matrices each spanning a given `subcomm` 10310 10311 Level: advanced 10312 10313 Notes: 10314 The submatrix partition across processors is dictated by `subComm` a 10315 communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm` 10316 is not restricted to be grouped with consecutive original ranks. 10317 10318 Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices 10319 map directly to the layout of the original matrix [wrt the local 10320 row,col partitioning]. So the original 'DiagonalMat' naturally maps 10321 into the 'DiagonalMat' of the `subMat`, hence it is used directly from 10322 the `subMat`. However the offDiagMat looses some columns - and this is 10323 reconstructed with `MatSetValues()` 10324 10325 This is used by `PCBJACOBI` when a single block spans multiple MPI ranks 10326 10327 .seealso: [](chapter_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI` 10328 @*/ 10329 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) 10330 { 10331 PetscMPIInt commsize, subCommSize; 10332 10333 PetscFunctionBegin; 10334 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize)); 10335 PetscCallMPI(MPI_Comm_size(subComm, &subCommSize)); 10336 PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize); 10337 10338 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"); 10339 PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10340 PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat); 10341 PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10342 PetscFunctionReturn(PETSC_SUCCESS); 10343 } 10344 10345 /*@ 10346 MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering 10347 10348 Not Collective 10349 10350 Input Parameters: 10351 + mat - matrix to extract local submatrix from 10352 . isrow - local row indices for submatrix 10353 - iscol - local column indices for submatrix 10354 10355 Output Parameter: 10356 . submat - the submatrix 10357 10358 Level: intermediate 10359 10360 Notes: 10361 `submat` should be disposed of with `MatRestoreLocalSubMatrix()`. 10362 10363 Depending on the format of `mat`, the returned submat may not implement `MatMult()`. Its communicator may be 10364 the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of `mat`'s. 10365 10366 `submat` always implements `MatSetValuesLocal()`. If `isrow` and `iscol` have the same block size, then 10367 `MatSetValuesBlockedLocal()` will also be implemented. 10368 10369 `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`. 10370 Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided. 10371 10372 .seealso: [](chapter_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()` 10373 @*/ 10374 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10375 { 10376 PetscFunctionBegin; 10377 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10378 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10379 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10380 PetscCheckSameComm(isrow, 2, iscol, 3); 10381 PetscValidPointer(submat, 4); 10382 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call"); 10383 10384 if (mat->ops->getlocalsubmatrix) { 10385 PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat); 10386 } else { 10387 PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat)); 10388 } 10389 PetscFunctionReturn(PETSC_SUCCESS); 10390 } 10391 10392 /*@ 10393 MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()` 10394 10395 Not Collective 10396 10397 Input Parameters: 10398 + mat - matrix to extract local submatrix from 10399 . isrow - local row indices for submatrix 10400 . iscol - local column indices for submatrix 10401 - submat - the submatrix 10402 10403 Level: intermediate 10404 10405 .seealso: [](chapter_matrices), `Mat`, `MatGetLocalSubMatrix()` 10406 @*/ 10407 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10408 { 10409 PetscFunctionBegin; 10410 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10411 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10412 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10413 PetscCheckSameComm(isrow, 2, iscol, 3); 10414 PetscValidPointer(submat, 4); 10415 if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4); 10416 10417 if (mat->ops->restorelocalsubmatrix) { 10418 PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat); 10419 } else { 10420 PetscCall(MatDestroy(submat)); 10421 } 10422 *submat = NULL; 10423 PetscFunctionReturn(PETSC_SUCCESS); 10424 } 10425 10426 /*@ 10427 MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix 10428 10429 Collective 10430 10431 Input Parameter: 10432 . mat - the matrix 10433 10434 Output Parameter: 10435 . is - if any rows have zero diagonals this contains the list of them 10436 10437 Level: developer 10438 10439 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10440 @*/ 10441 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is) 10442 { 10443 PetscFunctionBegin; 10444 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10445 PetscValidType(mat, 1); 10446 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10447 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10448 10449 if (!mat->ops->findzerodiagonals) { 10450 Vec diag; 10451 const PetscScalar *a; 10452 PetscInt *rows; 10453 PetscInt rStart, rEnd, r, nrow = 0; 10454 10455 PetscCall(MatCreateVecs(mat, &diag, NULL)); 10456 PetscCall(MatGetDiagonal(mat, diag)); 10457 PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd)); 10458 PetscCall(VecGetArrayRead(diag, &a)); 10459 for (r = 0; r < rEnd - rStart; ++r) 10460 if (a[r] == 0.0) ++nrow; 10461 PetscCall(PetscMalloc1(nrow, &rows)); 10462 nrow = 0; 10463 for (r = 0; r < rEnd - rStart; ++r) 10464 if (a[r] == 0.0) rows[nrow++] = r + rStart; 10465 PetscCall(VecRestoreArrayRead(diag, &a)); 10466 PetscCall(VecDestroy(&diag)); 10467 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is)); 10468 } else { 10469 PetscUseTypeMethod(mat, findzerodiagonals, is); 10470 } 10471 PetscFunctionReturn(PETSC_SUCCESS); 10472 } 10473 10474 /*@ 10475 MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size) 10476 10477 Collective 10478 10479 Input Parameter: 10480 . mat - the matrix 10481 10482 Output Parameter: 10483 . is - contains the list of rows with off block diagonal entries 10484 10485 Level: developer 10486 10487 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10488 @*/ 10489 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is) 10490 { 10491 PetscFunctionBegin; 10492 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10493 PetscValidType(mat, 1); 10494 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10495 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10496 10497 PetscUseTypeMethod(mat, findoffblockdiagonalentries, is); 10498 PetscFunctionReturn(PETSC_SUCCESS); 10499 } 10500 10501 /*@C 10502 MatInvertBlockDiagonal - Inverts the block diagonal entries. 10503 10504 Collective; No Fortran Support 10505 10506 Input Parameter: 10507 . mat - the matrix 10508 10509 Output Parameter: 10510 . values - the block inverses in column major order (FORTRAN-like) 10511 10512 Level: advanced 10513 10514 Notes: 10515 The size of the blocks is determined by the block size of the matrix. 10516 10517 The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case 10518 10519 The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size 10520 10521 .seealso: [](chapter_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()` 10522 @*/ 10523 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values) 10524 { 10525 PetscFunctionBegin; 10526 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10527 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10528 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10529 PetscUseTypeMethod(mat, invertblockdiagonal, values); 10530 PetscFunctionReturn(PETSC_SUCCESS); 10531 } 10532 10533 /*@C 10534 MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries. 10535 10536 Collective; No Fortran Support 10537 10538 Input Parameters: 10539 + mat - the matrix 10540 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()` 10541 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()` 10542 10543 Output Parameter: 10544 . values - the block inverses in column major order (FORTRAN-like) 10545 10546 Level: advanced 10547 10548 Notes: 10549 Use `MatInvertBlockDiagonal()` if all blocks have the same size 10550 10551 The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case 10552 10553 .seealso: [](chapter_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()` 10554 @*/ 10555 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values) 10556 { 10557 PetscFunctionBegin; 10558 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10559 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10560 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10561 PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values); 10562 PetscFunctionReturn(PETSC_SUCCESS); 10563 } 10564 10565 /*@ 10566 MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A 10567 10568 Collective 10569 10570 Input Parameters: 10571 + A - the matrix 10572 - C - matrix with inverted block diagonal of `A`. This matrix should be created and may have its type set. 10573 10574 Level: advanced 10575 10576 Note: 10577 The blocksize of the matrix is used to determine the blocks on the diagonal of `C` 10578 10579 .seealso: [](chapter_matrices), `Mat`, `MatInvertBlockDiagonal()` 10580 @*/ 10581 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C) 10582 { 10583 const PetscScalar *vals; 10584 PetscInt *dnnz; 10585 PetscInt m, rstart, rend, bs, i, j; 10586 10587 PetscFunctionBegin; 10588 PetscCall(MatInvertBlockDiagonal(A, &vals)); 10589 PetscCall(MatGetBlockSize(A, &bs)); 10590 PetscCall(MatGetLocalSize(A, &m, NULL)); 10591 PetscCall(MatSetLayouts(C, A->rmap, A->cmap)); 10592 PetscCall(PetscMalloc1(m / bs, &dnnz)); 10593 for (j = 0; j < m / bs; j++) dnnz[j] = 1; 10594 PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL)); 10595 PetscCall(PetscFree(dnnz)); 10596 PetscCall(MatGetOwnershipRange(C, &rstart, &rend)); 10597 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE)); 10598 for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES)); 10599 PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 10600 PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 10601 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE)); 10602 PetscFunctionReturn(PETSC_SUCCESS); 10603 } 10604 10605 /*@C 10606 MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created 10607 via `MatTransposeColoringCreate()`. 10608 10609 Collective 10610 10611 Input Parameter: 10612 . c - coloring context 10613 10614 Level: intermediate 10615 10616 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringCreate()` 10617 @*/ 10618 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c) 10619 { 10620 MatTransposeColoring matcolor = *c; 10621 10622 PetscFunctionBegin; 10623 if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS); 10624 if (--((PetscObject)matcolor)->refct > 0) { 10625 matcolor = NULL; 10626 PetscFunctionReturn(PETSC_SUCCESS); 10627 } 10628 10629 PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow)); 10630 PetscCall(PetscFree(matcolor->rows)); 10631 PetscCall(PetscFree(matcolor->den2sp)); 10632 PetscCall(PetscFree(matcolor->colorforcol)); 10633 PetscCall(PetscFree(matcolor->columns)); 10634 if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart)); 10635 PetscCall(PetscHeaderDestroy(c)); 10636 PetscFunctionReturn(PETSC_SUCCESS); 10637 } 10638 10639 /*@C 10640 MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which 10641 a `MatTransposeColoring` context has been created, computes a dense B^T by applying 10642 `MatTransposeColoring` to sparse B. 10643 10644 Collective 10645 10646 Input Parameters: 10647 + coloring - coloring context created with `MatTransposeColoringCreate()` 10648 - B - sparse matrix 10649 10650 Output Parameter: 10651 . Btdense - dense matrix B^T 10652 10653 Level: developer 10654 10655 Note: 10656 These are used internally for some implementations of `MatRARt()` 10657 10658 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()` 10659 @*/ 10660 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense) 10661 { 10662 PetscFunctionBegin; 10663 PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10664 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 10665 PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3); 10666 10667 PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense)); 10668 PetscFunctionReturn(PETSC_SUCCESS); 10669 } 10670 10671 /*@C 10672 MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which 10673 a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense 10674 in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix 10675 `Csp` from `Cden`. 10676 10677 Collective 10678 10679 Input Parameters: 10680 + matcoloring - coloring context created with `MatTransposeColoringCreate()` 10681 - Cden - matrix product of a sparse matrix and a dense matrix Btdense 10682 10683 Output Parameter: 10684 . Csp - sparse matrix 10685 10686 Level: developer 10687 10688 Note: 10689 These are used internally for some implementations of `MatRARt()` 10690 10691 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()` 10692 @*/ 10693 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp) 10694 { 10695 PetscFunctionBegin; 10696 PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10697 PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2); 10698 PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3); 10699 10700 PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp)); 10701 PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY)); 10702 PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY)); 10703 PetscFunctionReturn(PETSC_SUCCESS); 10704 } 10705 10706 /*@C 10707 MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T. 10708 10709 Collective 10710 10711 Input Parameters: 10712 + mat - the matrix product C 10713 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()` 10714 10715 Output Parameter: 10716 . color - the new coloring context 10717 10718 Level: intermediate 10719 10720 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`, 10721 `MatTransColoringApplyDenToSp()` 10722 @*/ 10723 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color) 10724 { 10725 MatTransposeColoring c; 10726 MPI_Comm comm; 10727 10728 PetscFunctionBegin; 10729 PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10730 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10731 PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL)); 10732 10733 c->ctype = iscoloring->ctype; 10734 PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c); 10735 10736 *color = c; 10737 PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10738 PetscFunctionReturn(PETSC_SUCCESS); 10739 } 10740 10741 /*@ 10742 MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the 10743 matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the 10744 same, otherwise it will be larger 10745 10746 Not Collective 10747 10748 Input Parameter: 10749 . A - the matrix 10750 10751 Output Parameter: 10752 . state - the current state 10753 10754 Level: intermediate 10755 10756 Notes: 10757 You can only compare states from two different calls to the SAME matrix, you cannot compare calls between 10758 different matrices 10759 10760 Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix 10761 10762 Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers. 10763 10764 .seealso: [](chapter_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()` 10765 @*/ 10766 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state) 10767 { 10768 PetscFunctionBegin; 10769 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10770 *state = mat->nonzerostate; 10771 PetscFunctionReturn(PETSC_SUCCESS); 10772 } 10773 10774 /*@ 10775 MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential 10776 matrices from each processor 10777 10778 Collective 10779 10780 Input Parameters: 10781 + comm - the communicators the parallel matrix will live on 10782 . seqmat - the input sequential matrices 10783 . n - number of local columns (or `PETSC_DECIDE`) 10784 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10785 10786 Output Parameter: 10787 . mpimat - the parallel matrix generated 10788 10789 Level: developer 10790 10791 Note: 10792 The number of columns of the matrix in EACH processor MUST be the same. 10793 10794 .seealso: [](chapter_matrices), `Mat` 10795 @*/ 10796 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat) 10797 { 10798 PetscMPIInt size; 10799 10800 PetscFunctionBegin; 10801 PetscCallMPI(MPI_Comm_size(comm, &size)); 10802 if (size == 1) { 10803 if (reuse == MAT_INITIAL_MATRIX) { 10804 PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat)); 10805 } else { 10806 PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN)); 10807 } 10808 PetscFunctionReturn(PETSC_SUCCESS); 10809 } 10810 10811 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"); 10812 10813 PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0)); 10814 PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat)); 10815 PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0)); 10816 PetscFunctionReturn(PETSC_SUCCESS); 10817 } 10818 10819 /*@ 10820 MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent ranks' ownership ranges. 10821 10822 Collective 10823 10824 Input Parameters: 10825 + A - the matrix to create subdomains from 10826 - N - requested number of subdomains 10827 10828 Output Parameters: 10829 + n - number of subdomains resulting on this rank 10830 - iss - `IS` list with indices of subdomains on this rank 10831 10832 Level: advanced 10833 10834 Note: 10835 The number of subdomains must be smaller than the communicator size 10836 10837 .seealso: [](chapter_matrices), `Mat`, `IS` 10838 @*/ 10839 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[]) 10840 { 10841 MPI_Comm comm, subcomm; 10842 PetscMPIInt size, rank, color; 10843 PetscInt rstart, rend, k; 10844 10845 PetscFunctionBegin; 10846 PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 10847 PetscCallMPI(MPI_Comm_size(comm, &size)); 10848 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 10849 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); 10850 *n = 1; 10851 k = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */ 10852 color = rank / k; 10853 PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm)); 10854 PetscCall(PetscMalloc1(1, iss)); 10855 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 10856 PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0])); 10857 PetscCallMPI(MPI_Comm_free(&subcomm)); 10858 PetscFunctionReturn(PETSC_SUCCESS); 10859 } 10860 10861 /*@ 10862 MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection. 10863 10864 If the interpolation and restriction operators are the same, uses `MatPtAP()`. 10865 If they are not the same, uses `MatMatMatMult()`. 10866 10867 Once the coarse grid problem is constructed, correct for interpolation operators 10868 that are not of full rank, which can legitimately happen in the case of non-nested 10869 geometric multigrid. 10870 10871 Input Parameters: 10872 + restrct - restriction operator 10873 . dA - fine grid matrix 10874 . interpolate - interpolation operator 10875 . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10876 - fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate 10877 10878 Output Parameter: 10879 . A - the Galerkin coarse matrix 10880 10881 Options Database Key: 10882 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used 10883 10884 Level: developer 10885 10886 .seealso: [](chapter_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()` 10887 @*/ 10888 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A) 10889 { 10890 IS zerorows; 10891 Vec diag; 10892 10893 PetscFunctionBegin; 10894 PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10895 /* Construct the coarse grid matrix */ 10896 if (interpolate == restrct) { 10897 PetscCall(MatPtAP(dA, interpolate, reuse, fill, A)); 10898 } else { 10899 PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A)); 10900 } 10901 10902 /* If the interpolation matrix is not of full rank, A will have zero rows. 10903 This can legitimately happen in the case of non-nested geometric multigrid. 10904 In that event, we set the rows of the matrix to the rows of the identity, 10905 ignoring the equations (as the RHS will also be zero). */ 10906 10907 PetscCall(MatFindZeroRows(*A, &zerorows)); 10908 10909 if (zerorows != NULL) { /* if there are any zero rows */ 10910 PetscCall(MatCreateVecs(*A, &diag, NULL)); 10911 PetscCall(MatGetDiagonal(*A, diag)); 10912 PetscCall(VecISSet(diag, zerorows, 1.0)); 10913 PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES)); 10914 PetscCall(VecDestroy(&diag)); 10915 PetscCall(ISDestroy(&zerorows)); 10916 } 10917 PetscFunctionReturn(PETSC_SUCCESS); 10918 } 10919 10920 /*@C 10921 MatSetOperation - Allows user to set a matrix operation for any matrix type 10922 10923 Logically Collective 10924 10925 Input Parameters: 10926 + mat - the matrix 10927 . op - the name of the operation 10928 - f - the function that provides the operation 10929 10930 Level: developer 10931 10932 Usage: 10933 .vb 10934 extern PetscErrorCode usermult(Mat, Vec, Vec); 10935 10936 PetscCall(MatCreateXXX(comm, ..., &A)); 10937 PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFunction)usermult)); 10938 .ve 10939 10940 Notes: 10941 See the file `include/petscmat.h` for a complete list of matrix 10942 operations, which all have the form MATOP_<OPERATION>, where 10943 <OPERATION> is the name (in all capital letters) of the 10944 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 10945 10946 All user-provided functions (except for `MATOP_DESTROY`) should have the same calling 10947 sequence as the usual matrix interface routines, since they 10948 are intended to be accessed via the usual matrix interface 10949 routines, e.g., 10950 .vb 10951 MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec) 10952 .ve 10953 10954 In particular each function MUST return `PETSC_SUCCESS` on success and 10955 nonzero on failure. 10956 10957 This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type. 10958 10959 .seealso: [](chapter_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()` 10960 @*/ 10961 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void)) 10962 { 10963 PetscFunctionBegin; 10964 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10965 if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view; 10966 (((void (**)(void))mat->ops)[op]) = f; 10967 PetscFunctionReturn(PETSC_SUCCESS); 10968 } 10969 10970 /*@C 10971 MatGetOperation - Gets a matrix operation for any matrix type. 10972 10973 Not Collective 10974 10975 Input Parameters: 10976 + mat - the matrix 10977 - op - the name of the operation 10978 10979 Output Parameter: 10980 . f - the function that provides the operation 10981 10982 Level: developer 10983 10984 Usage: 10985 .vb 10986 PetscErrorCode (*usermult)(Mat, Vec, Vec); 10987 MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult); 10988 .ve 10989 10990 Notes: 10991 See the file include/petscmat.h for a complete list of matrix 10992 operations, which all have the form MATOP_<OPERATION>, where 10993 <OPERATION> is the name (in all capital letters) of the 10994 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 10995 10996 This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type. 10997 10998 .seealso: [](chapter_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()` 10999 @*/ 11000 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void)) 11001 { 11002 PetscFunctionBegin; 11003 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11004 *f = (((void (**)(void))mat->ops)[op]); 11005 PetscFunctionReturn(PETSC_SUCCESS); 11006 } 11007 11008 /*@ 11009 MatHasOperation - Determines whether the given matrix supports the particular operation. 11010 11011 Not Collective 11012 11013 Input Parameters: 11014 + mat - the matrix 11015 - op - the operation, for example, `MATOP_GET_DIAGONAL` 11016 11017 Output Parameter: 11018 . has - either `PETSC_TRUE` or `PETSC_FALSE` 11019 11020 Level: advanced 11021 11022 Note: 11023 See `MatSetOperation()` for additional discussion on naming convention and usage of `op`. 11024 11025 .seealso: [](chapter_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()` 11026 @*/ 11027 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has) 11028 { 11029 PetscFunctionBegin; 11030 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11031 PetscValidBoolPointer(has, 3); 11032 if (mat->ops->hasoperation) { 11033 PetscUseTypeMethod(mat, hasoperation, op, has); 11034 } else { 11035 if (((void **)mat->ops)[op]) *has = PETSC_TRUE; 11036 else { 11037 *has = PETSC_FALSE; 11038 if (op == MATOP_CREATE_SUBMATRIX) { 11039 PetscMPIInt size; 11040 11041 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 11042 if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has)); 11043 } 11044 } 11045 } 11046 PetscFunctionReturn(PETSC_SUCCESS); 11047 } 11048 11049 /*@ 11050 MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent 11051 11052 Collective 11053 11054 Input Parameter: 11055 . mat - the matrix 11056 11057 Output Parameter: 11058 . cong - either `PETSC_TRUE` or `PETSC_FALSE` 11059 11060 Level: beginner 11061 11062 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout` 11063 @*/ 11064 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong) 11065 { 11066 PetscFunctionBegin; 11067 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11068 PetscValidType(mat, 1); 11069 PetscValidBoolPointer(cong, 2); 11070 if (!mat->rmap || !mat->cmap) { 11071 *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE; 11072 PetscFunctionReturn(PETSC_SUCCESS); 11073 } 11074 if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */ 11075 PetscCall(PetscLayoutSetUp(mat->rmap)); 11076 PetscCall(PetscLayoutSetUp(mat->cmap)); 11077 PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong)); 11078 if (*cong) mat->congruentlayouts = 1; 11079 else mat->congruentlayouts = 0; 11080 } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE; 11081 PetscFunctionReturn(PETSC_SUCCESS); 11082 } 11083 11084 PetscErrorCode MatSetInf(Mat A) 11085 { 11086 PetscFunctionBegin; 11087 PetscUseTypeMethod(A, setinf); 11088 PetscFunctionReturn(PETSC_SUCCESS); 11089 } 11090 11091 /*@C 11092 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 11093 and possibly removes small values from the graph structure. 11094 11095 Collective 11096 11097 Input Parameters: 11098 + A - the matrix 11099 . sym - `PETSC_TRUE` indicates that the graph should be symmetrized 11100 . scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry 11101 - filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value 11102 11103 Output Parameter: 11104 . graph - the resulting graph 11105 11106 Level: advanced 11107 11108 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `PCGAMG` 11109 @*/ 11110 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph) 11111 { 11112 PetscFunctionBegin; 11113 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11114 PetscValidType(A, 1); 11115 PetscValidLogicalCollectiveBool(A, scale, 3); 11116 PetscValidPointer(graph, 5); 11117 PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph); 11118 PetscFunctionReturn(PETSC_SUCCESS); 11119 } 11120 11121 /*@ 11122 MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place, 11123 meaning the same memory is used for the matrix, and no new memory is allocated. 11124 11125 Collective 11126 11127 Input Parameter: 11128 . A - the matrix 11129 11130 Level: intermediate 11131 11132 Developer Note: 11133 The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end 11134 of the arrays in the data structure are unneeded. 11135 11136 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatChop()` 11137 @*/ 11138 PetscErrorCode MatEliminateZeros(Mat A) 11139 { 11140 PetscFunctionBegin; 11141 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11142 PetscUseTypeMethod(A, eliminatezeros); 11143 PetscFunctionReturn(PETSC_SUCCESS); 11144 } 11145