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