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