1 /* 2 This is where the abstract matrix operations are defined 3 Portions of this code are under: 4 Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved. 5 */ 6 7 #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/ 8 #include <petsc/private/isimpl.h> 9 #include <petsc/private/vecimpl.h> 10 11 /* Logging support */ 12 PetscClassId MAT_CLASSID; 13 PetscClassId MAT_COLORING_CLASSID; 14 PetscClassId MAT_FDCOLORING_CLASSID; 15 PetscClassId MAT_TRANSPOSECOLORING_CLASSID; 16 17 PetscLogEvent MAT_Mult, MAT_MultAdd, MAT_MultTranspose; 18 PetscLogEvent MAT_MultTransposeAdd, MAT_Solve, MAT_Solves, MAT_SolveAdd, MAT_SolveTranspose, MAT_MatSolve, MAT_MatTrSolve; 19 PetscLogEvent MAT_SolveTransposeAdd, MAT_SOR, MAT_ForwardSolve, MAT_BackwardSolve, MAT_LUFactor, MAT_LUFactorSymbolic; 20 PetscLogEvent MAT_LUFactorNumeric, MAT_CholeskyFactor, MAT_CholeskyFactorSymbolic, MAT_CholeskyFactorNumeric, MAT_ILUFactor; 21 PetscLogEvent MAT_ILUFactorSymbolic, MAT_ICCFactorSymbolic, MAT_Copy, MAT_Convert, MAT_Scale, MAT_AssemblyBegin; 22 PetscLogEvent MAT_QRFactorNumeric, MAT_QRFactorSymbolic, MAT_QRFactor; 23 PetscLogEvent MAT_AssemblyEnd, MAT_SetValues, MAT_GetValues, MAT_GetRow, MAT_GetRowIJ, MAT_CreateSubMats, MAT_GetOrdering, MAT_RedundantMat, MAT_GetSeqNonzeroStructure; 24 PetscLogEvent MAT_IncreaseOverlap, MAT_Partitioning, MAT_PartitioningND, MAT_Coarsen, MAT_ZeroEntries, MAT_Load, MAT_View, MAT_AXPY, MAT_FDColoringCreate; 25 PetscLogEvent MAT_FDColoringSetUp, MAT_FDColoringApply, MAT_Transpose, MAT_FDColoringFunction, MAT_CreateSubMat; 26 PetscLogEvent MAT_TransposeColoringCreate; 27 PetscLogEvent MAT_MatMult, MAT_MatMultSymbolic, MAT_MatMultNumeric; 28 PetscLogEvent MAT_PtAP, MAT_PtAPSymbolic, MAT_PtAPNumeric, MAT_RARt, MAT_RARtSymbolic, MAT_RARtNumeric; 29 PetscLogEvent MAT_MatTransposeMult, MAT_MatTransposeMultSymbolic, MAT_MatTransposeMultNumeric; 30 PetscLogEvent MAT_TransposeMatMult, MAT_TransposeMatMultSymbolic, MAT_TransposeMatMultNumeric; 31 PetscLogEvent MAT_MatMatMult, MAT_MatMatMultSymbolic, MAT_MatMatMultNumeric; 32 PetscLogEvent MAT_MultHermitianTranspose, MAT_MultHermitianTransposeAdd; 33 PetscLogEvent MAT_Getsymtransreduced, MAT_GetBrowsOfAcols; 34 PetscLogEvent MAT_GetBrowsOfAocols, MAT_Getlocalmat, MAT_Getlocalmatcondensed, MAT_Seqstompi, MAT_Seqstompinum, MAT_Seqstompisym; 35 PetscLogEvent MAT_GetMultiProcBlock; 36 PetscLogEvent MAT_CUSPARSECopyToGPU, MAT_CUSPARSECopyFromGPU, MAT_CUSPARSEGenerateTranspose, MAT_CUSPARSESolveAnalysis; 37 PetscLogEvent MAT_HIPSPARSECopyToGPU, MAT_HIPSPARSECopyFromGPU, MAT_HIPSPARSEGenerateTranspose, MAT_HIPSPARSESolveAnalysis; 38 PetscLogEvent MAT_PreallCOO, MAT_SetVCOO; 39 PetscLogEvent MAT_SetValuesBatch; 40 PetscLogEvent MAT_ViennaCLCopyToGPU; 41 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU; 42 PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom; 43 PetscLogEvent MAT_FactorFactS, MAT_FactorInvS; 44 PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights; 45 PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR; 46 47 const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL}; 48 49 /*@ 50 MatSetRandom - Sets all components of a matrix to random numbers. 51 52 Logically Collective 53 54 Input Parameters: 55 + x - the matrix 56 - rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or `NULL` and 57 it will create one internally. 58 59 Example: 60 .vb 61 PetscRandomCreate(PETSC_COMM_WORLD,&rctx); 62 MatSetRandom(x,rctx); 63 PetscRandomDestroy(rctx); 64 .ve 65 66 Level: intermediate 67 68 Notes: 69 For sparse matrices that have been preallocated but not been assembled it randomly selects appropriate locations, 70 71 for sparse matrices that already have locations it fills the locations with random numbers. 72 73 It generates an error if used on sparse matrices that have not been preallocated. 74 75 .seealso: [](ch_matrices), `Mat`, `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomCreate()`, `PetscRandomDestroy()` 76 @*/ 77 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx) 78 { 79 PetscRandom randObj = NULL; 80 81 PetscFunctionBegin; 82 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 83 if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2); 84 PetscValidType(x, 1); 85 MatCheckPreallocated(x, 1); 86 87 if (!rctx) { 88 MPI_Comm comm; 89 PetscCall(PetscObjectGetComm((PetscObject)x, &comm)); 90 PetscCall(PetscRandomCreate(comm, &randObj)); 91 PetscCall(PetscRandomSetType(randObj, x->defaultrandtype)); 92 PetscCall(PetscRandomSetFromOptions(randObj)); 93 rctx = randObj; 94 } 95 PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0)); 96 PetscUseTypeMethod(x, setrandom, rctx); 97 PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0)); 98 99 PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY)); 100 PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY)); 101 PetscCall(PetscRandomDestroy(&randObj)); 102 PetscFunctionReturn(PETSC_SUCCESS); 103 } 104 105 /*@ 106 MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in 107 108 Logically Collective 109 110 Input Parameter: 111 . mat - the factored matrix 112 113 Output Parameters: 114 + pivot - the pivot value computed 115 - row - the row that the zero pivot occurred. This row value must be interpreted carefully due to row reorderings and which processes 116 the share the matrix 117 118 Level: advanced 119 120 Notes: 121 This routine does not work for factorizations done with external packages. 122 123 This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT` 124 125 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 126 127 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, 128 `MAT_FACTOR_NUMERIC_ZEROPIVOT` 129 @*/ 130 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row) 131 { 132 PetscFunctionBegin; 133 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 134 PetscValidRealPointer(pivot, 2); 135 PetscValidIntPointer(row, 3); 136 *pivot = mat->factorerror_zeropivot_value; 137 *row = mat->factorerror_zeropivot_row; 138 PetscFunctionReturn(PETSC_SUCCESS); 139 } 140 141 /*@ 142 MatFactorGetError - gets the error code from a factorization 143 144 Logically Collective 145 146 Input Parameter: 147 . mat - the factored matrix 148 149 Output Parameter: 150 . err - the error code 151 152 Level: advanced 153 154 Note: 155 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 156 157 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, 158 `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, `MatFactorError` 159 @*/ 160 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err) 161 { 162 PetscFunctionBegin; 163 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 164 PetscValidPointer(err, 2); 165 *err = mat->factorerrortype; 166 PetscFunctionReturn(PETSC_SUCCESS); 167 } 168 169 /*@ 170 MatFactorClearError - clears the error code in a factorization 171 172 Logically Collective 173 174 Input Parameter: 175 . mat - the factored matrix 176 177 Level: developer 178 179 Note: 180 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 181 182 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`, 183 `MatGetErrorCode()`, `MatFactorError` 184 @*/ 185 PetscErrorCode MatFactorClearError(Mat mat) 186 { 187 PetscFunctionBegin; 188 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 189 mat->factorerrortype = MAT_FACTOR_NOERROR; 190 mat->factorerror_zeropivot_value = 0.0; 191 mat->factorerror_zeropivot_row = 0; 192 PetscFunctionReturn(PETSC_SUCCESS); 193 } 194 195 PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero) 196 { 197 Vec r, l; 198 const PetscScalar *al; 199 PetscInt i, nz, gnz, N, n; 200 201 PetscFunctionBegin; 202 PetscCall(MatCreateVecs(mat, &r, &l)); 203 if (!cols) { /* nonzero rows */ 204 PetscCall(MatGetSize(mat, &N, NULL)); 205 PetscCall(MatGetLocalSize(mat, &n, NULL)); 206 PetscCall(VecSet(l, 0.0)); 207 PetscCall(VecSetRandom(r, NULL)); 208 PetscCall(MatMult(mat, r, l)); 209 PetscCall(VecGetArrayRead(l, &al)); 210 } else { /* nonzero columns */ 211 PetscCall(MatGetSize(mat, NULL, &N)); 212 PetscCall(MatGetLocalSize(mat, NULL, &n)); 213 PetscCall(VecSet(r, 0.0)); 214 PetscCall(VecSetRandom(l, NULL)); 215 PetscCall(MatMultTranspose(mat, l, r)); 216 PetscCall(VecGetArrayRead(r, &al)); 217 } 218 if (tol <= 0.0) { 219 for (i = 0, nz = 0; i < n; i++) 220 if (al[i] != 0.0) nz++; 221 } else { 222 for (i = 0, nz = 0; i < n; i++) 223 if (PetscAbsScalar(al[i]) > tol) nz++; 224 } 225 PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 226 if (gnz != N) { 227 PetscInt *nzr; 228 PetscCall(PetscMalloc1(nz, &nzr)); 229 if (nz) { 230 if (tol < 0) { 231 for (i = 0, nz = 0; i < n; i++) 232 if (al[i] != 0.0) nzr[nz++] = i; 233 } else { 234 for (i = 0, nz = 0; i < n; i++) 235 if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i; 236 } 237 } 238 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero)); 239 } else *nonzero = NULL; 240 if (!cols) { /* nonzero rows */ 241 PetscCall(VecRestoreArrayRead(l, &al)); 242 } else { 243 PetscCall(VecRestoreArrayRead(r, &al)); 244 } 245 PetscCall(VecDestroy(&l)); 246 PetscCall(VecDestroy(&r)); 247 PetscFunctionReturn(PETSC_SUCCESS); 248 } 249 250 /*@ 251 MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix 252 253 Input Parameter: 254 . A - the matrix 255 256 Output Parameter: 257 . keptrows - the rows that are not completely zero 258 259 Level: intermediate 260 261 Note: 262 `keptrows` is set to `NULL` if all rows are nonzero. 263 264 .seealso: [](ch_matrices), `Mat`, `MatFindZeroRows()` 265 @*/ 266 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows) 267 { 268 PetscFunctionBegin; 269 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 270 PetscValidType(mat, 1); 271 PetscValidPointer(keptrows, 2); 272 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 273 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 274 if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows); 275 else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows)); 276 PetscFunctionReturn(PETSC_SUCCESS); 277 } 278 279 /*@ 280 MatFindZeroRows - Locate all rows that are completely zero in the matrix 281 282 Input Parameter: 283 . A - the matrix 284 285 Output Parameter: 286 . zerorows - the rows that are completely zero 287 288 Level: intermediate 289 290 Note: 291 `zerorows` is set to `NULL` if no rows are zero. 292 293 .seealso: [](ch_matrices), `Mat`, `MatFindNonzeroRows()` 294 @*/ 295 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows) 296 { 297 IS keptrows; 298 PetscInt m, n; 299 300 PetscFunctionBegin; 301 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 302 PetscValidType(mat, 1); 303 PetscValidPointer(zerorows, 2); 304 PetscCall(MatFindNonzeroRows(mat, &keptrows)); 305 /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows. 306 In keeping with this convention, we set zerorows to NULL if there are no zero 307 rows. */ 308 if (keptrows == NULL) { 309 *zerorows = NULL; 310 } else { 311 PetscCall(MatGetOwnershipRange(mat, &m, &n)); 312 PetscCall(ISComplement(keptrows, m, n, zerorows)); 313 PetscCall(ISDestroy(&keptrows)); 314 } 315 PetscFunctionReturn(PETSC_SUCCESS); 316 } 317 318 /*@ 319 MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling 320 321 Not Collective 322 323 Input Parameter: 324 . A - the matrix 325 326 Output Parameter: 327 . a - the diagonal part (which is a SEQUENTIAL matrix) 328 329 Level: advanced 330 331 Notes: 332 See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix. 333 334 Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation. 335 336 .seealso: [](ch_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ` 337 @*/ 338 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a) 339 { 340 PetscFunctionBegin; 341 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 342 PetscValidType(A, 1); 343 PetscValidPointer(a, 2); 344 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 345 if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a); 346 else { 347 PetscMPIInt size; 348 349 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 350 PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name); 351 *a = A; 352 } 353 PetscFunctionReturn(PETSC_SUCCESS); 354 } 355 356 /*@ 357 MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries. 358 359 Collective 360 361 Input Parameter: 362 . mat - the matrix 363 364 Output Parameter: 365 . trace - the sum of the diagonal entries 366 367 Level: advanced 368 369 .seealso: [](ch_matrices), `Mat` 370 @*/ 371 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace) 372 { 373 Vec diag; 374 375 PetscFunctionBegin; 376 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 377 PetscValidScalarPointer(trace, 2); 378 PetscCall(MatCreateVecs(mat, &diag, NULL)); 379 PetscCall(MatGetDiagonal(mat, diag)); 380 PetscCall(VecSum(diag, trace)); 381 PetscCall(VecDestroy(&diag)); 382 PetscFunctionReturn(PETSC_SUCCESS); 383 } 384 385 /*@ 386 MatRealPart - Zeros out the imaginary part of the matrix 387 388 Logically Collective 389 390 Input Parameter: 391 . mat - the matrix 392 393 Level: advanced 394 395 .seealso: [](ch_matrices), `Mat`, `MatImaginaryPart()` 396 @*/ 397 PetscErrorCode MatRealPart(Mat mat) 398 { 399 PetscFunctionBegin; 400 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 401 PetscValidType(mat, 1); 402 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 403 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 404 MatCheckPreallocated(mat, 1); 405 PetscUseTypeMethod(mat, realpart); 406 PetscFunctionReturn(PETSC_SUCCESS); 407 } 408 409 /*@C 410 MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix 411 412 Collective 413 414 Input Parameter: 415 . mat - the matrix 416 417 Output Parameters: 418 + nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each block) 419 - ghosts - the global indices of the ghost points 420 421 Level: advanced 422 423 Note: 424 `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()` 425 426 .seealso: [](ch_matrices), `Mat`, `VecCreateGhost()` 427 @*/ 428 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[]) 429 { 430 PetscFunctionBegin; 431 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 432 PetscValidType(mat, 1); 433 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 434 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 435 if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts); 436 else { 437 if (nghosts) *nghosts = 0; 438 if (ghosts) *ghosts = NULL; 439 } 440 PetscFunctionReturn(PETSC_SUCCESS); 441 } 442 443 /*@ 444 MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part 445 446 Logically Collective 447 448 Input Parameter: 449 . mat - the matrix 450 451 Level: advanced 452 453 .seealso: [](ch_matrices), `Mat`, `MatRealPart()` 454 @*/ 455 PetscErrorCode MatImaginaryPart(Mat mat) 456 { 457 PetscFunctionBegin; 458 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 459 PetscValidType(mat, 1); 460 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 461 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 462 MatCheckPreallocated(mat, 1); 463 PetscUseTypeMethod(mat, imaginarypart); 464 PetscFunctionReturn(PETSC_SUCCESS); 465 } 466 467 /*@ 468 MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices) 469 470 Not Collective 471 472 Input Parameter: 473 . mat - the matrix 474 475 Output Parameters: 476 + missing - is any diagonal missing 477 - dd - first diagonal entry that is missing (optional) on this process 478 479 Level: advanced 480 481 .seealso: [](ch_matrices), `Mat` 482 @*/ 483 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd) 484 { 485 PetscFunctionBegin; 486 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 487 PetscValidType(mat, 1); 488 PetscValidBoolPointer(missing, 2); 489 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name); 490 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 491 PetscUseTypeMethod(mat, missingdiagonal, missing, dd); 492 PetscFunctionReturn(PETSC_SUCCESS); 493 } 494 495 /*@C 496 MatGetRow - Gets a row of a matrix. You MUST call `MatRestoreRow()` 497 for each row that you get to ensure that your application does 498 not bleed memory. 499 500 Not Collective 501 502 Input Parameters: 503 + mat - the matrix 504 - row - the row to get 505 506 Output Parameters: 507 + ncols - if not `NULL`, the number of nonzeros in the row 508 . cols - if not `NULL`, the column numbers 509 - vals - if not `NULL`, the values 510 511 Level: advanced 512 513 Notes: 514 This routine is provided for people who need to have direct access 515 to the structure of a matrix. We hope that we provide enough 516 high-level matrix routines that few users will need it. 517 518 `MatGetRow()` always returns 0-based column indices, regardless of 519 whether the internal representation is 0-based (default) or 1-based. 520 521 For better efficiency, set cols and/or vals to `NULL` if you do 522 not wish to extract these quantities. 523 524 The user can only examine the values extracted with `MatGetRow()`; 525 the values cannot be altered. To change the matrix entries, one 526 must use `MatSetValues()`. 527 528 You can only have one call to `MatGetRow()` outstanding for a particular 529 matrix at a time, per processor. `MatGetRow()` can only obtain rows 530 associated with the given processor, it cannot get rows from the 531 other processors; for that we suggest using `MatCreateSubMatrices()`, then 532 MatGetRow() on the submatrix. The row index passed to `MatGetRow()` 533 is in the global number of rows. 534 535 Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix. 536 537 Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly. 538 539 Fortran Note: 540 The calling sequence is 541 .vb 542 MatGetRow(matrix,row,ncols,cols,values,ierr) 543 Mat matrix (input) 544 integer row (input) 545 integer ncols (output) 546 integer cols(maxcols) (output) 547 double precision (or double complex) values(maxcols) output 548 .ve 549 where maxcols >= maximum nonzeros in any row of the matrix. 550 551 Caution: 552 Do not try to change the contents of the output arrays (`cols` and `vals`). 553 In some cases, this may corrupt the matrix. 554 555 .seealso: [](ch_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()` 556 @*/ 557 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 558 { 559 PetscInt incols; 560 561 PetscFunctionBegin; 562 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 563 PetscValidType(mat, 1); 564 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 565 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 566 MatCheckPreallocated(mat, 1); 567 PetscCheck(row >= mat->rmap->rstart && row < mat->rmap->rend, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Only for local rows, %" PetscInt_FMT " not in [%" PetscInt_FMT ",%" PetscInt_FMT ")", row, mat->rmap->rstart, mat->rmap->rend); 568 PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0)); 569 PetscUseTypeMethod(mat, getrow, row, &incols, (PetscInt **)cols, (PetscScalar **)vals); 570 if (ncols) *ncols = incols; 571 PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0)); 572 PetscFunctionReturn(PETSC_SUCCESS); 573 } 574 575 /*@ 576 MatConjugate - replaces the matrix values with their complex conjugates 577 578 Logically Collective 579 580 Input Parameter: 581 . mat - the matrix 582 583 Level: advanced 584 585 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()` 586 @*/ 587 PetscErrorCode MatConjugate(Mat mat) 588 { 589 PetscFunctionBegin; 590 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 591 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 592 if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) { 593 PetscUseTypeMethod(mat, conjugate); 594 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 595 } 596 PetscFunctionReturn(PETSC_SUCCESS); 597 } 598 599 /*@C 600 MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`. 601 602 Not Collective 603 604 Input Parameters: 605 + mat - the matrix 606 . row - the row to get 607 . ncols - the number of nonzeros 608 . cols - the columns of the nonzeros 609 - vals - if nonzero the column values 610 611 Level: advanced 612 613 Notes: 614 This routine should be called after you have finished examining the entries. 615 616 This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental 617 us of the array after it has been restored. If you pass `NULL`, it will 618 not zero the pointers. Use of `cols` or `vals` after `MatRestoreRow()` is invalid. 619 620 Fortran Notes: 621 The calling sequence is 622 .vb 623 MatRestoreRow(matrix,row,ncols,cols,values,ierr) 624 Mat matrix (input) 625 integer row (input) 626 integer ncols (output) 627 integer cols(maxcols) (output) 628 double precision (or double complex) values(maxcols) output 629 .ve 630 Where maxcols >= maximum nonzeros in any row of the matrix. 631 632 In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()` 633 before another call to `MatGetRow()` can be made. 634 635 .seealso: [](ch_matrices), `Mat`, `MatGetRow()` 636 @*/ 637 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 638 { 639 PetscFunctionBegin; 640 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 641 if (ncols) PetscValidIntPointer(ncols, 3); 642 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 643 if (!mat->ops->restorerow) PetscFunctionReturn(PETSC_SUCCESS); 644 PetscUseTypeMethod(mat, restorerow, row, ncols, (PetscInt **)cols, (PetscScalar **)vals); 645 if (ncols) *ncols = 0; 646 if (cols) *cols = NULL; 647 if (vals) *vals = NULL; 648 PetscFunctionReturn(PETSC_SUCCESS); 649 } 650 651 /*@ 652 MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 653 You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag. 654 655 Not Collective 656 657 Input Parameter: 658 . mat - the matrix 659 660 Level: advanced 661 662 Note: 663 The flag is to ensure that users are aware that `MatGetRow()` only provides the upper triangular part of the row for the matrices in `MATSBAIJ` format. 664 665 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()` 666 @*/ 667 PetscErrorCode MatGetRowUpperTriangular(Mat mat) 668 { 669 PetscFunctionBegin; 670 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 671 PetscValidType(mat, 1); 672 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 673 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 674 MatCheckPreallocated(mat, 1); 675 if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS); 676 PetscUseTypeMethod(mat, getrowuppertriangular); 677 PetscFunctionReturn(PETSC_SUCCESS); 678 } 679 680 /*@ 681 MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 682 683 Not Collective 684 685 Input Parameter: 686 . mat - the matrix 687 688 Level: advanced 689 690 Note: 691 This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`. 692 693 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()` 694 @*/ 695 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat) 696 { 697 PetscFunctionBegin; 698 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 699 PetscValidType(mat, 1); 700 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 701 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 702 MatCheckPreallocated(mat, 1); 703 if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS); 704 PetscUseTypeMethod(mat, restorerowuppertriangular); 705 PetscFunctionReturn(PETSC_SUCCESS); 706 } 707 708 /*@C 709 MatSetOptionsPrefix - Sets the prefix used for searching for all 710 `Mat` options in the database. 711 712 Logically Collective 713 714 Input Parameters: 715 + A - the matrix 716 - prefix - the prefix to prepend to all option names 717 718 Level: advanced 719 720 Notes: 721 A hyphen (-) must NOT be given at the beginning of the prefix name. 722 The first character of all runtime options is AUTOMATICALLY the hyphen. 723 724 This is NOT used for options for the factorization of the matrix. Normally the 725 prefix is automatically passed in from the PC calling the factorization. To set 726 it directly use `MatSetOptionsPrefixFactor()` 727 728 .seealso: [](ch_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()` 729 @*/ 730 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[]) 731 { 732 PetscFunctionBegin; 733 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 734 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix)); 735 PetscFunctionReturn(PETSC_SUCCESS); 736 } 737 738 /*@C 739 MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for 740 for matrices created with `MatGetFactor()` 741 742 Logically Collective 743 744 Input Parameters: 745 + A - the matrix 746 - prefix - the prefix to prepend to all option names for the factored matrix 747 748 Level: developer 749 750 Notes: 751 A hyphen (-) must NOT be given at the beginning of the prefix name. 752 The first character of all runtime options is AUTOMATICALLY the hyphen. 753 754 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 755 it directly when not using `KSP`/`PC` use `MatSetOptionsPrefixFactor()` 756 757 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()` 758 @*/ 759 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[]) 760 { 761 PetscFunctionBegin; 762 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 763 if (prefix) { 764 PetscValidCharPointer(prefix, 2); 765 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 766 if (prefix != A->factorprefix) { 767 PetscCall(PetscFree(A->factorprefix)); 768 PetscCall(PetscStrallocpy(prefix, &A->factorprefix)); 769 } 770 } else PetscCall(PetscFree(A->factorprefix)); 771 PetscFunctionReturn(PETSC_SUCCESS); 772 } 773 774 /*@C 775 MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for 776 for matrices created with `MatGetFactor()` 777 778 Logically Collective 779 780 Input Parameters: 781 + A - the matrix 782 - prefix - the prefix to prepend to all option names for the factored matrix 783 784 Level: developer 785 786 Notes: 787 A hyphen (-) must NOT be given at the beginning of the prefix name. 788 The first character of all runtime options is AUTOMATICALLY the hyphen. 789 790 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 791 it directly when not using `KSP`/`PC` use `MatAppendOptionsPrefixFactor()` 792 793 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`, 794 `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`, 795 `MatSetOptionsPrefix()` 796 @*/ 797 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[]) 798 { 799 size_t len1, len2, new_len; 800 801 PetscFunctionBegin; 802 PetscValidHeader(A, 1); 803 if (!prefix) PetscFunctionReturn(PETSC_SUCCESS); 804 if (!A->factorprefix) { 805 PetscCall(MatSetOptionsPrefixFactor(A, prefix)); 806 PetscFunctionReturn(PETSC_SUCCESS); 807 } 808 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 809 810 PetscCall(PetscStrlen(A->factorprefix, &len1)); 811 PetscCall(PetscStrlen(prefix, &len2)); 812 new_len = len1 + len2 + 1; 813 PetscCall(PetscRealloc(new_len * sizeof(*(A->factorprefix)), &A->factorprefix)); 814 PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1)); 815 PetscFunctionReturn(PETSC_SUCCESS); 816 } 817 818 /*@C 819 MatAppendOptionsPrefix - Appends to the prefix used for searching for all 820 matrix options in the database. 821 822 Logically Collective 823 824 Input Parameters: 825 + A - the matrix 826 - prefix - the prefix to prepend to all option names 827 828 Level: advanced 829 830 Note: 831 A hyphen (-) must NOT be given at the beginning of the prefix name. 832 The first character of all runtime options is AUTOMATICALLY the hyphen. 833 834 .seealso: [](ch_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()` 835 @*/ 836 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[]) 837 { 838 PetscFunctionBegin; 839 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 840 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix)); 841 PetscFunctionReturn(PETSC_SUCCESS); 842 } 843 844 /*@C 845 MatGetOptionsPrefix - Gets the prefix used for searching for all 846 matrix options in the database. 847 848 Not Collective 849 850 Input Parameter: 851 . A - the matrix 852 853 Output Parameter: 854 . prefix - pointer to the prefix string used 855 856 Level: advanced 857 858 Fortran Note: 859 The user should pass in a string `prefix` of 860 sufficient length to hold the prefix. 861 862 .seealso: [](ch_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()` 863 @*/ 864 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[]) 865 { 866 PetscFunctionBegin; 867 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 868 PetscValidPointer(prefix, 2); 869 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix)); 870 PetscFunctionReturn(PETSC_SUCCESS); 871 } 872 873 /*@ 874 MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by users. 875 876 Collective 877 878 Input Parameter: 879 . A - the matrix 880 881 Level: beginner 882 883 Notes: 884 The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`. 885 886 Users can reset the preallocation to access the original memory. 887 888 Currently only supported for `MATAIJ` matrices. 889 890 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()` 891 @*/ 892 PetscErrorCode MatResetPreallocation(Mat A) 893 { 894 PetscFunctionBegin; 895 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 896 PetscValidType(A, 1); 897 PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A)); 898 PetscFunctionReturn(PETSC_SUCCESS); 899 } 900 901 /*@ 902 MatSetUp - Sets up the internal matrix data structures for later use. 903 904 Collective 905 906 Input Parameter: 907 . A - the matrix 908 909 Level: intermediate 910 911 Notes: 912 If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of 913 setting values in the matrix. 914 915 If a suitable preallocation routine is used, this function does not need to be called. 916 917 This routine is called internally by other matrix functions when needed so rarely needs to be called by users 918 919 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()` 920 @*/ 921 PetscErrorCode MatSetUp(Mat A) 922 { 923 PetscFunctionBegin; 924 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 925 if (!((PetscObject)A)->type_name) { 926 PetscMPIInt size; 927 928 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 929 PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ)); 930 } 931 if (!A->preallocated) PetscTryTypeMethod(A, setup); 932 PetscCall(PetscLayoutSetUp(A->rmap)); 933 PetscCall(PetscLayoutSetUp(A->cmap)); 934 A->preallocated = PETSC_TRUE; 935 PetscFunctionReturn(PETSC_SUCCESS); 936 } 937 938 #if defined(PETSC_HAVE_SAWS) 939 #include <petscviewersaws.h> 940 #endif 941 942 /* 943 If threadsafety is on extraneous matrices may be printed 944 945 This flag cannot be stored in the matrix because the original matrix in MatView() may assemble a new matrix which is passed into MatViewFromOptions() 946 */ 947 #if !defined(PETSC_HAVE_THREADSAFETY) 948 static PetscInt insidematview = 0; 949 #endif 950 951 /*@C 952 MatViewFromOptions - View properties of the matrix based on options set in the options database 953 954 Collective 955 956 Input Parameters: 957 + A - the matrix 958 . obj - optional additional object that provides the options prefix to use 959 - name - command line option 960 961 Options Database Key: 962 . -mat_view [viewertype]:... - the viewer and its options 963 964 Level: intermediate 965 966 Notes: 967 .vb 968 If no value is provided ascii:stdout is used 969 ascii[:[filename][:[format][:append]]] defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab, 970 for example ascii::ascii_info prints just the information about the object not all details 971 unless :append is given filename opens in write mode, overwriting what was already there 972 binary[:[filename][:[format][:append]]] defaults to the file binaryoutput 973 draw[:drawtype[:filename]] for example, draw:tikz, draw:tikz:figure.tex or draw:x 974 socket[:port] defaults to the standard output port 975 saws[:communicatorname] publishes object to the Scientific Application Webserver (SAWs) 976 .ve 977 978 .seealso: [](ch_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()` 979 @*/ 980 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[]) 981 { 982 PetscFunctionBegin; 983 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 984 #if !defined(PETSC_HAVE_THREADSAFETY) 985 if (insidematview) PetscFunctionReturn(PETSC_SUCCESS); 986 #endif 987 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 988 PetscFunctionReturn(PETSC_SUCCESS); 989 } 990 991 /*@C 992 MatView - display information about a matrix in a variety ways 993 994 Collective 995 996 Input Parameters: 997 + mat - the matrix 998 - viewer - visualization context 999 1000 Options Database Keys: 1001 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 1002 . -mat_view ::ascii_info_detail - Prints more detailed info 1003 . -mat_view - Prints matrix in ASCII format 1004 . -mat_view ::ascii_matlab - Prints matrix in Matlab format 1005 . -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 1006 . -display <name> - Sets display name (default is host) 1007 . -draw_pause <sec> - Sets number of seconds to pause after display 1008 . -mat_view socket - Sends matrix to socket, can be accessed from Matlab (see Users-Manual: ch_matlab for details) 1009 . -viewer_socket_machine <machine> - 1010 . -viewer_socket_port <port> - 1011 . -mat_view binary - save matrix to file in binary format 1012 - -viewer_binary_filename <name> - 1013 1014 Level: beginner 1015 1016 Notes: 1017 The available visualization contexts include 1018 + `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices 1019 . `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD` 1020 . `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm 1021 - `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure 1022 1023 The user can open alternative visualization contexts with 1024 + `PetscViewerASCIIOpen()` - Outputs matrix to a specified file 1025 . `PetscViewerBinaryOpen()` - Outputs matrix in binary to a 1026 specified file; corresponding input uses MatLoad() 1027 . `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to 1028 an X window display 1029 - `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer. 1030 Currently only the sequential dense and AIJ 1031 matrix types support the Socket viewer. 1032 1033 The user can call `PetscViewerPushFormat()` to specify the output 1034 format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`, 1035 `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`). Available formats include 1036 + `PETSC_VIEWER_DEFAULT` - default, prints matrix contents 1037 . `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in Matlab format 1038 . `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros 1039 . `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse 1040 format common among all matrix types 1041 . `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific 1042 format (which is in many cases the same as the default) 1043 . `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix 1044 size and structure (not the matrix entries) 1045 - `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about 1046 the matrix structure 1047 1048 The ASCII viewers are only recommended for small matrices on at most a moderate number of processes, 1049 the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format. 1050 1051 In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer). 1052 1053 See the manual page for `MatLoad()` for the exact format of the binary file when the binary 1054 viewer is used. 1055 1056 See share/petsc/matlab/PetscBinaryRead.m for a Matlab code that can read in the binary file when the binary 1057 viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python. 1058 1059 One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure, 1060 and then use the following mouse functions. 1061 .vb 1062 left mouse: zoom in 1063 middle mouse: zoom out 1064 right mouse: continue with the simulation 1065 .ve 1066 1067 .seealso: [](ch_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`, 1068 `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()` 1069 @*/ 1070 PetscErrorCode MatView(Mat mat, PetscViewer viewer) 1071 { 1072 PetscInt rows, cols, rbs, cbs; 1073 PetscBool isascii, isstring, issaws; 1074 PetscViewerFormat format; 1075 PetscMPIInt size; 1076 1077 PetscFunctionBegin; 1078 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1079 PetscValidType(mat, 1); 1080 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer)); 1081 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1082 PetscCheckSameComm(mat, 1, viewer, 2); 1083 1084 PetscCall(PetscViewerGetFormat(viewer, &format)); 1085 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 1086 if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS); 1087 1088 #if !defined(PETSC_HAVE_THREADSAFETY) 1089 insidematview++; 1090 #endif 1091 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 1092 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 1093 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws)); 1094 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"); 1095 1096 PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0)); 1097 if (isascii) { 1098 if (!mat->preallocated) { 1099 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n")); 1100 #if !defined(PETSC_HAVE_THREADSAFETY) 1101 insidematview--; 1102 #endif 1103 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1104 PetscFunctionReturn(PETSC_SUCCESS); 1105 } 1106 if (!mat->assembled) { 1107 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n")); 1108 #if !defined(PETSC_HAVE_THREADSAFETY) 1109 insidematview--; 1110 #endif 1111 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1112 PetscFunctionReturn(PETSC_SUCCESS); 1113 } 1114 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer)); 1115 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1116 MatNullSpace nullsp, transnullsp; 1117 1118 PetscCall(PetscViewerASCIIPushTab(viewer)); 1119 PetscCall(MatGetSize(mat, &rows, &cols)); 1120 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1121 if (rbs != 1 || cbs != 1) { 1122 if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs)); 1123 else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs)); 1124 } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols)); 1125 if (mat->factortype) { 1126 MatSolverType solver; 1127 PetscCall(MatFactorGetSolverType(mat, &solver)); 1128 PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver)); 1129 } 1130 if (mat->ops->getinfo) { 1131 MatInfo info; 1132 PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info)); 1133 PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated)); 1134 if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs)); 1135 } 1136 PetscCall(MatGetNullSpace(mat, &nullsp)); 1137 PetscCall(MatGetTransposeNullSpace(mat, &transnullsp)); 1138 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached null space\n")); 1139 if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached transposed null space\n")); 1140 PetscCall(MatGetNearNullSpace(mat, &nullsp)); 1141 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached near null space\n")); 1142 PetscCall(PetscViewerASCIIPushTab(viewer)); 1143 PetscCall(MatProductView(mat, viewer)); 1144 PetscCall(PetscViewerASCIIPopTab(viewer)); 1145 } 1146 } else if (issaws) { 1147 #if defined(PETSC_HAVE_SAWS) 1148 PetscMPIInt rank; 1149 1150 PetscCall(PetscObjectName((PetscObject)mat)); 1151 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 1152 if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer)); 1153 #endif 1154 } else if (isstring) { 1155 const char *type; 1156 PetscCall(MatGetType(mat, &type)); 1157 PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type)); 1158 PetscTryTypeMethod(mat, view, viewer); 1159 } 1160 if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) { 1161 PetscCall(PetscViewerASCIIPushTab(viewer)); 1162 PetscUseTypeMethod(mat, viewnative, viewer); 1163 PetscCall(PetscViewerASCIIPopTab(viewer)); 1164 } else if (mat->ops->view) { 1165 PetscCall(PetscViewerASCIIPushTab(viewer)); 1166 PetscUseTypeMethod(mat, view, viewer); 1167 PetscCall(PetscViewerASCIIPopTab(viewer)); 1168 } 1169 if (isascii) { 1170 PetscCall(PetscViewerGetFormat(viewer, &format)); 1171 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer)); 1172 } 1173 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1174 #if !defined(PETSC_HAVE_THREADSAFETY) 1175 insidematview--; 1176 #endif 1177 PetscFunctionReturn(PETSC_SUCCESS); 1178 } 1179 1180 #if defined(PETSC_USE_DEBUG) 1181 #include <../src/sys/totalview/tv_data_display.h> 1182 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat) 1183 { 1184 TV_add_row("Local rows", "int", &mat->rmap->n); 1185 TV_add_row("Local columns", "int", &mat->cmap->n); 1186 TV_add_row("Global rows", "int", &mat->rmap->N); 1187 TV_add_row("Global columns", "int", &mat->cmap->N); 1188 TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name); 1189 return TV_format_OK; 1190 } 1191 #endif 1192 1193 /*@C 1194 MatLoad - Loads a matrix that has been stored in binary/HDF5 format 1195 with `MatView()`. The matrix format is determined from the options database. 1196 Generates a parallel MPI matrix if the communicator has more than one 1197 processor. The default matrix type is `MATAIJ`. 1198 1199 Collective 1200 1201 Input Parameters: 1202 + mat - the newly loaded matrix, this needs to have been created with `MatCreate()` 1203 or some related function before a call to `MatLoad()` 1204 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer 1205 1206 Options Database Keys: 1207 Used with block matrix formats (`MATSEQBAIJ`, ...) to specify 1208 block size 1209 . -matload_block_size <bs> - set block size 1210 1211 Level: beginner 1212 1213 Notes: 1214 If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the 1215 `Mat` before calling this routine if you wish to set it from the options database. 1216 1217 `MatLoad()` automatically loads into the options database any options 1218 given in the file filename.info where filename is the name of the file 1219 that was passed to the `PetscViewerBinaryOpen()`. The options in the info 1220 file will be ignored if you use the -viewer_binary_skip_info option. 1221 1222 If the type or size of mat is not set before a call to `MatLoad()`, PETSc 1223 sets the default matrix type AIJ and sets the local and global sizes. 1224 If type and/or size is already set, then the same are used. 1225 1226 In parallel, each processor can load a subset of rows (or the 1227 entire matrix). This routine is especially useful when a large 1228 matrix is stored on disk and only part of it is desired on each 1229 processor. For example, a parallel solver may access only some of 1230 the rows from each processor. The algorithm used here reads 1231 relatively small blocks of data rather than reading the entire 1232 matrix and then subsetting it. 1233 1234 Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`. 1235 Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`, 1236 or the sequence like 1237 .vb 1238 `PetscViewer` v; 1239 `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v); 1240 `PetscViewerSetType`(v,`PETSCVIEWERBINARY`); 1241 `PetscViewerSetFromOptions`(v); 1242 `PetscViewerFileSetMode`(v,`FILE_MODE_READ`); 1243 `PetscViewerFileSetName`(v,"datafile"); 1244 .ve 1245 The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option 1246 $ -viewer_type {binary, hdf5} 1247 1248 See the example src/ksp/ksp/tutorials/ex27.c with the first approach, 1249 and src/mat/tutorials/ex10.c with the second approach. 1250 1251 In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks 1252 is read onto rank 0 and then shipped to its destination rank, one after another. 1253 Multiple objects, both matrices and vectors, can be stored within the same file. 1254 Their PetscObject name is ignored; they are loaded in the order of their storage. 1255 1256 Most users should not need to know the details of the binary storage 1257 format, since `MatLoad()` and `MatView()` completely hide these details. 1258 But for anyone who's interested, the standard binary matrix storage 1259 format is 1260 1261 .vb 1262 PetscInt MAT_FILE_CLASSID 1263 PetscInt number of rows 1264 PetscInt number of columns 1265 PetscInt total number of nonzeros 1266 PetscInt *number nonzeros in each row 1267 PetscInt *column indices of all nonzeros (starting index is zero) 1268 PetscScalar *values of all nonzeros 1269 .ve 1270 1271 PETSc automatically does the byte swapping for 1272 machines that store the bytes reversed. Thus if you write your own binary 1273 read/write routines you have to swap the bytes; see `PetscBinaryRead()` 1274 and `PetscBinaryWrite()` to see how this may be done. 1275 1276 In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used. 1277 Each processor's chunk is loaded independently by its owning rank. 1278 Multiple objects, both matrices and vectors, can be stored within the same file. 1279 They are looked up by their PetscObject name. 1280 1281 As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use 1282 by default the same structure and naming of the AIJ arrays and column count 1283 within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g. 1284 $ save example.mat A b -v7.3 1285 can be directly read by this routine (see Reference 1 for details). 1286 1287 Depending on your MATLAB version, this format might be a default, 1288 otherwise you can set it as default in Preferences. 1289 1290 Unless -nocompression flag is used to save the file in MATLAB, 1291 PETSc must be configured with ZLIB package. 1292 1293 See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c 1294 1295 This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5` 1296 1297 Corresponding `MatView()` is not yet implemented. 1298 1299 The loaded matrix is actually a transpose of the original one in MATLAB, 1300 unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above). 1301 With this format, matrix is automatically transposed by PETSc, 1302 unless the matrix is marked as SPD or symmetric 1303 (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`). 1304 1305 References: 1306 . * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version 1307 1308 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()` 1309 @*/ 1310 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer) 1311 { 1312 PetscBool flg; 1313 1314 PetscFunctionBegin; 1315 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1316 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1317 1318 if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ)); 1319 1320 flg = PETSC_FALSE; 1321 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL)); 1322 if (flg) { 1323 PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE)); 1324 PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE)); 1325 } 1326 flg = PETSC_FALSE; 1327 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL)); 1328 if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE)); 1329 1330 PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0)); 1331 PetscUseTypeMethod(mat, load, viewer); 1332 PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0)); 1333 PetscFunctionReturn(PETSC_SUCCESS); 1334 } 1335 1336 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant) 1337 { 1338 Mat_Redundant *redund = *redundant; 1339 1340 PetscFunctionBegin; 1341 if (redund) { 1342 if (redund->matseq) { /* via MatCreateSubMatrices() */ 1343 PetscCall(ISDestroy(&redund->isrow)); 1344 PetscCall(ISDestroy(&redund->iscol)); 1345 PetscCall(MatDestroySubMatrices(1, &redund->matseq)); 1346 } else { 1347 PetscCall(PetscFree2(redund->send_rank, redund->recv_rank)); 1348 PetscCall(PetscFree(redund->sbuf_j)); 1349 PetscCall(PetscFree(redund->sbuf_a)); 1350 for (PetscInt i = 0; i < redund->nrecvs; i++) { 1351 PetscCall(PetscFree(redund->rbuf_j[i])); 1352 PetscCall(PetscFree(redund->rbuf_a[i])); 1353 } 1354 PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a)); 1355 } 1356 1357 if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm)); 1358 PetscCall(PetscFree(redund)); 1359 } 1360 PetscFunctionReturn(PETSC_SUCCESS); 1361 } 1362 1363 /*@C 1364 MatDestroy - Frees space taken by a matrix. 1365 1366 Collective 1367 1368 Input Parameter: 1369 . A - the matrix 1370 1371 Level: beginner 1372 1373 Developer Note: 1374 Some special arrays of matrices are not destroyed in this routine but instead by the routines called by 1375 `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines. 1376 `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes 1377 if changes are needed here. 1378 1379 .seealso: [](ch_matrices), `Mat`, `MatCreate()` 1380 @*/ 1381 PetscErrorCode MatDestroy(Mat *A) 1382 { 1383 PetscFunctionBegin; 1384 if (!*A) PetscFunctionReturn(PETSC_SUCCESS); 1385 PetscValidHeaderSpecific(*A, MAT_CLASSID, 1); 1386 if (--((PetscObject)(*A))->refct > 0) { 1387 *A = NULL; 1388 PetscFunctionReturn(PETSC_SUCCESS); 1389 } 1390 1391 /* if memory was published with SAWs then destroy it */ 1392 PetscCall(PetscObjectSAWsViewOff((PetscObject)*A)); 1393 PetscTryTypeMethod((*A), destroy); 1394 1395 PetscCall(PetscFree((*A)->factorprefix)); 1396 PetscCall(PetscFree((*A)->defaultvectype)); 1397 PetscCall(PetscFree((*A)->defaultrandtype)); 1398 PetscCall(PetscFree((*A)->bsizes)); 1399 PetscCall(PetscFree((*A)->solvertype)); 1400 for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i])); 1401 if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL; 1402 PetscCall(MatDestroy_Redundant(&(*A)->redundant)); 1403 PetscCall(MatProductClear(*A)); 1404 PetscCall(MatNullSpaceDestroy(&(*A)->nullsp)); 1405 PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp)); 1406 PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp)); 1407 PetscCall(MatDestroy(&(*A)->schur)); 1408 PetscCall(PetscLayoutDestroy(&(*A)->rmap)); 1409 PetscCall(PetscLayoutDestroy(&(*A)->cmap)); 1410 PetscCall(PetscHeaderDestroy(A)); 1411 PetscFunctionReturn(PETSC_SUCCESS); 1412 } 1413 1414 /*@C 1415 MatSetValues - Inserts or adds a block of values into a matrix. 1416 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1417 MUST be called after all calls to `MatSetValues()` have been completed. 1418 1419 Not Collective 1420 1421 Input Parameters: 1422 + mat - the matrix 1423 . v - a logically two-dimensional array of values 1424 . m - the number of rows 1425 . idxm - the global indices of the rows 1426 . n - the number of columns 1427 . idxn - the global indices of the columns 1428 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1429 1430 Level: beginner 1431 1432 Notes: 1433 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1434 1435 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1436 options cannot be mixed without intervening calls to the assembly 1437 routines. 1438 1439 `MatSetValues()` uses 0-based row and column numbers in Fortran 1440 as well as in C. 1441 1442 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1443 simply ignored. This allows easily inserting element stiffness matrices 1444 with homogeneous Dirchlet boundary conditions that you don't want represented 1445 in the matrix. 1446 1447 Efficiency Alert: 1448 The routine `MatSetValuesBlocked()` may offer much better efficiency 1449 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1450 1451 Developer Note: 1452 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1453 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1454 1455 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1456 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1457 @*/ 1458 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1459 { 1460 PetscFunctionBeginHot; 1461 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1462 PetscValidType(mat, 1); 1463 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1464 PetscValidIntPointer(idxm, 3); 1465 PetscValidIntPointer(idxn, 5); 1466 MatCheckPreallocated(mat, 1); 1467 1468 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1469 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1470 1471 if (PetscDefined(USE_DEBUG)) { 1472 PetscInt i, j; 1473 1474 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1475 for (i = 0; i < m; i++) { 1476 for (j = 0; j < n; j++) { 1477 if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j])) 1478 #if defined(PETSC_USE_COMPLEX) 1479 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]); 1480 #else 1481 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]); 1482 #endif 1483 } 1484 } 1485 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); 1486 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); 1487 } 1488 1489 if (mat->assembled) { 1490 mat->was_assembled = PETSC_TRUE; 1491 mat->assembled = PETSC_FALSE; 1492 } 1493 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1494 PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv); 1495 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1496 PetscFunctionReturn(PETSC_SUCCESS); 1497 } 1498 1499 /*@C 1500 MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns 1501 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1502 MUST be called after all calls to `MatSetValues()` have been completed. 1503 1504 Not Collective 1505 1506 Input Parameters: 1507 + mat - the matrix 1508 . v - a logically two-dimensional array of values 1509 . ism - the rows to provide 1510 . isn - the columns to provide 1511 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1512 1513 Level: beginner 1514 1515 Notes: 1516 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1517 1518 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1519 options cannot be mixed without intervening calls to the assembly 1520 routines. 1521 1522 `MatSetValues()` uses 0-based row and column numbers in Fortran 1523 as well as in C. 1524 1525 Negative indices may be passed in `ism` and `isn`, these rows and columns are 1526 simply ignored. This allows easily inserting element stiffness matrices 1527 with homogeneous Dirchlet boundary conditions that you don't want represented 1528 in the matrix. 1529 1530 Efficiency Alert: 1531 The routine `MatSetValuesBlocked()` may offer much better efficiency 1532 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1533 1534 This is currently not optimized for any particular `ISType` 1535 1536 Developer Notes: 1537 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1538 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1539 1540 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1541 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()` 1542 @*/ 1543 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv) 1544 { 1545 PetscInt m, n; 1546 const PetscInt *rows, *cols; 1547 1548 PetscFunctionBeginHot; 1549 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1550 PetscCall(ISGetIndices(ism, &rows)); 1551 PetscCall(ISGetIndices(isn, &cols)); 1552 PetscCall(ISGetLocalSize(ism, &m)); 1553 PetscCall(ISGetLocalSize(isn, &n)); 1554 PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv)); 1555 PetscCall(ISRestoreIndices(ism, &rows)); 1556 PetscCall(ISRestoreIndices(isn, &cols)); 1557 PetscFunctionReturn(PETSC_SUCCESS); 1558 } 1559 1560 /*@ 1561 MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1562 values into a matrix 1563 1564 Not Collective 1565 1566 Input Parameters: 1567 + mat - the matrix 1568 . row - the (block) row to set 1569 - v - a logically two-dimensional array of values 1570 1571 Level: intermediate 1572 1573 Notes: 1574 The values, `v`, are column-oriented (for the block version) and sorted 1575 1576 All the nonzeros in the row must be provided 1577 1578 The matrix must have previously had its column indices set, likely by having been assembled. 1579 1580 The row must belong to this process 1581 1582 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1583 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()` 1584 @*/ 1585 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[]) 1586 { 1587 PetscInt globalrow; 1588 1589 PetscFunctionBegin; 1590 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1591 PetscValidType(mat, 1); 1592 PetscValidScalarPointer(v, 3); 1593 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow)); 1594 PetscCall(MatSetValuesRow(mat, globalrow, v)); 1595 PetscFunctionReturn(PETSC_SUCCESS); 1596 } 1597 1598 /*@ 1599 MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1600 values into a matrix 1601 1602 Not Collective 1603 1604 Input Parameters: 1605 + mat - the matrix 1606 . row - the (block) row to set 1607 - 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 1608 1609 Level: advanced 1610 1611 Notes: 1612 The values, `v`, are column-oriented for the block version. 1613 1614 All the nonzeros in the row must be provided 1615 1616 THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used. 1617 1618 The row must belong to this process 1619 1620 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1621 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()` 1622 @*/ 1623 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[]) 1624 { 1625 PetscFunctionBeginHot; 1626 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1627 PetscValidType(mat, 1); 1628 MatCheckPreallocated(mat, 1); 1629 PetscValidScalarPointer(v, 3); 1630 PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values"); 1631 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1632 mat->insertmode = INSERT_VALUES; 1633 1634 if (mat->assembled) { 1635 mat->was_assembled = PETSC_TRUE; 1636 mat->assembled = PETSC_FALSE; 1637 } 1638 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1639 PetscUseTypeMethod(mat, setvaluesrow, row, v); 1640 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1641 PetscFunctionReturn(PETSC_SUCCESS); 1642 } 1643 1644 /*@ 1645 MatSetValuesStencil - Inserts or adds a block of values into a matrix. 1646 Using structured grid indexing 1647 1648 Not Collective 1649 1650 Input Parameters: 1651 + mat - the matrix 1652 . m - number of rows being entered 1653 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered 1654 . n - number of columns being entered 1655 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered 1656 . v - a logically two-dimensional array of values 1657 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values 1658 1659 Level: beginner 1660 1661 Notes: 1662 By default the values, `v`, are row-oriented. See `MatSetOption()` for other options. 1663 1664 Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1665 options cannot be mixed without intervening calls to the assembly 1666 routines. 1667 1668 The grid coordinates are across the entire grid, not just the local portion 1669 1670 `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran 1671 as well as in C. 1672 1673 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1674 1675 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1676 or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1677 1678 The columns and rows in the stencil passed in MUST be contained within the 1679 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1680 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1681 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1682 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1683 1684 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 1685 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 1686 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 1687 `DM_BOUNDARY_PERIODIC` boundary type. 1688 1689 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 1690 a single value per point) you can skip filling those indices. 1691 1692 Inspired by the structured grid interface to the HYPRE package 1693 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1694 1695 Efficiency Alert: 1696 The routine `MatSetValuesBlockedStencil()` may offer much better efficiency 1697 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1698 1699 Fortran Note: 1700 `idxm` and `idxn` should be declared as 1701 $ MatStencil idxm(4,m),idxn(4,n) 1702 and the values inserted using 1703 .vb 1704 idxm(MatStencil_i,1) = i 1705 idxm(MatStencil_j,1) = j 1706 idxm(MatStencil_k,1) = k 1707 idxm(MatStencil_c,1) = c 1708 etc 1709 .ve 1710 1711 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1712 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil` 1713 @*/ 1714 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1715 { 1716 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1717 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1718 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1719 1720 PetscFunctionBegin; 1721 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1722 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1723 PetscValidType(mat, 1); 1724 PetscValidPointer(idxm, 3); 1725 PetscValidPointer(idxn, 5); 1726 1727 if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 1728 jdxm = buf; 1729 jdxn = buf + m; 1730 } else { 1731 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1732 jdxm = bufm; 1733 jdxn = bufn; 1734 } 1735 for (i = 0; i < m; i++) { 1736 for (j = 0; j < 3 - sdim; j++) dxm++; 1737 tmp = *dxm++ - starts[0]; 1738 for (j = 0; j < dim - 1; j++) { 1739 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1740 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1741 } 1742 if (mat->stencil.noc) dxm++; 1743 jdxm[i] = tmp; 1744 } 1745 for (i = 0; i < n; i++) { 1746 for (j = 0; j < 3 - sdim; j++) dxn++; 1747 tmp = *dxn++ - starts[0]; 1748 for (j = 0; j < dim - 1; j++) { 1749 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1750 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1751 } 1752 if (mat->stencil.noc) dxn++; 1753 jdxn[i] = tmp; 1754 } 1755 PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv)); 1756 PetscCall(PetscFree2(bufm, bufn)); 1757 PetscFunctionReturn(PETSC_SUCCESS); 1758 } 1759 1760 /*@ 1761 MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix. 1762 Using structured grid indexing 1763 1764 Not Collective 1765 1766 Input Parameters: 1767 + mat - the matrix 1768 . m - number of rows being entered 1769 . idxm - grid coordinates for matrix rows being entered 1770 . n - number of columns being entered 1771 . idxn - grid coordinates for matrix columns being entered 1772 . v - a logically two-dimensional array of values 1773 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values 1774 1775 Level: beginner 1776 1777 Notes: 1778 By default the values, `v`, are row-oriented and unsorted. 1779 See `MatSetOption()` for other options. 1780 1781 Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1782 options cannot be mixed without intervening calls to the assembly 1783 routines. 1784 1785 The grid coordinates are across the entire grid, not just the local portion 1786 1787 `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran 1788 as well as in C. 1789 1790 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1791 1792 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1793 or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1794 1795 The columns and rows in the stencil passed in MUST be contained within the 1796 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1797 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1798 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1799 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1800 1801 Negative indices may be passed in idxm and idxn, these rows and columns are 1802 simply ignored. This allows easily inserting element stiffness matrices 1803 with homogeneous Dirchlet boundary conditions that you don't want represented 1804 in the matrix. 1805 1806 Inspired by the structured grid interface to the HYPRE package 1807 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1808 1809 Fortran Note: 1810 `idxm` and `idxn` should be declared as 1811 $ MatStencil idxm(4,m),idxn(4,n) 1812 and the values inserted using 1813 .vb 1814 idxm(MatStencil_i,1) = i 1815 idxm(MatStencil_j,1) = j 1816 idxm(MatStencil_k,1) = k 1817 etc 1818 .ve 1819 1820 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1821 `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`, 1822 `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` 1823 @*/ 1824 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1825 { 1826 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1827 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1828 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1829 1830 PetscFunctionBegin; 1831 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1832 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1833 PetscValidType(mat, 1); 1834 PetscValidPointer(idxm, 3); 1835 PetscValidPointer(idxn, 5); 1836 PetscValidScalarPointer(v, 6); 1837 1838 if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 1839 jdxm = buf; 1840 jdxn = buf + m; 1841 } else { 1842 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1843 jdxm = bufm; 1844 jdxn = bufn; 1845 } 1846 for (i = 0; i < m; i++) { 1847 for (j = 0; j < 3 - sdim; j++) dxm++; 1848 tmp = *dxm++ - starts[0]; 1849 for (j = 0; j < sdim - 1; j++) { 1850 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1851 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1852 } 1853 dxm++; 1854 jdxm[i] = tmp; 1855 } 1856 for (i = 0; i < n; i++) { 1857 for (j = 0; j < 3 - sdim; j++) dxn++; 1858 tmp = *dxn++ - starts[0]; 1859 for (j = 0; j < sdim - 1; j++) { 1860 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1861 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1862 } 1863 dxn++; 1864 jdxn[i] = tmp; 1865 } 1866 PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv)); 1867 PetscCall(PetscFree2(bufm, bufn)); 1868 PetscFunctionReturn(PETSC_SUCCESS); 1869 } 1870 1871 /*@ 1872 MatSetStencil - Sets the grid information for setting values into a matrix via 1873 `MatSetValuesStencil()` 1874 1875 Not Collective 1876 1877 Input Parameters: 1878 + mat - the matrix 1879 . dim - dimension of the grid 1, 2, or 3 1880 . dims - number of grid points in x, y, and z direction, including ghost points on your processor 1881 . starts - starting point of ghost nodes on your processor in x, y, and z direction 1882 - dof - number of degrees of freedom per node 1883 1884 Level: beginner 1885 1886 Notes: 1887 Inspired by the structured grid interface to the HYPRE package 1888 (www.llnl.gov/CASC/hyper) 1889 1890 For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the 1891 user. 1892 1893 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1894 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()` 1895 @*/ 1896 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof) 1897 { 1898 PetscFunctionBegin; 1899 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1900 PetscValidIntPointer(dims, 3); 1901 PetscValidIntPointer(starts, 4); 1902 1903 mat->stencil.dim = dim + (dof > 1); 1904 for (PetscInt i = 0; i < dim; i++) { 1905 mat->stencil.dims[i] = dims[dim - i - 1]; /* copy the values in backwards */ 1906 mat->stencil.starts[i] = starts[dim - i - 1]; 1907 } 1908 mat->stencil.dims[dim] = dof; 1909 mat->stencil.starts[dim] = 0; 1910 mat->stencil.noc = (PetscBool)(dof == 1); 1911 PetscFunctionReturn(PETSC_SUCCESS); 1912 } 1913 1914 /*@C 1915 MatSetValuesBlocked - Inserts or adds a block of values into a matrix. 1916 1917 Not Collective 1918 1919 Input Parameters: 1920 + mat - the matrix 1921 . v - a logically two-dimensional array of values 1922 . m - the number of block rows 1923 . idxm - the global block indices 1924 . n - the number of block columns 1925 . idxn - the global block indices 1926 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values 1927 1928 Level: intermediate 1929 1930 Notes: 1931 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call 1932 MatXXXXSetPreallocation() or `MatSetUp()` before using this routine. 1933 1934 The `m` and `n` count the NUMBER of blocks in the row direction and column direction, 1935 NOT the total number of rows/columns; for example, if the block size is 2 and 1936 you are passing in values for rows 2,3,4,5 then m would be 2 (not 4). 1937 The values in idxm would be 1 2; that is the first index for each block divided by 1938 the block size. 1939 1940 You must call `MatSetBlockSize()` when constructing this matrix (before 1941 preallocating it). 1942 1943 By default the values, `v`, are row-oriented, so the layout of 1944 `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options. 1945 1946 Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES` 1947 options cannot be mixed without intervening calls to the assembly 1948 routines. 1949 1950 `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran 1951 as well as in C. 1952 1953 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1954 simply ignored. This allows easily inserting element stiffness matrices 1955 with homogeneous Dirchlet boundary conditions that you don't want represented 1956 in the matrix. 1957 1958 Each time an entry is set within a sparse matrix via `MatSetValues()`, 1959 internal searching must be done to determine where to place the 1960 data in the matrix storage space. By instead inserting blocks of 1961 entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is 1962 reduced. 1963 1964 Example: 1965 .vb 1966 Suppose m=n=2 and block size(bs) = 2 The array is 1967 1968 1 2 | 3 4 1969 5 6 | 7 8 1970 - - - | - - - 1971 9 10 | 11 12 1972 13 14 | 15 16 1973 1974 v[] should be passed in like 1975 v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] 1976 1977 If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then 1978 v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16] 1979 .ve 1980 1981 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()` 1982 @*/ 1983 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1984 { 1985 PetscFunctionBeginHot; 1986 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1987 PetscValidType(mat, 1); 1988 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1989 PetscValidIntPointer(idxm, 3); 1990 PetscValidIntPointer(idxn, 5); 1991 MatCheckPreallocated(mat, 1); 1992 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1993 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1994 if (PetscDefined(USE_DEBUG)) { 1995 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1996 PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 1997 } 1998 if (PetscDefined(USE_DEBUG)) { 1999 PetscInt rbs, cbs, M, N, i; 2000 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 2001 PetscCall(MatGetSize(mat, &M, &N)); 2002 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); 2003 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); 2004 } 2005 if (mat->assembled) { 2006 mat->was_assembled = PETSC_TRUE; 2007 mat->assembled = PETSC_FALSE; 2008 } 2009 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2010 if (mat->ops->setvaluesblocked) { 2011 PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv); 2012 } else { 2013 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn; 2014 PetscInt i, j, bs, cbs; 2015 2016 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 2017 if (m * bs + n * cbs <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2018 iidxm = buf; 2019 iidxn = buf + m * bs; 2020 } else { 2021 PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc)); 2022 iidxm = bufr; 2023 iidxn = bufc; 2024 } 2025 for (i = 0; i < m; i++) { 2026 for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j; 2027 } 2028 if (m != n || bs != cbs || idxm != idxn) { 2029 for (i = 0; i < n; i++) { 2030 for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j; 2031 } 2032 } else iidxn = iidxm; 2033 PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv)); 2034 PetscCall(PetscFree2(bufr, bufc)); 2035 } 2036 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2037 PetscFunctionReturn(PETSC_SUCCESS); 2038 } 2039 2040 /*@C 2041 MatGetValues - Gets a block of local values from a matrix. 2042 2043 Not Collective; can only return values that are owned by the give process 2044 2045 Input Parameters: 2046 + mat - the matrix 2047 . v - a logically two-dimensional array for storing the values 2048 . m - the number of rows 2049 . idxm - the global indices of the rows 2050 . n - the number of columns 2051 - idxn - the global indices of the columns 2052 2053 Level: advanced 2054 2055 Notes: 2056 The user must allocate space (m*n `PetscScalar`s) for the values, `v`. 2057 The values, `v`, are then returned in a row-oriented format, 2058 analogous to that used by default in `MatSetValues()`. 2059 2060 `MatGetValues()` uses 0-based row and column numbers in 2061 Fortran as well as in C. 2062 2063 `MatGetValues()` requires that the matrix has been assembled 2064 with `MatAssemblyBegin()`/`MatAssemblyEnd()`. Thus, calls to 2065 `MatSetValues()` and `MatGetValues()` CANNOT be made in succession 2066 without intermediate matrix assembly. 2067 2068 Negative row or column indices will be ignored and those locations in `v` will be 2069 left unchanged. 2070 2071 For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI rank. 2072 That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable 2073 from `MatGetOwnershipRange`(mat,&rstart,&rend). 2074 2075 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()` 2076 @*/ 2077 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) 2078 { 2079 PetscFunctionBegin; 2080 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2081 PetscValidType(mat, 1); 2082 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); 2083 PetscValidIntPointer(idxm, 3); 2084 PetscValidIntPointer(idxn, 5); 2085 PetscValidScalarPointer(v, 6); 2086 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2087 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2088 MatCheckPreallocated(mat, 1); 2089 2090 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2091 PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v); 2092 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2093 PetscFunctionReturn(PETSC_SUCCESS); 2094 } 2095 2096 /*@C 2097 MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices 2098 defined previously by `MatSetLocalToGlobalMapping()` 2099 2100 Not Collective 2101 2102 Input Parameters: 2103 + mat - the matrix 2104 . nrow - number of rows 2105 . irow - the row local indices 2106 . ncol - number of columns 2107 - icol - the column local indices 2108 2109 Output Parameter: 2110 . y - a logically two-dimensional array of values 2111 2112 Level: advanced 2113 2114 Notes: 2115 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine. 2116 2117 This routine can only return values that are owned by the requesting MPI rank. That is, for standard matrix formats, rows that, in the global numbering, 2118 are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can 2119 determine if the resulting global row associated with the local row r is owned by the requesting MPI rank by applying the `ISLocalToGlobalMapping` set 2120 with `MatSetLocalToGlobalMapping()`. 2121 2122 Developer Note: 2123 This is labelled with C so does not automatically generate Fortran stubs and interfaces 2124 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2125 2126 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2127 `MatSetValuesLocal()`, `MatGetValues()` 2128 @*/ 2129 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[]) 2130 { 2131 PetscFunctionBeginHot; 2132 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2133 PetscValidType(mat, 1); 2134 MatCheckPreallocated(mat, 1); 2135 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */ 2136 PetscValidIntPointer(irow, 3); 2137 PetscValidIntPointer(icol, 5); 2138 if (PetscDefined(USE_DEBUG)) { 2139 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2140 PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2141 } 2142 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2143 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2144 if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y); 2145 else { 2146 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm; 2147 if ((nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2148 irowm = buf; 2149 icolm = buf + nrow; 2150 } else { 2151 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2152 irowm = bufr; 2153 icolm = bufc; 2154 } 2155 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping())."); 2156 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping())."); 2157 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm)); 2158 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm)); 2159 PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y)); 2160 PetscCall(PetscFree2(bufr, bufc)); 2161 } 2162 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2163 PetscFunctionReturn(PETSC_SUCCESS); 2164 } 2165 2166 /*@ 2167 MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and 2168 the same size. Currently, this can only be called once and creates the given matrix. 2169 2170 Not Collective 2171 2172 Input Parameters: 2173 + mat - the matrix 2174 . nb - the number of blocks 2175 . bs - the number of rows (and columns) in each block 2176 . rows - a concatenation of the rows for each block 2177 - v - a concatenation of logically two-dimensional arrays of values 2178 2179 Level: advanced 2180 2181 Note: 2182 `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values 2183 2184 In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix. 2185 2186 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 2187 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()` 2188 @*/ 2189 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[]) 2190 { 2191 PetscFunctionBegin; 2192 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2193 PetscValidType(mat, 1); 2194 PetscValidIntPointer(rows, 4); 2195 PetscValidScalarPointer(v, 5); 2196 PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2197 2198 PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0)); 2199 if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v); 2200 else { 2201 for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES)); 2202 } 2203 PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0)); 2204 PetscFunctionReturn(PETSC_SUCCESS); 2205 } 2206 2207 /*@ 2208 MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by 2209 the routine `MatSetValuesLocal()` to allow users to insert matrix entries 2210 using a local (per-processor) numbering. 2211 2212 Not Collective 2213 2214 Input Parameters: 2215 + x - the matrix 2216 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()` 2217 - cmapping - column mapping 2218 2219 Level: intermediate 2220 2221 Note: 2222 If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix 2223 2224 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()` 2225 @*/ 2226 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping) 2227 { 2228 PetscFunctionBegin; 2229 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 2230 PetscValidType(x, 1); 2231 if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2); 2232 if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3); 2233 if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping); 2234 else { 2235 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping)); 2236 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping)); 2237 } 2238 PetscFunctionReturn(PETSC_SUCCESS); 2239 } 2240 2241 /*@ 2242 MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()` 2243 2244 Not Collective 2245 2246 Input Parameter: 2247 . A - the matrix 2248 2249 Output Parameters: 2250 + rmapping - row mapping 2251 - cmapping - column mapping 2252 2253 Level: advanced 2254 2255 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()` 2256 @*/ 2257 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping) 2258 { 2259 PetscFunctionBegin; 2260 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2261 PetscValidType(A, 1); 2262 if (rmapping) { 2263 PetscValidPointer(rmapping, 2); 2264 *rmapping = A->rmap->mapping; 2265 } 2266 if (cmapping) { 2267 PetscValidPointer(cmapping, 3); 2268 *cmapping = A->cmap->mapping; 2269 } 2270 PetscFunctionReturn(PETSC_SUCCESS); 2271 } 2272 2273 /*@ 2274 MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix 2275 2276 Logically Collective 2277 2278 Input Parameters: 2279 + A - the matrix 2280 . rmap - row layout 2281 - cmap - column layout 2282 2283 Level: advanced 2284 2285 Note: 2286 The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called. 2287 2288 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()` 2289 @*/ 2290 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap) 2291 { 2292 PetscFunctionBegin; 2293 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2294 PetscCall(PetscLayoutReference(rmap, &A->rmap)); 2295 PetscCall(PetscLayoutReference(cmap, &A->cmap)); 2296 PetscFunctionReturn(PETSC_SUCCESS); 2297 } 2298 2299 /*@ 2300 MatGetLayouts - Gets the `PetscLayout` objects for rows and columns 2301 2302 Not Collective 2303 2304 Input Parameter: 2305 . A - the matrix 2306 2307 Output Parameters: 2308 + rmap - row layout 2309 - cmap - column layout 2310 2311 Level: advanced 2312 2313 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()` 2314 @*/ 2315 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap) 2316 { 2317 PetscFunctionBegin; 2318 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2319 PetscValidType(A, 1); 2320 if (rmap) { 2321 PetscValidPointer(rmap, 2); 2322 *rmap = A->rmap; 2323 } 2324 if (cmap) { 2325 PetscValidPointer(cmap, 3); 2326 *cmap = A->cmap; 2327 } 2328 PetscFunctionReturn(PETSC_SUCCESS); 2329 } 2330 2331 /*@C 2332 MatSetValuesLocal - Inserts or adds values into certain locations of a matrix, 2333 using a local numbering of the nodes. 2334 2335 Not Collective 2336 2337 Input Parameters: 2338 + mat - the matrix 2339 . nrow - number of rows 2340 . irow - the row local indices 2341 . ncol - number of columns 2342 . icol - the column local indices 2343 . y - a logically two-dimensional array of values 2344 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2345 2346 Level: intermediate 2347 2348 Notes: 2349 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 2350 `MatSetUp()` before using this routine 2351 2352 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine 2353 2354 Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2355 options cannot be mixed without intervening calls to the assembly 2356 routines. 2357 2358 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2359 MUST be called after all calls to `MatSetValuesLocal()` have been completed. 2360 2361 Developer Note: 2362 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2363 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2364 2365 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2366 `MatGetValuesLocal()` 2367 @*/ 2368 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2369 { 2370 PetscFunctionBeginHot; 2371 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2372 PetscValidType(mat, 1); 2373 MatCheckPreallocated(mat, 1); 2374 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2375 PetscValidIntPointer(irow, 3); 2376 PetscValidIntPointer(icol, 5); 2377 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2378 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2379 if (PetscDefined(USE_DEBUG)) { 2380 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2381 PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2382 } 2383 2384 if (mat->assembled) { 2385 mat->was_assembled = PETSC_TRUE; 2386 mat->assembled = PETSC_FALSE; 2387 } 2388 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2389 if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv); 2390 else { 2391 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2392 const PetscInt *irowm, *icolm; 2393 2394 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2395 bufr = buf; 2396 bufc = buf + nrow; 2397 irowm = bufr; 2398 icolm = bufc; 2399 } else { 2400 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2401 irowm = bufr; 2402 icolm = bufc; 2403 } 2404 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr)); 2405 else irowm = irow; 2406 if (mat->cmap->mapping) { 2407 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2408 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc)); 2409 } else icolm = irowm; 2410 } else icolm = icol; 2411 PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv)); 2412 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2413 } 2414 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2415 PetscFunctionReturn(PETSC_SUCCESS); 2416 } 2417 2418 /*@C 2419 MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix, 2420 using a local ordering of the nodes a block at a time. 2421 2422 Not Collective 2423 2424 Input Parameters: 2425 + x - the matrix 2426 . nrow - number of rows 2427 . irow - the row local indices 2428 . ncol - number of columns 2429 . icol - the column local indices 2430 . y - a logically two-dimensional array of values 2431 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2432 2433 Level: intermediate 2434 2435 Notes: 2436 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 2437 `MatSetUp()` before using this routine 2438 2439 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()` 2440 before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the 2441 2442 Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2443 options cannot be mixed without intervening calls to the assembly 2444 routines. 2445 2446 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2447 MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed. 2448 2449 Developer Note: 2450 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2451 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2452 2453 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, 2454 `MatSetValuesLocal()`, `MatSetValuesBlocked()` 2455 @*/ 2456 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2457 { 2458 PetscFunctionBeginHot; 2459 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2460 PetscValidType(mat, 1); 2461 MatCheckPreallocated(mat, 1); 2462 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2463 PetscValidIntPointer(irow, 3); 2464 PetscValidIntPointer(icol, 5); 2465 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2466 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2467 if (PetscDefined(USE_DEBUG)) { 2468 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2469 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); 2470 } 2471 2472 if (mat->assembled) { 2473 mat->was_assembled = PETSC_TRUE; 2474 mat->assembled = PETSC_FALSE; 2475 } 2476 if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */ 2477 PetscInt irbs, rbs; 2478 PetscCall(MatGetBlockSizes(mat, &rbs, NULL)); 2479 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs)); 2480 PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs); 2481 } 2482 if (PetscUnlikelyDebug(mat->cmap->mapping)) { 2483 PetscInt icbs, cbs; 2484 PetscCall(MatGetBlockSizes(mat, NULL, &cbs)); 2485 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs)); 2486 PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs); 2487 } 2488 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2489 if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv); 2490 else { 2491 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2492 const PetscInt *irowm, *icolm; 2493 2494 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2495 bufr = buf; 2496 bufc = buf + nrow; 2497 irowm = bufr; 2498 icolm = bufc; 2499 } else { 2500 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2501 irowm = bufr; 2502 icolm = bufc; 2503 } 2504 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr)); 2505 else irowm = irow; 2506 if (mat->cmap->mapping) { 2507 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2508 PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc)); 2509 } else icolm = irowm; 2510 } else icolm = icol; 2511 PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv)); 2512 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2513 } 2514 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2515 PetscFunctionReturn(PETSC_SUCCESS); 2516 } 2517 2518 /*@ 2519 MatMultDiagonalBlock - Computes the matrix-vector product, y = Dx. Where D is defined by the inode or block structure of the diagonal 2520 2521 Collective 2522 2523 Input Parameters: 2524 + mat - the matrix 2525 - x - the vector to be multiplied 2526 2527 Output Parameter: 2528 . y - the result 2529 2530 Level: developer 2531 2532 Note: 2533 The vectors `x` and `y` cannot be the same. I.e., one cannot 2534 call `MatMultDiagonalBlock`(A,y,y). 2535 2536 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2537 @*/ 2538 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y) 2539 { 2540 PetscFunctionBegin; 2541 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2542 PetscValidType(mat, 1); 2543 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2544 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2545 2546 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2547 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2548 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2549 MatCheckPreallocated(mat, 1); 2550 2551 PetscUseTypeMethod(mat, multdiagonalblock, x, y); 2552 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2553 PetscFunctionReturn(PETSC_SUCCESS); 2554 } 2555 2556 /*@ 2557 MatMult - Computes the matrix-vector product, y = Ax. 2558 2559 Neighbor-wise Collective 2560 2561 Input Parameters: 2562 + mat - the matrix 2563 - x - the vector to be multiplied 2564 2565 Output Parameter: 2566 . y - the result 2567 2568 Level: beginner 2569 2570 Note: 2571 The vectors `x` and `y` cannot be the same. I.e., one cannot 2572 call `MatMult`(A,y,y). 2573 2574 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2575 @*/ 2576 PetscErrorCode MatMult(Mat mat, Vec x, Vec y) 2577 { 2578 PetscFunctionBegin; 2579 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2580 PetscValidType(mat, 1); 2581 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2582 VecCheckAssembled(x); 2583 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2584 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2585 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2586 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2587 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); 2588 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); 2589 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); 2590 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); 2591 PetscCall(VecSetErrorIfLocked(y, 3)); 2592 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2593 MatCheckPreallocated(mat, 1); 2594 2595 PetscCall(VecLockReadPush(x)); 2596 PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0)); 2597 PetscUseTypeMethod(mat, mult, x, y); 2598 PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0)); 2599 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2600 PetscCall(VecLockReadPop(x)); 2601 PetscFunctionReturn(PETSC_SUCCESS); 2602 } 2603 2604 /*@ 2605 MatMultTranspose - Computes matrix transpose times a vector y = A^T * x. 2606 2607 Neighbor-wise Collective 2608 2609 Input Parameters: 2610 + mat - the matrix 2611 - x - the vector to be multiplied 2612 2613 Output Parameter: 2614 . y - the result 2615 2616 Level: beginner 2617 2618 Notes: 2619 The vectors `x` and `y` cannot be the same. I.e., one cannot 2620 call `MatMultTranspose`(A,y,y). 2621 2622 For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple, 2623 use `MatMultHermitianTranspose()` 2624 2625 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()` 2626 @*/ 2627 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y) 2628 { 2629 PetscErrorCode (*op)(Mat, Vec, Vec) = NULL; 2630 2631 PetscFunctionBegin; 2632 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2633 PetscValidType(mat, 1); 2634 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2635 VecCheckAssembled(x); 2636 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2637 2638 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2639 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2640 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2641 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); 2642 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); 2643 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); 2644 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); 2645 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2646 MatCheckPreallocated(mat, 1); 2647 2648 if (!mat->ops->multtranspose) { 2649 if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult; 2650 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); 2651 } else op = mat->ops->multtranspose; 2652 PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0)); 2653 PetscCall(VecLockReadPush(x)); 2654 PetscCall((*op)(mat, x, y)); 2655 PetscCall(VecLockReadPop(x)); 2656 PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0)); 2657 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2658 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2659 PetscFunctionReturn(PETSC_SUCCESS); 2660 } 2661 2662 /*@ 2663 MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector. 2664 2665 Neighbor-wise Collective 2666 2667 Input Parameters: 2668 + mat - the matrix 2669 - x - the vector to be multilplied 2670 2671 Output Parameter: 2672 . y - the result 2673 2674 Level: beginner 2675 2676 Notes: 2677 The vectors `x` and `y` cannot be the same. I.e., one cannot 2678 call `MatMultHermitianTranspose`(A,y,y). 2679 2680 Also called the conjugate transpose, complex conjugate transpose, or adjoint. 2681 2682 For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical. 2683 2684 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()` 2685 @*/ 2686 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y) 2687 { 2688 PetscFunctionBegin; 2689 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2690 PetscValidType(mat, 1); 2691 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2692 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2693 2694 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2695 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2696 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2697 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); 2698 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); 2699 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); 2700 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); 2701 MatCheckPreallocated(mat, 1); 2702 2703 PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0)); 2704 #if defined(PETSC_USE_COMPLEX) 2705 if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) { 2706 PetscCall(VecLockReadPush(x)); 2707 if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y); 2708 else PetscUseTypeMethod(mat, mult, x, y); 2709 PetscCall(VecLockReadPop(x)); 2710 } else { 2711 Vec w; 2712 PetscCall(VecDuplicate(x, &w)); 2713 PetscCall(VecCopy(x, w)); 2714 PetscCall(VecConjugate(w)); 2715 PetscCall(MatMultTranspose(mat, w, y)); 2716 PetscCall(VecDestroy(&w)); 2717 PetscCall(VecConjugate(y)); 2718 } 2719 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2720 #else 2721 PetscCall(MatMultTranspose(mat, x, y)); 2722 #endif 2723 PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0)); 2724 PetscFunctionReturn(PETSC_SUCCESS); 2725 } 2726 2727 /*@ 2728 MatMultAdd - Computes v3 = v2 + A * v1. 2729 2730 Neighbor-wise Collective 2731 2732 Input Parameters: 2733 + mat - the matrix 2734 . v1 - the vector to be multiplied by `mat` 2735 - v2 - the vector to be added to the result 2736 2737 Output Parameter: 2738 . v3 - the result 2739 2740 Level: beginner 2741 2742 Note: 2743 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2744 call `MatMultAdd`(A,v1,v2,v1). 2745 2746 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()` 2747 @*/ 2748 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2749 { 2750 PetscFunctionBegin; 2751 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2752 PetscValidType(mat, 1); 2753 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2754 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2755 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2756 2757 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2758 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2759 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); 2760 /* 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); 2761 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); */ 2762 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); 2763 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); 2764 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2765 MatCheckPreallocated(mat, 1); 2766 2767 PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3)); 2768 PetscCall(VecLockReadPush(v1)); 2769 PetscUseTypeMethod(mat, multadd, v1, v2, v3); 2770 PetscCall(VecLockReadPop(v1)); 2771 PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3)); 2772 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2773 PetscFunctionReturn(PETSC_SUCCESS); 2774 } 2775 2776 /*@ 2777 MatMultTransposeAdd - Computes v3 = v2 + A' * v1. 2778 2779 Neighbor-wise Collective 2780 2781 Input Parameters: 2782 + mat - the matrix 2783 . v1 - the vector to be multiplied by the transpose of the matrix 2784 - v2 - the vector to be added to the result 2785 2786 Output Parameter: 2787 . v3 - the result 2788 2789 Level: beginner 2790 2791 Note: 2792 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2793 call `MatMultTransposeAdd`(A,v1,v2,v1). 2794 2795 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2796 @*/ 2797 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2798 { 2799 PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd; 2800 2801 PetscFunctionBegin; 2802 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2803 PetscValidType(mat, 1); 2804 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2805 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2806 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2807 2808 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2809 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2810 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); 2811 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); 2812 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); 2813 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2814 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2815 MatCheckPreallocated(mat, 1); 2816 2817 PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2818 PetscCall(VecLockReadPush(v1)); 2819 PetscCall((*op)(mat, v1, v2, v3)); 2820 PetscCall(VecLockReadPop(v1)); 2821 PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2822 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2823 PetscFunctionReturn(PETSC_SUCCESS); 2824 } 2825 2826 /*@ 2827 MatMultHermitianTransposeAdd - Computes v3 = v2 + A^H * v1. 2828 2829 Neighbor-wise Collective 2830 2831 Input Parameters: 2832 + mat - the matrix 2833 . v1 - the vector to be multiplied by the Hermitian transpose 2834 - v2 - the vector to be added to the result 2835 2836 Output Parameter: 2837 . v3 - the result 2838 2839 Level: beginner 2840 2841 Note: 2842 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2843 call `MatMultHermitianTransposeAdd`(A,v1,v2,v1). 2844 2845 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2846 @*/ 2847 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2848 { 2849 PetscFunctionBegin; 2850 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2851 PetscValidType(mat, 1); 2852 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2853 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2854 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2855 2856 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2857 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2858 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2859 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); 2860 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); 2861 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); 2862 MatCheckPreallocated(mat, 1); 2863 2864 PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2865 PetscCall(VecLockReadPush(v1)); 2866 if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3); 2867 else { 2868 Vec w, z; 2869 PetscCall(VecDuplicate(v1, &w)); 2870 PetscCall(VecCopy(v1, w)); 2871 PetscCall(VecConjugate(w)); 2872 PetscCall(VecDuplicate(v3, &z)); 2873 PetscCall(MatMultTranspose(mat, w, z)); 2874 PetscCall(VecDestroy(&w)); 2875 PetscCall(VecConjugate(z)); 2876 if (v2 != v3) { 2877 PetscCall(VecWAXPY(v3, 1.0, v2, z)); 2878 } else { 2879 PetscCall(VecAXPY(v3, 1.0, z)); 2880 } 2881 PetscCall(VecDestroy(&z)); 2882 } 2883 PetscCall(VecLockReadPop(v1)); 2884 PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2885 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2886 PetscFunctionReturn(PETSC_SUCCESS); 2887 } 2888 2889 /*@C 2890 MatGetFactorType - gets the type of factorization it is 2891 2892 Not Collective 2893 2894 Input Parameter: 2895 . mat - the matrix 2896 2897 Output Parameter: 2898 . t - the type, one of `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2899 2900 Level: intermediate 2901 2902 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2903 `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2904 @*/ 2905 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t) 2906 { 2907 PetscFunctionBegin; 2908 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2909 PetscValidType(mat, 1); 2910 PetscValidPointer(t, 2); 2911 *t = mat->factortype; 2912 PetscFunctionReturn(PETSC_SUCCESS); 2913 } 2914 2915 /*@C 2916 MatSetFactorType - sets the type of factorization it is 2917 2918 Logically Collective 2919 2920 Input Parameters: 2921 + mat - the matrix 2922 - 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` 2923 2924 Level: intermediate 2925 2926 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2927 `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2928 @*/ 2929 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t) 2930 { 2931 PetscFunctionBegin; 2932 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2933 PetscValidType(mat, 1); 2934 mat->factortype = t; 2935 PetscFunctionReturn(PETSC_SUCCESS); 2936 } 2937 2938 /*@C 2939 MatGetInfo - Returns information about matrix storage (number of 2940 nonzeros, memory, etc.). 2941 2942 Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag 2943 2944 Input Parameters: 2945 + mat - the matrix 2946 - 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) 2947 2948 Output Parameter: 2949 . info - matrix information context 2950 2951 Options Database Key: 2952 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT` 2953 2954 Notes: 2955 The `MatInfo` context contains a variety of matrix data, including 2956 number of nonzeros allocated and used, number of mallocs during 2957 matrix assembly, etc. Additional information for factored matrices 2958 is provided (such as the fill ratio, number of mallocs during 2959 factorization, etc.). 2960 2961 Example: 2962 See the file ${PETSC_DIR}/include/petscmat.h for a complete list of 2963 data within the MatInfo context. For example, 2964 .vb 2965 MatInfo info; 2966 Mat A; 2967 double mal, nz_a, nz_u; 2968 2969 MatGetInfo(A, MAT_LOCAL, &info); 2970 mal = info.mallocs; 2971 nz_a = info.nz_allocated; 2972 .ve 2973 2974 Fortran users should declare info as a double precision 2975 array of dimension `MAT_INFO_SIZE`, and then extract the parameters 2976 of interest. See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h 2977 a complete list of parameter names. 2978 .vb 2979 double precision info(MAT_INFO_SIZE) 2980 double precision mal, nz_a 2981 Mat A 2982 integer ierr 2983 2984 call MatGetInfo(A, MAT_LOCAL, info, ierr) 2985 mal = info(MAT_INFO_MALLOCS) 2986 nz_a = info(MAT_INFO_NZ_ALLOCATED) 2987 .ve 2988 2989 Level: intermediate 2990 2991 Developer Note: 2992 The Fortran interface is not autogenerated as the 2993 interface definition cannot be generated correctly [due to `MatInfo` argument] 2994 2995 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()` 2996 @*/ 2997 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info) 2998 { 2999 PetscFunctionBegin; 3000 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3001 PetscValidType(mat, 1); 3002 PetscValidPointer(info, 3); 3003 MatCheckPreallocated(mat, 1); 3004 PetscUseTypeMethod(mat, getinfo, flag, info); 3005 PetscFunctionReturn(PETSC_SUCCESS); 3006 } 3007 3008 /* 3009 This is used by external packages where it is not easy to get the info from the actual 3010 matrix factorization. 3011 */ 3012 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info) 3013 { 3014 PetscFunctionBegin; 3015 PetscCall(PetscMemzero(info, sizeof(MatInfo))); 3016 PetscFunctionReturn(PETSC_SUCCESS); 3017 } 3018 3019 /*@C 3020 MatLUFactor - Performs in-place LU factorization of matrix. 3021 3022 Collective 3023 3024 Input Parameters: 3025 + mat - the matrix 3026 . row - row permutation 3027 . col - column permutation 3028 - info - options for factorization, includes 3029 .vb 3030 fill - expected fill as ratio of original fill. 3031 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3032 Run with the option -info to determine an optimal value to use 3033 .ve 3034 Level: developer 3035 3036 Notes: 3037 Most users should employ the `KSP` interface for linear solvers 3038 instead of working directly with matrix algebra routines such as this. 3039 See, e.g., `KSPCreate()`. 3040 3041 This changes the state of the matrix to a factored matrix; it cannot be used 3042 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3043 3044 This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()` 3045 when not using `KSP`. 3046 3047 Developer Note: 3048 The Fortran interface is not autogenerated as the 3049 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3050 3051 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, 3052 `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3053 @*/ 3054 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3055 { 3056 MatFactorInfo tinfo; 3057 3058 PetscFunctionBegin; 3059 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3060 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3061 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3062 if (info) PetscValidPointer(info, 4); 3063 PetscValidType(mat, 1); 3064 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3065 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3066 MatCheckPreallocated(mat, 1); 3067 if (!info) { 3068 PetscCall(MatFactorInfoInitialize(&tinfo)); 3069 info = &tinfo; 3070 } 3071 3072 PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0)); 3073 PetscUseTypeMethod(mat, lufactor, row, col, info); 3074 PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0)); 3075 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3076 PetscFunctionReturn(PETSC_SUCCESS); 3077 } 3078 3079 /*@C 3080 MatILUFactor - Performs in-place ILU factorization of matrix. 3081 3082 Collective 3083 3084 Input Parameters: 3085 + mat - the matrix 3086 . row - row permutation 3087 . col - column permutation 3088 - info - structure containing 3089 .vb 3090 levels - number of levels of fill. 3091 expected fill - as ratio of original fill. 3092 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 3093 missing diagonal entries) 3094 .ve 3095 3096 Level: developer 3097 3098 Notes: 3099 Most users should employ the `KSP` interface for linear solvers 3100 instead of working directly with matrix algebra routines such as this. 3101 See, e.g., `KSPCreate()`. 3102 3103 Probably really in-place only when level of fill is zero, otherwise allocates 3104 new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()` 3105 when not using `KSP`. 3106 3107 Developer Note: 3108 The Fortran interface is not autogenerated as the 3109 interface definition cannot be generated correctly [due to MatFactorInfo] 3110 3111 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 3112 @*/ 3113 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3114 { 3115 PetscFunctionBegin; 3116 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3117 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3118 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3119 PetscValidPointer(info, 4); 3120 PetscValidType(mat, 1); 3121 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 3122 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3123 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3124 MatCheckPreallocated(mat, 1); 3125 3126 PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0)); 3127 PetscUseTypeMethod(mat, ilufactor, row, col, info); 3128 PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0)); 3129 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3130 PetscFunctionReturn(PETSC_SUCCESS); 3131 } 3132 3133 /*@C 3134 MatLUFactorSymbolic - Performs symbolic LU factorization of matrix. 3135 Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`. 3136 3137 Collective 3138 3139 Input Parameters: 3140 + fact - the factor matrix obtained with `MatGetFactor()` 3141 . mat - the matrix 3142 . row - the row permutation 3143 . col - the column permutation 3144 - info - options for factorization, includes 3145 .vb 3146 fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use 3147 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3148 .ve 3149 3150 Level: developer 3151 3152 Notes: 3153 See [Matrix Factorization](sec_matfactor) for additional information about factorizations 3154 3155 Most users should employ the simplified `KSP` interface for linear solvers 3156 instead of working directly with matrix algebra routines such as this. 3157 See, e.g., `KSPCreate()`. 3158 3159 Developer Note: 3160 The Fortran interface is not autogenerated as the 3161 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3162 3163 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3164 @*/ 3165 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 3166 { 3167 MatFactorInfo tinfo; 3168 3169 PetscFunctionBegin; 3170 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3171 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3172 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 3173 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 3174 if (info) PetscValidPointer(info, 5); 3175 PetscValidType(fact, 1); 3176 PetscValidType(mat, 2); 3177 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3178 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3179 MatCheckPreallocated(mat, 2); 3180 if (!info) { 3181 PetscCall(MatFactorInfoInitialize(&tinfo)); 3182 info = &tinfo; 3183 } 3184 3185 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0)); 3186 PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info); 3187 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0)); 3188 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3189 PetscFunctionReturn(PETSC_SUCCESS); 3190 } 3191 3192 /*@C 3193 MatLUFactorNumeric - Performs numeric LU factorization of a matrix. 3194 Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`. 3195 3196 Collective 3197 3198 Input Parameters: 3199 + fact - the factor matrix obtained with `MatGetFactor()` 3200 . mat - the matrix 3201 - info - options for factorization 3202 3203 Level: developer 3204 3205 Notes: 3206 See `MatLUFactor()` for in-place factorization. See 3207 `MatCholeskyFactorNumeric()` for the symmetric, positive definite case. 3208 3209 Most users should employ the `KSP` interface for linear solvers 3210 instead of working directly with matrix algebra routines such as this. 3211 See, e.g., `KSPCreate()`. 3212 3213 Developer Note: 3214 The Fortran interface is not autogenerated as the 3215 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3216 3217 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()` 3218 @*/ 3219 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3220 { 3221 MatFactorInfo tinfo; 3222 3223 PetscFunctionBegin; 3224 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3225 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3226 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3227 PetscValidType(fact, 1); 3228 PetscValidType(mat, 2); 3229 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3230 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, 3231 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3232 3233 MatCheckPreallocated(mat, 2); 3234 if (!info) { 3235 PetscCall(MatFactorInfoInitialize(&tinfo)); 3236 info = &tinfo; 3237 } 3238 3239 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3240 else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0)); 3241 PetscUseTypeMethod(fact, lufactornumeric, mat, info); 3242 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3243 else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0)); 3244 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3245 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3246 PetscFunctionReturn(PETSC_SUCCESS); 3247 } 3248 3249 /*@C 3250 MatCholeskyFactor - Performs in-place Cholesky factorization of a 3251 symmetric matrix. 3252 3253 Collective 3254 3255 Input Parameters: 3256 + mat - the matrix 3257 . perm - row and column permutations 3258 - f - expected fill as ratio of original fill 3259 3260 Level: developer 3261 3262 Notes: 3263 See `MatLUFactor()` for the nonsymmetric case. See also `MatGetFactor()`, 3264 `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`. 3265 3266 Most users should employ the `KSP` interface for linear solvers 3267 instead of working directly with matrix algebra routines such as this. 3268 See, e.g., `KSPCreate()`. 3269 3270 Developer Note: 3271 The Fortran interface is not autogenerated as the 3272 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3273 3274 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()` 3275 `MatGetOrdering()` 3276 @*/ 3277 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info) 3278 { 3279 MatFactorInfo tinfo; 3280 3281 PetscFunctionBegin; 3282 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3283 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2); 3284 if (info) PetscValidPointer(info, 3); 3285 PetscValidType(mat, 1); 3286 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3287 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3288 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3289 MatCheckPreallocated(mat, 1); 3290 if (!info) { 3291 PetscCall(MatFactorInfoInitialize(&tinfo)); 3292 info = &tinfo; 3293 } 3294 3295 PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0)); 3296 PetscUseTypeMethod(mat, choleskyfactor, perm, info); 3297 PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0)); 3298 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3299 PetscFunctionReturn(PETSC_SUCCESS); 3300 } 3301 3302 /*@C 3303 MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization 3304 of a symmetric matrix. 3305 3306 Collective 3307 3308 Input Parameters: 3309 + fact - the factor matrix obtained with `MatGetFactor()` 3310 . mat - the matrix 3311 . perm - row and column permutations 3312 - info - options for factorization, includes 3313 .vb 3314 fill - expected fill as ratio of original fill. 3315 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3316 Run with the option -info to determine an optimal value to use 3317 .ve 3318 3319 Level: developer 3320 3321 Notes: 3322 See `MatLUFactorSymbolic()` for the nonsymmetric case. See also 3323 `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`. 3324 3325 Most users should employ the `KSP` interface for linear solvers 3326 instead of working directly with matrix algebra routines such as this. 3327 See, e.g., `KSPCreate()`. 3328 3329 Developer Note: 3330 The Fortran interface is not autogenerated as the 3331 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3332 3333 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()` 3334 `MatGetOrdering()` 3335 @*/ 3336 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 3337 { 3338 MatFactorInfo tinfo; 3339 3340 PetscFunctionBegin; 3341 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3342 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3343 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 3344 if (info) PetscValidPointer(info, 4); 3345 PetscValidType(fact, 1); 3346 PetscValidType(mat, 2); 3347 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3348 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3349 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3350 MatCheckPreallocated(mat, 2); 3351 if (!info) { 3352 PetscCall(MatFactorInfoInitialize(&tinfo)); 3353 info = &tinfo; 3354 } 3355 3356 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3357 PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info); 3358 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3359 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3360 PetscFunctionReturn(PETSC_SUCCESS); 3361 } 3362 3363 /*@C 3364 MatCholeskyFactorNumeric - Performs numeric Cholesky factorization 3365 of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and 3366 `MatCholeskyFactorSymbolic()`. 3367 3368 Collective 3369 3370 Input Parameters: 3371 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored 3372 . mat - the initial matrix that is to be factored 3373 - info - options for factorization 3374 3375 Level: developer 3376 3377 Note: 3378 Most users should employ the `KSP` interface for linear solvers 3379 instead of working directly with matrix algebra routines such as this. 3380 See, e.g., `KSPCreate()`. 3381 3382 Developer Note: 3383 The Fortran interface is not autogenerated as the 3384 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3385 3386 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()` 3387 @*/ 3388 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3389 { 3390 MatFactorInfo tinfo; 3391 3392 PetscFunctionBegin; 3393 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3394 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3395 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3396 PetscValidType(fact, 1); 3397 PetscValidType(mat, 2); 3398 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3399 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, 3400 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3401 MatCheckPreallocated(mat, 2); 3402 if (!info) { 3403 PetscCall(MatFactorInfoInitialize(&tinfo)); 3404 info = &tinfo; 3405 } 3406 3407 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3408 else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0)); 3409 PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info); 3410 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3411 else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0)); 3412 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3413 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3414 PetscFunctionReturn(PETSC_SUCCESS); 3415 } 3416 3417 /*@ 3418 MatQRFactor - Performs in-place QR factorization of matrix. 3419 3420 Collective 3421 3422 Input Parameters: 3423 + mat - the matrix 3424 . col - column permutation 3425 - info - options for factorization, includes 3426 .vb 3427 fill - expected fill as ratio of original fill. 3428 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3429 Run with the option -info to determine an optimal value to use 3430 .ve 3431 3432 Level: developer 3433 3434 Notes: 3435 Most users should employ the `KSP` interface for linear solvers 3436 instead of working directly with matrix algebra routines such as this. 3437 See, e.g., `KSPCreate()`. 3438 3439 This changes the state of the matrix to a factored matrix; it cannot be used 3440 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3441 3442 Developer Note: 3443 The Fortran interface is not autogenerated as the 3444 interface definition cannot be generated correctly [due to MatFactorInfo] 3445 3446 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`, 3447 `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3448 @*/ 3449 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info) 3450 { 3451 PetscFunctionBegin; 3452 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3453 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2); 3454 if (info) PetscValidPointer(info, 3); 3455 PetscValidType(mat, 1); 3456 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3457 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3458 MatCheckPreallocated(mat, 1); 3459 PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0)); 3460 PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info)); 3461 PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0)); 3462 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3463 PetscFunctionReturn(PETSC_SUCCESS); 3464 } 3465 3466 /*@ 3467 MatQRFactorSymbolic - Performs symbolic QR factorization of matrix. 3468 Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`. 3469 3470 Collective 3471 3472 Input Parameters: 3473 + fact - the factor matrix obtained with `MatGetFactor()` 3474 . mat - the matrix 3475 . col - column permutation 3476 - info - options for factorization, includes 3477 .vb 3478 fill - expected fill as ratio of original fill. 3479 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3480 Run with the option -info to determine an optimal value to use 3481 .ve 3482 3483 Level: developer 3484 3485 Note: 3486 Most users should employ the `KSP` interface for linear solvers 3487 instead of working directly with matrix algebra routines such as this. 3488 See, e.g., `KSPCreate()`. 3489 3490 Developer Note: 3491 The Fortran interface is not autogenerated as the 3492 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3493 3494 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3495 @*/ 3496 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info) 3497 { 3498 MatFactorInfo tinfo; 3499 3500 PetscFunctionBegin; 3501 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3502 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3503 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3504 if (info) PetscValidPointer(info, 4); 3505 PetscValidType(fact, 1); 3506 PetscValidType(mat, 2); 3507 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3508 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3509 MatCheckPreallocated(mat, 2); 3510 if (!info) { 3511 PetscCall(MatFactorInfoInitialize(&tinfo)); 3512 info = &tinfo; 3513 } 3514 3515 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3516 PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info)); 3517 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3518 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3519 PetscFunctionReturn(PETSC_SUCCESS); 3520 } 3521 3522 /*@ 3523 MatQRFactorNumeric - Performs numeric QR factorization of a matrix. 3524 Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`. 3525 3526 Collective 3527 3528 Input Parameters: 3529 + fact - the factor matrix obtained with `MatGetFactor()` 3530 . mat - the matrix 3531 - info - options for factorization 3532 3533 Level: developer 3534 3535 Notes: 3536 See `MatQRFactor()` for in-place factorization. 3537 3538 Most users should employ the `KSP` interface for linear solvers 3539 instead of working directly with matrix algebra routines such as this. 3540 See, e.g., `KSPCreate()`. 3541 3542 Developer Note: 3543 The Fortran interface is not autogenerated as the 3544 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3545 3546 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()` 3547 @*/ 3548 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3549 { 3550 MatFactorInfo tinfo; 3551 3552 PetscFunctionBegin; 3553 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3554 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3555 PetscValidType(fact, 1); 3556 PetscValidType(mat, 2); 3557 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3558 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, 3559 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3560 3561 MatCheckPreallocated(mat, 2); 3562 if (!info) { 3563 PetscCall(MatFactorInfoInitialize(&tinfo)); 3564 info = &tinfo; 3565 } 3566 3567 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3568 else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0)); 3569 PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info)); 3570 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3571 else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0)); 3572 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3573 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3574 PetscFunctionReturn(PETSC_SUCCESS); 3575 } 3576 3577 /*@ 3578 MatSolve - Solves A x = b, given a factored matrix. 3579 3580 Neighbor-wise Collective 3581 3582 Input Parameters: 3583 + mat - the factored matrix 3584 - b - the right-hand-side vector 3585 3586 Output Parameter: 3587 . x - the result vector 3588 3589 Level: developer 3590 3591 Notes: 3592 The vectors `b` and `x` cannot be the same. I.e., one cannot 3593 call `MatSolve`(A,x,x). 3594 3595 Most users should employ the `KSP` interface for linear solvers 3596 instead of working directly with matrix algebra routines such as this. 3597 See, e.g., `KSPCreate()`. 3598 3599 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3600 @*/ 3601 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x) 3602 { 3603 PetscFunctionBegin; 3604 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3605 PetscValidType(mat, 1); 3606 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3607 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3608 PetscCheckSameComm(mat, 1, b, 2); 3609 PetscCheckSameComm(mat, 1, x, 3); 3610 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3611 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); 3612 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); 3613 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); 3614 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3615 MatCheckPreallocated(mat, 1); 3616 3617 PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0)); 3618 if (mat->factorerrortype) { 3619 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3620 PetscCall(VecSetInf(x)); 3621 } else PetscUseTypeMethod(mat, solve, b, x); 3622 PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0)); 3623 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3624 PetscFunctionReturn(PETSC_SUCCESS); 3625 } 3626 3627 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans) 3628 { 3629 Vec b, x; 3630 PetscInt N, i; 3631 PetscErrorCode (*f)(Mat, Vec, Vec); 3632 PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE; 3633 3634 PetscFunctionBegin; 3635 if (A->factorerrortype) { 3636 PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype)); 3637 PetscCall(MatSetInf(X)); 3638 PetscFunctionReturn(PETSC_SUCCESS); 3639 } 3640 f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose; 3641 PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 3642 PetscCall(MatBoundToCPU(A, &Abound)); 3643 if (!Abound) { 3644 PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3645 PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3646 } 3647 #if PetscDefined(HAVE_CUDA) 3648 if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B)); 3649 if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X)); 3650 #elif PetscDefined(HAVE_HIP) 3651 if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B)); 3652 if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X)); 3653 #endif 3654 PetscCall(MatGetSize(B, NULL, &N)); 3655 for (i = 0; i < N; i++) { 3656 PetscCall(MatDenseGetColumnVecRead(B, i, &b)); 3657 PetscCall(MatDenseGetColumnVecWrite(X, i, &x)); 3658 PetscCall((*f)(A, b, x)); 3659 PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x)); 3660 PetscCall(MatDenseRestoreColumnVecRead(B, i, &b)); 3661 } 3662 if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B)); 3663 if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X)); 3664 PetscFunctionReturn(PETSC_SUCCESS); 3665 } 3666 3667 /*@ 3668 MatMatSolve - Solves A X = B, given a factored matrix. 3669 3670 Neighbor-wise Collective 3671 3672 Input Parameters: 3673 + A - the factored matrix 3674 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS) 3675 3676 Output Parameter: 3677 . X - the result matrix (dense matrix) 3678 3679 Level: developer 3680 3681 Note: 3682 If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`; 3683 otherwise, `B` and `X` cannot be the same. 3684 3685 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3686 @*/ 3687 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X) 3688 { 3689 PetscFunctionBegin; 3690 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3691 PetscValidType(A, 1); 3692 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3693 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3694 PetscCheckSameComm(A, 1, B, 2); 3695 PetscCheckSameComm(A, 1, X, 3); 3696 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); 3697 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); 3698 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"); 3699 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3700 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3701 MatCheckPreallocated(A, 1); 3702 3703 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3704 if (!A->ops->matsolve) { 3705 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name)); 3706 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE)); 3707 } else PetscUseTypeMethod(A, matsolve, B, X); 3708 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3709 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3710 PetscFunctionReturn(PETSC_SUCCESS); 3711 } 3712 3713 /*@ 3714 MatMatSolveTranspose - Solves A^T X = B, given a factored matrix. 3715 3716 Neighbor-wise Collective 3717 3718 Input Parameters: 3719 + A - the factored matrix 3720 - B - the right-hand-side matrix (`MATDENSE` matrix) 3721 3722 Output Parameter: 3723 . X - the result matrix (dense matrix) 3724 3725 Level: developer 3726 3727 Note: 3728 The matrices `B` and `X` cannot be the same. I.e., one cannot 3729 call `MatMatSolveTranspose`(A,X,X). 3730 3731 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()` 3732 @*/ 3733 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X) 3734 { 3735 PetscFunctionBegin; 3736 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3737 PetscValidType(A, 1); 3738 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3739 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3740 PetscCheckSameComm(A, 1, B, 2); 3741 PetscCheckSameComm(A, 1, X, 3); 3742 PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3743 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); 3744 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); 3745 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); 3746 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"); 3747 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3748 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3749 MatCheckPreallocated(A, 1); 3750 3751 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3752 if (!A->ops->matsolvetranspose) { 3753 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name)); 3754 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE)); 3755 } else PetscUseTypeMethod(A, matsolvetranspose, B, X); 3756 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3757 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3758 PetscFunctionReturn(PETSC_SUCCESS); 3759 } 3760 3761 /*@ 3762 MatMatTransposeSolve - Solves A X = B^T, given a factored matrix. 3763 3764 Neighbor-wise Collective 3765 3766 Input Parameters: 3767 + A - the factored matrix 3768 - Bt - the transpose of right-hand-side matrix as a `MATDENSE` 3769 3770 Output Parameter: 3771 . X - the result matrix (dense matrix) 3772 3773 Level: developer 3774 3775 Note: 3776 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 3777 format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`. 3778 3779 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3780 @*/ 3781 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X) 3782 { 3783 PetscFunctionBegin; 3784 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3785 PetscValidType(A, 1); 3786 PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2); 3787 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3788 PetscCheckSameComm(A, 1, Bt, 2); 3789 PetscCheckSameComm(A, 1, X, 3); 3790 3791 PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3792 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); 3793 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); 3794 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"); 3795 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3796 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3797 MatCheckPreallocated(A, 1); 3798 3799 PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0)); 3800 PetscUseTypeMethod(A, mattransposesolve, Bt, X); 3801 PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0)); 3802 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3803 PetscFunctionReturn(PETSC_SUCCESS); 3804 } 3805 3806 /*@ 3807 MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or 3808 U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U, 3809 3810 Neighbor-wise Collective 3811 3812 Input Parameters: 3813 + mat - the factored matrix 3814 - b - the right-hand-side vector 3815 3816 Output Parameter: 3817 . x - the result vector 3818 3819 Level: developer 3820 3821 Notes: 3822 `MatSolve()` should be used for most applications, as it performs 3823 a forward solve followed by a backward solve. 3824 3825 The vectors `b` and `x` cannot be the same, i.e., one cannot 3826 call `MatForwardSolve`(A,x,x). 3827 3828 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3829 the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet. 3830 `MatForwardSolve()` solves U^T*D y = b, and 3831 `MatBackwardSolve()` solves U x = y. 3832 Thus they do not provide a symmetric preconditioner. 3833 3834 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatBackwardSolve()` 3835 @*/ 3836 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x) 3837 { 3838 PetscFunctionBegin; 3839 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3840 PetscValidType(mat, 1); 3841 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3842 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3843 PetscCheckSameComm(mat, 1, b, 2); 3844 PetscCheckSameComm(mat, 1, x, 3); 3845 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3846 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); 3847 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); 3848 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); 3849 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3850 MatCheckPreallocated(mat, 1); 3851 3852 PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0)); 3853 PetscUseTypeMethod(mat, forwardsolve, b, x); 3854 PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0)); 3855 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3856 PetscFunctionReturn(PETSC_SUCCESS); 3857 } 3858 3859 /*@ 3860 MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU. 3861 D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U, 3862 3863 Neighbor-wise Collective 3864 3865 Input Parameters: 3866 + mat - the factored matrix 3867 - b - the right-hand-side vector 3868 3869 Output Parameter: 3870 . x - the result vector 3871 3872 Level: developer 3873 3874 Notes: 3875 `MatSolve()` should be used for most applications, as it performs 3876 a forward solve followed by a backward solve. 3877 3878 The vectors `b` and `x` cannot be the same. I.e., one cannot 3879 call `MatBackwardSolve`(A,x,x). 3880 3881 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3882 the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet. 3883 `MatForwardSolve()` solves U^T*D y = b, and 3884 `MatBackwardSolve()` solves U x = y. 3885 Thus they do not provide a symmetric preconditioner. 3886 3887 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatForwardSolve()` 3888 @*/ 3889 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x) 3890 { 3891 PetscFunctionBegin; 3892 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3893 PetscValidType(mat, 1); 3894 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3895 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3896 PetscCheckSameComm(mat, 1, b, 2); 3897 PetscCheckSameComm(mat, 1, x, 3); 3898 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3899 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); 3900 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); 3901 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); 3902 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3903 MatCheckPreallocated(mat, 1); 3904 3905 PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0)); 3906 PetscUseTypeMethod(mat, backwardsolve, b, x); 3907 PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0)); 3908 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3909 PetscFunctionReturn(PETSC_SUCCESS); 3910 } 3911 3912 /*@ 3913 MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix. 3914 3915 Neighbor-wise Collective 3916 3917 Input Parameters: 3918 + mat - the factored matrix 3919 . b - the right-hand-side vector 3920 - y - the vector to be added to 3921 3922 Output Parameter: 3923 . x - the result vector 3924 3925 Level: developer 3926 3927 Note: 3928 The vectors `b` and `x` cannot be the same. I.e., one cannot 3929 call `MatSolveAdd`(A,x,y,x). 3930 3931 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3932 @*/ 3933 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x) 3934 { 3935 PetscScalar one = 1.0; 3936 Vec tmp; 3937 3938 PetscFunctionBegin; 3939 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3940 PetscValidType(mat, 1); 3941 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 3942 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3943 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 3944 PetscCheckSameComm(mat, 1, b, 2); 3945 PetscCheckSameComm(mat, 1, y, 3); 3946 PetscCheckSameComm(mat, 1, x, 4); 3947 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3948 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); 3949 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); 3950 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); 3951 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); 3952 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); 3953 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3954 MatCheckPreallocated(mat, 1); 3955 3956 PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y)); 3957 if (mat->factorerrortype) { 3958 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3959 PetscCall(VecSetInf(x)); 3960 } else if (mat->ops->solveadd) { 3961 PetscUseTypeMethod(mat, solveadd, b, y, x); 3962 } else { 3963 /* do the solve then the add manually */ 3964 if (x != y) { 3965 PetscCall(MatSolve(mat, b, x)); 3966 PetscCall(VecAXPY(x, one, y)); 3967 } else { 3968 PetscCall(VecDuplicate(x, &tmp)); 3969 PetscCall(VecCopy(x, tmp)); 3970 PetscCall(MatSolve(mat, b, x)); 3971 PetscCall(VecAXPY(x, one, tmp)); 3972 PetscCall(VecDestroy(&tmp)); 3973 } 3974 } 3975 PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y)); 3976 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3977 PetscFunctionReturn(PETSC_SUCCESS); 3978 } 3979 3980 /*@ 3981 MatSolveTranspose - Solves A' x = b, given a factored matrix. 3982 3983 Neighbor-wise Collective 3984 3985 Input Parameters: 3986 + mat - the factored matrix 3987 - b - the right-hand-side vector 3988 3989 Output Parameter: 3990 . x - the result vector 3991 3992 Level: developer 3993 3994 Notes: 3995 The vectors `b` and `x` cannot be the same. I.e., one cannot 3996 call `MatSolveTranspose`(A,x,x). 3997 3998 Most users should employ the `KSP` interface for linear solvers 3999 instead of working directly with matrix algebra routines such as this. 4000 See, e.g., `KSPCreate()`. 4001 4002 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()` 4003 @*/ 4004 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x) 4005 { 4006 PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose; 4007 4008 PetscFunctionBegin; 4009 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4010 PetscValidType(mat, 1); 4011 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4012 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 4013 PetscCheckSameComm(mat, 1, b, 2); 4014 PetscCheckSameComm(mat, 1, x, 3); 4015 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4016 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); 4017 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); 4018 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4019 MatCheckPreallocated(mat, 1); 4020 PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0)); 4021 if (mat->factorerrortype) { 4022 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4023 PetscCall(VecSetInf(x)); 4024 } else { 4025 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name); 4026 PetscCall((*f)(mat, b, x)); 4027 } 4028 PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0)); 4029 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4030 PetscFunctionReturn(PETSC_SUCCESS); 4031 } 4032 4033 /*@ 4034 MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a 4035 factored matrix. 4036 4037 Neighbor-wise Collective 4038 4039 Input Parameters: 4040 + mat - the factored matrix 4041 . b - the right-hand-side vector 4042 - y - the vector to be added to 4043 4044 Output Parameter: 4045 . x - the result vector 4046 4047 Level: developer 4048 4049 Note: 4050 The vectors `b` and `x` cannot be the same. I.e., one cannot 4051 call `MatSolveTransposeAdd`(A,x,y,x). 4052 4053 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()` 4054 @*/ 4055 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x) 4056 { 4057 PetscScalar one = 1.0; 4058 Vec tmp; 4059 PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd; 4060 4061 PetscFunctionBegin; 4062 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4063 PetscValidType(mat, 1); 4064 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4065 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4066 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4067 PetscCheckSameComm(mat, 1, b, 2); 4068 PetscCheckSameComm(mat, 1, y, 3); 4069 PetscCheckSameComm(mat, 1, x, 4); 4070 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4071 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); 4072 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); 4073 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); 4074 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); 4075 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4076 MatCheckPreallocated(mat, 1); 4077 4078 PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y)); 4079 if (mat->factorerrortype) { 4080 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4081 PetscCall(VecSetInf(x)); 4082 } else if (f) { 4083 PetscCall((*f)(mat, b, y, x)); 4084 } else { 4085 /* do the solve then the add manually */ 4086 if (x != y) { 4087 PetscCall(MatSolveTranspose(mat, b, x)); 4088 PetscCall(VecAXPY(x, one, y)); 4089 } else { 4090 PetscCall(VecDuplicate(x, &tmp)); 4091 PetscCall(VecCopy(x, tmp)); 4092 PetscCall(MatSolveTranspose(mat, b, x)); 4093 PetscCall(VecAXPY(x, one, tmp)); 4094 PetscCall(VecDestroy(&tmp)); 4095 } 4096 } 4097 PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y)); 4098 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4099 PetscFunctionReturn(PETSC_SUCCESS); 4100 } 4101 4102 /*@ 4103 MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps. 4104 4105 Neighbor-wise Collective 4106 4107 Input Parameters: 4108 + mat - the matrix 4109 . b - the right hand side 4110 . omega - the relaxation factor 4111 . flag - flag indicating the type of SOR (see below) 4112 . shift - diagonal shift 4113 . its - the number of iterations 4114 - lits - the number of local iterations 4115 4116 Output Parameter: 4117 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess) 4118 4119 SOR Flags: 4120 + `SOR_FORWARD_SWEEP` - forward SOR 4121 . `SOR_BACKWARD_SWEEP` - backward SOR 4122 . `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR) 4123 . `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR 4124 . `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR 4125 . `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR 4126 . `SOR_EISENSTAT` - SOR with Eisenstat trick 4127 . `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies 4128 upper/lower triangular part of matrix to 4129 vector (with omega) 4130 - `SOR_ZERO_INITIAL_GUESS` - zero initial guess 4131 4132 Level: developer 4133 4134 Notes: 4135 `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and 4136 `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings 4137 on each processor. 4138 4139 Application programmers will not generally use `MatSOR()` directly, 4140 but instead will employ the `KSP`/`PC` interface. 4141 4142 For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing 4143 4144 Most users should employ the `KSP` interface for linear solvers 4145 instead of working directly with matrix algebra routines such as this. 4146 See, e.g., `KSPCreate()`. 4147 4148 Vectors `x` and `b` CANNOT be the same 4149 4150 The flags are implemented as bitwise inclusive or operations. 4151 For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`) 4152 to specify a zero initial guess for SSOR. 4153 4154 Developer Note: 4155 We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes 4156 4157 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()` 4158 @*/ 4159 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x) 4160 { 4161 PetscFunctionBegin; 4162 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4163 PetscValidType(mat, 1); 4164 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4165 PetscValidHeaderSpecific(x, VEC_CLASSID, 8); 4166 PetscCheckSameComm(mat, 1, b, 2); 4167 PetscCheckSameComm(mat, 1, x, 8); 4168 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4169 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4170 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); 4171 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); 4172 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); 4173 PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its); 4174 PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits); 4175 PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same"); 4176 4177 MatCheckPreallocated(mat, 1); 4178 PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0)); 4179 PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x); 4180 PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0)); 4181 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4182 PetscFunctionReturn(PETSC_SUCCESS); 4183 } 4184 4185 /* 4186 Default matrix copy routine. 4187 */ 4188 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str) 4189 { 4190 PetscInt i, rstart = 0, rend = 0, nz; 4191 const PetscInt *cwork; 4192 const PetscScalar *vwork; 4193 4194 PetscFunctionBegin; 4195 if (B->assembled) PetscCall(MatZeroEntries(B)); 4196 if (str == SAME_NONZERO_PATTERN) { 4197 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 4198 for (i = rstart; i < rend; i++) { 4199 PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork)); 4200 PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES)); 4201 PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork)); 4202 } 4203 } else { 4204 PetscCall(MatAYPX(B, 0.0, A, str)); 4205 } 4206 PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 4207 PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 4208 PetscFunctionReturn(PETSC_SUCCESS); 4209 } 4210 4211 /*@ 4212 MatCopy - Copies a matrix to another matrix. 4213 4214 Collective 4215 4216 Input Parameters: 4217 + A - the matrix 4218 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN` 4219 4220 Output Parameter: 4221 . B - where the copy is put 4222 4223 Level: intermediate 4224 4225 Notes: 4226 If you use `SAME_NONZERO_PATTERN` then the two matrices must have the same nonzero pattern or the routine will crash. 4227 4228 `MatCopy()` copies the matrix entries of a matrix to another existing 4229 matrix (after first zeroing the second matrix). A related routine is 4230 `MatConvert()`, which first creates a new matrix and then copies the data. 4231 4232 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()` 4233 @*/ 4234 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str) 4235 { 4236 PetscInt i; 4237 4238 PetscFunctionBegin; 4239 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 4240 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 4241 PetscValidType(A, 1); 4242 PetscValidType(B, 2); 4243 PetscCheckSameComm(A, 1, B, 2); 4244 MatCheckPreallocated(B, 2); 4245 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4246 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4247 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, 4248 A->cmap->N, B->cmap->N); 4249 MatCheckPreallocated(A, 1); 4250 if (A == B) PetscFunctionReturn(PETSC_SUCCESS); 4251 4252 PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0)); 4253 if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str); 4254 else PetscCall(MatCopy_Basic(A, B, str)); 4255 4256 B->stencil.dim = A->stencil.dim; 4257 B->stencil.noc = A->stencil.noc; 4258 for (i = 0; i <= A->stencil.dim; i++) { 4259 B->stencil.dims[i] = A->stencil.dims[i]; 4260 B->stencil.starts[i] = A->stencil.starts[i]; 4261 } 4262 4263 PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0)); 4264 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4265 PetscFunctionReturn(PETSC_SUCCESS); 4266 } 4267 4268 /*@C 4269 MatConvert - Converts a matrix to another matrix, either of the same 4270 or different type. 4271 4272 Collective 4273 4274 Input Parameters: 4275 + mat - the matrix 4276 . newtype - new matrix type. Use `MATSAME` to create a new matrix of the 4277 same type as the original matrix. 4278 - reuse - denotes if the destination matrix is to be created or reused. 4279 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 4280 `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). 4281 4282 Output Parameter: 4283 . M - pointer to place new matrix 4284 4285 Level: intermediate 4286 4287 Notes: 4288 `MatConvert()` first creates a new matrix and then copies the data from 4289 the first matrix. A related routine is `MatCopy()`, which copies the matrix 4290 entries of one matrix to another already existing matrix context. 4291 4292 Cannot be used to convert a sequential matrix to parallel or parallel to sequential, 4293 the MPI communicator of the generated matrix is always the same as the communicator 4294 of the input matrix. 4295 4296 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 4297 @*/ 4298 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M) 4299 { 4300 PetscBool sametype, issame, flg; 4301 PetscBool3 issymmetric, ishermitian; 4302 char convname[256], mtype[256]; 4303 Mat B; 4304 4305 PetscFunctionBegin; 4306 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4307 PetscValidType(mat, 1); 4308 PetscValidPointer(M, 4); 4309 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4310 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4311 MatCheckPreallocated(mat, 1); 4312 4313 PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg)); 4314 if (flg) newtype = mtype; 4315 4316 PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype)); 4317 PetscCall(PetscStrcmp(newtype, "same", &issame)); 4318 PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix"); 4319 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"); 4320 4321 if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) { 4322 PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4323 PetscFunctionReturn(PETSC_SUCCESS); 4324 } 4325 4326 /* Cache Mat options because some converters use MatHeaderReplace */ 4327 issymmetric = mat->symmetric; 4328 ishermitian = mat->hermitian; 4329 4330 if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) { 4331 PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4332 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4333 } else { 4334 PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL; 4335 const char *prefix[3] = {"seq", "mpi", ""}; 4336 PetscInt i; 4337 /* 4338 Order of precedence: 4339 0) See if newtype is a superclass of the current matrix. 4340 1) See if a specialized converter is known to the current matrix. 4341 2) See if a specialized converter is known to the desired matrix class. 4342 3) See if a good general converter is registered for the desired class 4343 (as of 6/27/03 only MATMPIADJ falls into this category). 4344 4) See if a good general converter is known for the current matrix. 4345 5) Use a really basic converter. 4346 */ 4347 4348 /* 0) See if newtype is a superclass of the current matrix. 4349 i.e mat is mpiaij and newtype is aij */ 4350 for (i = 0; i < 2; i++) { 4351 PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname))); 4352 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4353 PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg)); 4354 PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg)); 4355 if (flg) { 4356 if (reuse == MAT_INPLACE_MATRIX) { 4357 PetscCall(PetscInfo(mat, "Early return\n")); 4358 PetscFunctionReturn(PETSC_SUCCESS); 4359 } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) { 4360 PetscCall(PetscInfo(mat, "Calling MatDuplicate\n")); 4361 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4362 PetscFunctionReturn(PETSC_SUCCESS); 4363 } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) { 4364 PetscCall(PetscInfo(mat, "Calling MatCopy\n")); 4365 PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN)); 4366 PetscFunctionReturn(PETSC_SUCCESS); 4367 } 4368 } 4369 } 4370 /* 1) See if a specialized converter is known to the current matrix and the desired class */ 4371 for (i = 0; i < 3; i++) { 4372 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4373 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4374 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4375 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4376 PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname))); 4377 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4378 PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv)); 4379 PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv)); 4380 if (conv) goto foundconv; 4381 } 4382 4383 /* 2) See if a specialized converter is known to the desired matrix class. */ 4384 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B)); 4385 PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 4386 PetscCall(MatSetType(B, newtype)); 4387 for (i = 0; i < 3; i++) { 4388 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4389 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4390 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4391 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4392 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4393 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4394 PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv)); 4395 PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv)); 4396 if (conv) { 4397 PetscCall(MatDestroy(&B)); 4398 goto foundconv; 4399 } 4400 } 4401 4402 /* 3) See if a good general converter is registered for the desired class */ 4403 conv = B->ops->convertfrom; 4404 PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv)); 4405 PetscCall(MatDestroy(&B)); 4406 if (conv) goto foundconv; 4407 4408 /* 4) See if a good general converter is known for the current matrix */ 4409 if (mat->ops->convert) conv = mat->ops->convert; 4410 PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv)); 4411 if (conv) goto foundconv; 4412 4413 /* 5) Use a really basic converter. */ 4414 PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n")); 4415 conv = MatConvert_Basic; 4416 4417 foundconv: 4418 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4419 PetscCall((*conv)(mat, newtype, reuse, M)); 4420 if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) { 4421 /* the block sizes must be same if the mappings are copied over */ 4422 (*M)->rmap->bs = mat->rmap->bs; 4423 (*M)->cmap->bs = mat->cmap->bs; 4424 PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping)); 4425 PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping)); 4426 (*M)->rmap->mapping = mat->rmap->mapping; 4427 (*M)->cmap->mapping = mat->cmap->mapping; 4428 } 4429 (*M)->stencil.dim = mat->stencil.dim; 4430 (*M)->stencil.noc = mat->stencil.noc; 4431 for (i = 0; i <= mat->stencil.dim; i++) { 4432 (*M)->stencil.dims[i] = mat->stencil.dims[i]; 4433 (*M)->stencil.starts[i] = mat->stencil.starts[i]; 4434 } 4435 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4436 } 4437 PetscCall(PetscObjectStateIncrease((PetscObject)*M)); 4438 4439 /* Copy Mat options */ 4440 if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE)); 4441 else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE)); 4442 if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE)); 4443 else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE)); 4444 PetscFunctionReturn(PETSC_SUCCESS); 4445 } 4446 4447 /*@C 4448 MatFactorGetSolverType - Returns name of the package providing the factorization routines 4449 4450 Not Collective 4451 4452 Input Parameter: 4453 . mat - the matrix, must be a factored matrix 4454 4455 Output Parameter: 4456 . type - the string name of the package (do not free this string) 4457 4458 Level: intermediate 4459 4460 Fortran Note: 4461 Pass in an empty string and the package name will be copied into it. Make sure the string is long enough. 4462 4463 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()` 4464 @*/ 4465 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type) 4466 { 4467 PetscErrorCode (*conv)(Mat, MatSolverType *); 4468 4469 PetscFunctionBegin; 4470 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4471 PetscValidType(mat, 1); 4472 PetscValidPointer(type, 2); 4473 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 4474 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv)); 4475 if (conv) PetscCall((*conv)(mat, type)); 4476 else *type = MATSOLVERPETSC; 4477 PetscFunctionReturn(PETSC_SUCCESS); 4478 } 4479 4480 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType; 4481 struct _MatSolverTypeForSpecifcType { 4482 MatType mtype; 4483 /* no entry for MAT_FACTOR_NONE */ 4484 PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *); 4485 MatSolverTypeForSpecifcType next; 4486 }; 4487 4488 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder; 4489 struct _MatSolverTypeHolder { 4490 char *name; 4491 MatSolverTypeForSpecifcType handlers; 4492 MatSolverTypeHolder next; 4493 }; 4494 4495 static MatSolverTypeHolder MatSolverTypeHolders = NULL; 4496 4497 /*@C 4498 MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type 4499 4500 Input Parameters: 4501 + package - name of the package, for example petsc or superlu 4502 . mtype - the matrix type that works with this package 4503 . ftype - the type of factorization supported by the package 4504 - createfactor - routine that will create the factored matrix ready to be used 4505 4506 Level: developer 4507 4508 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()` 4509 @*/ 4510 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *)) 4511 { 4512 MatSolverTypeHolder next = MatSolverTypeHolders, prev = NULL; 4513 PetscBool flg; 4514 MatSolverTypeForSpecifcType inext, iprev = NULL; 4515 4516 PetscFunctionBegin; 4517 PetscCall(MatInitializePackage()); 4518 if (!next) { 4519 PetscCall(PetscNew(&MatSolverTypeHolders)); 4520 PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name)); 4521 PetscCall(PetscNew(&MatSolverTypeHolders->handlers)); 4522 PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype)); 4523 MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor; 4524 PetscFunctionReturn(PETSC_SUCCESS); 4525 } 4526 while (next) { 4527 PetscCall(PetscStrcasecmp(package, next->name, &flg)); 4528 if (flg) { 4529 PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers"); 4530 inext = next->handlers; 4531 while (inext) { 4532 PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg)); 4533 if (flg) { 4534 inext->createfactor[(int)ftype - 1] = createfactor; 4535 PetscFunctionReturn(PETSC_SUCCESS); 4536 } 4537 iprev = inext; 4538 inext = inext->next; 4539 } 4540 PetscCall(PetscNew(&iprev->next)); 4541 PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype)); 4542 iprev->next->createfactor[(int)ftype - 1] = createfactor; 4543 PetscFunctionReturn(PETSC_SUCCESS); 4544 } 4545 prev = next; 4546 next = next->next; 4547 } 4548 PetscCall(PetscNew(&prev->next)); 4549 PetscCall(PetscStrallocpy(package, &prev->next->name)); 4550 PetscCall(PetscNew(&prev->next->handlers)); 4551 PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype)); 4552 prev->next->handlers->createfactor[(int)ftype - 1] = createfactor; 4553 PetscFunctionReturn(PETSC_SUCCESS); 4554 } 4555 4556 /*@C 4557 MatSolverTypeGet - Gets the function that creates the factor matrix if it exist 4558 4559 Input Parameters: 4560 + type - name of the package, for example petsc or superlu 4561 . ftype - the type of factorization supported by the type 4562 - mtype - the matrix type that works with this type 4563 4564 Output Parameters: 4565 + foundtype - `PETSC_TRUE` if the type was registered 4566 . foundmtype - `PETSC_TRUE` if the type supports the requested mtype 4567 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found 4568 4569 Level: developer 4570 4571 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()` 4572 @*/ 4573 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *)) 4574 { 4575 MatSolverTypeHolder next = MatSolverTypeHolders; 4576 PetscBool flg; 4577 MatSolverTypeForSpecifcType inext; 4578 4579 PetscFunctionBegin; 4580 if (foundtype) *foundtype = PETSC_FALSE; 4581 if (foundmtype) *foundmtype = PETSC_FALSE; 4582 if (createfactor) *createfactor = NULL; 4583 4584 if (type) { 4585 while (next) { 4586 PetscCall(PetscStrcasecmp(type, next->name, &flg)); 4587 if (flg) { 4588 if (foundtype) *foundtype = PETSC_TRUE; 4589 inext = next->handlers; 4590 while (inext) { 4591 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4592 if (flg) { 4593 if (foundmtype) *foundmtype = PETSC_TRUE; 4594 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4595 PetscFunctionReturn(PETSC_SUCCESS); 4596 } 4597 inext = inext->next; 4598 } 4599 } 4600 next = next->next; 4601 } 4602 } else { 4603 while (next) { 4604 inext = next->handlers; 4605 while (inext) { 4606 PetscCall(PetscStrcmp(mtype, inext->mtype, &flg)); 4607 if (flg && inext->createfactor[(int)ftype - 1]) { 4608 if (foundtype) *foundtype = PETSC_TRUE; 4609 if (foundmtype) *foundmtype = PETSC_TRUE; 4610 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4611 PetscFunctionReturn(PETSC_SUCCESS); 4612 } 4613 inext = inext->next; 4614 } 4615 next = next->next; 4616 } 4617 /* try with base classes inext->mtype */ 4618 next = MatSolverTypeHolders; 4619 while (next) { 4620 inext = next->handlers; 4621 while (inext) { 4622 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4623 if (flg && inext->createfactor[(int)ftype - 1]) { 4624 if (foundtype) *foundtype = PETSC_TRUE; 4625 if (foundmtype) *foundmtype = PETSC_TRUE; 4626 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4627 PetscFunctionReturn(PETSC_SUCCESS); 4628 } 4629 inext = inext->next; 4630 } 4631 next = next->next; 4632 } 4633 } 4634 PetscFunctionReturn(PETSC_SUCCESS); 4635 } 4636 4637 PetscErrorCode MatSolverTypeDestroy(void) 4638 { 4639 MatSolverTypeHolder next = MatSolverTypeHolders, prev; 4640 MatSolverTypeForSpecifcType inext, iprev; 4641 4642 PetscFunctionBegin; 4643 while (next) { 4644 PetscCall(PetscFree(next->name)); 4645 inext = next->handlers; 4646 while (inext) { 4647 PetscCall(PetscFree(inext->mtype)); 4648 iprev = inext; 4649 inext = inext->next; 4650 PetscCall(PetscFree(iprev)); 4651 } 4652 prev = next; 4653 next = next->next; 4654 PetscCall(PetscFree(prev)); 4655 } 4656 MatSolverTypeHolders = NULL; 4657 PetscFunctionReturn(PETSC_SUCCESS); 4658 } 4659 4660 /*@C 4661 MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4662 4663 Logically Collective 4664 4665 Input Parameter: 4666 . mat - the matrix 4667 4668 Output Parameter: 4669 . flg - `PETSC_TRUE` if uses the ordering 4670 4671 Level: developer 4672 4673 Note: 4674 Most internal PETSc factorizations use the ordering passed to the factorization routine but external 4675 packages do not, thus we want to skip generating the ordering when it is not needed or used. 4676 4677 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4678 @*/ 4679 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg) 4680 { 4681 PetscFunctionBegin; 4682 *flg = mat->canuseordering; 4683 PetscFunctionReturn(PETSC_SUCCESS); 4684 } 4685 4686 /*@C 4687 MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object 4688 4689 Logically Collective 4690 4691 Input Parameters: 4692 + mat - the matrix obtained with `MatGetFactor()` 4693 - ftype - the factorization type to be used 4694 4695 Output Parameter: 4696 . otype - the preferred ordering type 4697 4698 Level: developer 4699 4700 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4701 @*/ 4702 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype) 4703 { 4704 PetscFunctionBegin; 4705 *otype = mat->preferredordering[ftype]; 4706 PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering"); 4707 PetscFunctionReturn(PETSC_SUCCESS); 4708 } 4709 4710 /*@C 4711 MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic() 4712 4713 Collective 4714 4715 Input Parameters: 4716 + mat - the matrix 4717 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4718 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4719 4720 Output Parameter: 4721 . f - the factor matrix used with MatXXFactorSymbolic() calls 4722 4723 Options Database Key: 4724 . -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory. 4725 One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices. 4726 4727 Level: intermediate 4728 4729 Notes: 4730 Users usually access the factorization solvers via `KSP` 4731 4732 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4733 such as pastix, superlu, mumps etc. 4734 4735 PETSc must have been ./configure to use the external solver, using the option --download-package 4736 4737 Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption 4738 where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set 4739 call `MatSetOptionsPrefixFactor()` on the originating matrix or `MatSetOptionsPrefix()` on the resulting factor matrix. 4740 4741 Developer Note: 4742 This should actually be called `MatCreateFactor()` since it creates a new factor object 4743 4744 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, 4745 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4746 @*/ 4747 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f) 4748 { 4749 PetscBool foundtype, foundmtype; 4750 PetscErrorCode (*conv)(Mat, MatFactorType, Mat *); 4751 4752 PetscFunctionBegin; 4753 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4754 PetscValidType(mat, 1); 4755 4756 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4757 MatCheckPreallocated(mat, 1); 4758 4759 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv)); 4760 if (!foundtype) { 4761 if (type) { 4762 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], 4763 ((PetscObject)mat)->type_name, type); 4764 } else { 4765 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); 4766 } 4767 } 4768 PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name); 4769 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); 4770 4771 PetscCall((*conv)(mat, ftype, f)); 4772 if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix)); 4773 PetscFunctionReturn(PETSC_SUCCESS); 4774 } 4775 4776 /*@C 4777 MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type 4778 4779 Not Collective 4780 4781 Input Parameters: 4782 + mat - the matrix 4783 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4784 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4785 4786 Output Parameter: 4787 . flg - PETSC_TRUE if the factorization is available 4788 4789 Level: intermediate 4790 4791 Notes: 4792 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4793 such as pastix, superlu, mumps etc. 4794 4795 PETSc must have been ./configure to use the external solver, using the option --download-package 4796 4797 Developer Note: 4798 This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object 4799 4800 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactor()`, `MatSolverTypeRegister()`, 4801 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4802 @*/ 4803 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg) 4804 { 4805 PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *); 4806 4807 PetscFunctionBegin; 4808 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4809 PetscValidType(mat, 1); 4810 PetscValidBoolPointer(flg, 4); 4811 4812 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4813 MatCheckPreallocated(mat, 1); 4814 4815 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv)); 4816 *flg = gconv ? PETSC_TRUE : PETSC_FALSE; 4817 PetscFunctionReturn(PETSC_SUCCESS); 4818 } 4819 4820 /*@ 4821 MatDuplicate - Duplicates a matrix including the non-zero structure. 4822 4823 Collective 4824 4825 Input Parameters: 4826 + mat - the matrix 4827 - op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`. 4828 See the manual page for `MatDuplicateOption()` for an explanation of these options. 4829 4830 Output Parameter: 4831 . M - pointer to place new matrix 4832 4833 Level: intermediate 4834 4835 Notes: 4836 You cannot change the nonzero pattern for the parent or child matrix if you use `MAT_SHARE_NONZERO_PATTERN`. 4837 4838 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. 4839 4840 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 4841 is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated. 4842 User should not use `MatDuplicate()` to create new matrix M if M is intended to be reused as the product of matrix operation. 4843 4844 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption` 4845 @*/ 4846 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M) 4847 { 4848 Mat B; 4849 VecType vtype; 4850 PetscInt i; 4851 PetscObject dm; 4852 void (*viewf)(void); 4853 4854 PetscFunctionBegin; 4855 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4856 PetscValidType(mat, 1); 4857 PetscValidPointer(M, 3); 4858 PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix"); 4859 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4860 MatCheckPreallocated(mat, 1); 4861 4862 *M = NULL; 4863 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4864 PetscUseTypeMethod(mat, duplicate, op, M); 4865 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4866 B = *M; 4867 4868 PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf)); 4869 if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf)); 4870 PetscCall(MatGetVecType(mat, &vtype)); 4871 PetscCall(MatSetVecType(B, vtype)); 4872 4873 B->stencil.dim = mat->stencil.dim; 4874 B->stencil.noc = mat->stencil.noc; 4875 for (i = 0; i <= mat->stencil.dim; i++) { 4876 B->stencil.dims[i] = mat->stencil.dims[i]; 4877 B->stencil.starts[i] = mat->stencil.starts[i]; 4878 } 4879 4880 B->nooffproczerorows = mat->nooffproczerorows; 4881 B->nooffprocentries = mat->nooffprocentries; 4882 4883 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm)); 4884 if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm)); 4885 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4886 PetscFunctionReturn(PETSC_SUCCESS); 4887 } 4888 4889 /*@ 4890 MatGetDiagonal - Gets the diagonal of a matrix as a `Vec` 4891 4892 Logically Collective 4893 4894 Input Parameter: 4895 . mat - the matrix 4896 4897 Output Parameter: 4898 . v - the diagonal of the matrix 4899 4900 Level: intermediate 4901 4902 Note: 4903 Currently only correct in parallel for square matrices. 4904 4905 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()` 4906 @*/ 4907 PetscErrorCode MatGetDiagonal(Mat mat, Vec v) 4908 { 4909 PetscFunctionBegin; 4910 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4911 PetscValidType(mat, 1); 4912 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4913 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4914 MatCheckPreallocated(mat, 1); 4915 4916 PetscUseTypeMethod(mat, getdiagonal, v); 4917 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4918 PetscFunctionReturn(PETSC_SUCCESS); 4919 } 4920 4921 /*@C 4922 MatGetRowMin - Gets the minimum value (of the real part) of each 4923 row of the matrix 4924 4925 Logically Collective 4926 4927 Input Parameter: 4928 . mat - the matrix 4929 4930 Output Parameters: 4931 + v - the vector for storing the maximums 4932 - idx - the indices of the column found for each row (optional) 4933 4934 Level: intermediate 4935 4936 Note: 4937 The result of this call are the same as if one converted the matrix to dense format 4938 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 4939 4940 This code is only implemented for a couple of matrix formats. 4941 4942 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, 4943 `MatGetRowMax()` 4944 @*/ 4945 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[]) 4946 { 4947 PetscFunctionBegin; 4948 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4949 PetscValidType(mat, 1); 4950 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4951 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4952 4953 if (!mat->cmap->N) { 4954 PetscCall(VecSet(v, PETSC_MAX_REAL)); 4955 if (idx) { 4956 PetscInt i, m = mat->rmap->n; 4957 for (i = 0; i < m; i++) idx[i] = -1; 4958 } 4959 } else { 4960 MatCheckPreallocated(mat, 1); 4961 } 4962 PetscUseTypeMethod(mat, getrowmin, v, idx); 4963 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4964 PetscFunctionReturn(PETSC_SUCCESS); 4965 } 4966 4967 /*@C 4968 MatGetRowMinAbs - Gets the minimum value (in absolute value) of each 4969 row of the matrix 4970 4971 Logically Collective 4972 4973 Input Parameter: 4974 . mat - the matrix 4975 4976 Output Parameters: 4977 + v - the vector for storing the minimums 4978 - idx - the indices of the column found for each row (or `NULL` if not needed) 4979 4980 Level: intermediate 4981 4982 Notes: 4983 if a row is completely empty or has only 0.0 values then the idx[] value for that 4984 row is 0 (the first column). 4985 4986 This code is only implemented for a couple of matrix formats. 4987 4988 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()` 4989 @*/ 4990 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[]) 4991 { 4992 PetscFunctionBegin; 4993 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4994 PetscValidType(mat, 1); 4995 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4996 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4997 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4998 4999 if (!mat->cmap->N) { 5000 PetscCall(VecSet(v, 0.0)); 5001 if (idx) { 5002 PetscInt i, m = mat->rmap->n; 5003 for (i = 0; i < m; i++) idx[i] = -1; 5004 } 5005 } else { 5006 MatCheckPreallocated(mat, 1); 5007 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5008 PetscUseTypeMethod(mat, getrowminabs, v, idx); 5009 } 5010 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5011 PetscFunctionReturn(PETSC_SUCCESS); 5012 } 5013 5014 /*@C 5015 MatGetRowMax - Gets the maximum value (of the real part) of each 5016 row of the matrix 5017 5018 Logically Collective 5019 5020 Input Parameter: 5021 . mat - the matrix 5022 5023 Output Parameters: 5024 + v - the vector for storing the maximums 5025 - idx - the indices of the column found for each row (optional) 5026 5027 Level: intermediate 5028 5029 Notes: 5030 The result of this call are the same as if one converted the matrix to dense format 5031 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5032 5033 This code is only implemented for a couple of matrix formats. 5034 5035 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5036 @*/ 5037 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[]) 5038 { 5039 PetscFunctionBegin; 5040 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5041 PetscValidType(mat, 1); 5042 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5043 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5044 5045 if (!mat->cmap->N) { 5046 PetscCall(VecSet(v, PETSC_MIN_REAL)); 5047 if (idx) { 5048 PetscInt i, m = mat->rmap->n; 5049 for (i = 0; i < m; i++) idx[i] = -1; 5050 } 5051 } else { 5052 MatCheckPreallocated(mat, 1); 5053 PetscUseTypeMethod(mat, getrowmax, v, idx); 5054 } 5055 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5056 PetscFunctionReturn(PETSC_SUCCESS); 5057 } 5058 5059 /*@C 5060 MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each 5061 row of the matrix 5062 5063 Logically Collective 5064 5065 Input Parameter: 5066 . mat - the matrix 5067 5068 Output Parameters: 5069 + v - the vector for storing the maximums 5070 - idx - the indices of the column found for each row (or `NULL` if not needed) 5071 5072 Level: intermediate 5073 5074 Notes: 5075 if a row is completely empty or has only 0.0 values then the idx[] value for that 5076 row is 0 (the first column). 5077 5078 This code is only implemented for a couple of matrix formats. 5079 5080 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5081 @*/ 5082 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[]) 5083 { 5084 PetscFunctionBegin; 5085 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5086 PetscValidType(mat, 1); 5087 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5088 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5089 5090 if (!mat->cmap->N) { 5091 PetscCall(VecSet(v, 0.0)); 5092 if (idx) { 5093 PetscInt i, m = mat->rmap->n; 5094 for (i = 0; i < m; i++) idx[i] = -1; 5095 } 5096 } else { 5097 MatCheckPreallocated(mat, 1); 5098 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5099 PetscUseTypeMethod(mat, getrowmaxabs, v, idx); 5100 } 5101 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5102 PetscFunctionReturn(PETSC_SUCCESS); 5103 } 5104 5105 /*@ 5106 MatGetRowSum - Gets the sum of each row of the matrix 5107 5108 Logically or Neighborhood Collective 5109 5110 Input Parameter: 5111 . mat - the matrix 5112 5113 Output Parameter: 5114 . v - the vector for storing the sum of rows 5115 5116 Level: intermediate 5117 5118 Notes: 5119 This code is slow since it is not currently specialized for different formats 5120 5121 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()` 5122 @*/ 5123 PetscErrorCode MatGetRowSum(Mat mat, Vec v) 5124 { 5125 Vec ones; 5126 5127 PetscFunctionBegin; 5128 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5129 PetscValidType(mat, 1); 5130 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5131 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5132 MatCheckPreallocated(mat, 1); 5133 PetscCall(MatCreateVecs(mat, &ones, NULL)); 5134 PetscCall(VecSet(ones, 1.)); 5135 PetscCall(MatMult(mat, ones, v)); 5136 PetscCall(VecDestroy(&ones)); 5137 PetscFunctionReturn(PETSC_SUCCESS); 5138 } 5139 5140 /*@ 5141 MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) 5142 when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B) 5143 5144 Collective 5145 5146 Input Parameter: 5147 . mat - the matrix to provide the transpose 5148 5149 Output Parameter: 5150 . 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 5151 5152 Level: advanced 5153 5154 Note: 5155 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 5156 routine allows bypassing that call. 5157 5158 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5159 @*/ 5160 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B) 5161 { 5162 PetscContainer rB = NULL; 5163 MatParentState *rb = NULL; 5164 5165 PetscFunctionBegin; 5166 PetscCall(PetscNew(&rb)); 5167 rb->id = ((PetscObject)mat)->id; 5168 rb->state = 0; 5169 PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate)); 5170 PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB)); 5171 PetscCall(PetscContainerSetPointer(rB, rb)); 5172 PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault)); 5173 PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB)); 5174 PetscCall(PetscObjectDereference((PetscObject)rB)); 5175 PetscFunctionReturn(PETSC_SUCCESS); 5176 } 5177 5178 /*@ 5179 MatTranspose - Computes an in-place or out-of-place transpose of a matrix. 5180 5181 Collective 5182 5183 Input Parameters: 5184 + mat - the matrix to transpose 5185 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5186 5187 Output Parameter: 5188 . B - the transpose 5189 5190 Level: intermediate 5191 5192 Notes: 5193 If you use `MAT_INPLACE_MATRIX` then you must pass in &mat for B 5194 5195 `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 5196 transpose, call `MatTransposeSetPrecursor`(mat,B) before calling this routine. 5197 5198 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. 5199 5200 Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed. 5201 5202 If mat is unchanged from the last call this function returns immediately without recomputing the result 5203 5204 If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()` 5205 5206 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`, 5207 `MatTransposeSymbolic()`, `MatCreateTranspose()` 5208 @*/ 5209 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B) 5210 { 5211 PetscContainer rB = NULL; 5212 MatParentState *rb = NULL; 5213 5214 PetscFunctionBegin; 5215 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5216 PetscValidType(mat, 1); 5217 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5218 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5219 PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first"); 5220 PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX"); 5221 MatCheckPreallocated(mat, 1); 5222 if (reuse == MAT_REUSE_MATRIX) { 5223 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5224 PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor()."); 5225 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5226 PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5227 if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS); 5228 } 5229 5230 PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0)); 5231 if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) { 5232 PetscUseTypeMethod(mat, transpose, reuse, B); 5233 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5234 } 5235 PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0)); 5236 5237 if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B)); 5238 if (reuse != MAT_INPLACE_MATRIX) { 5239 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5240 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5241 rb->state = ((PetscObject)mat)->state; 5242 rb->nonzerostate = mat->nonzerostate; 5243 } 5244 PetscFunctionReturn(PETSC_SUCCESS); 5245 } 5246 5247 /*@ 5248 MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix. 5249 5250 Collective 5251 5252 Input Parameter: 5253 . A - the matrix to transpose 5254 5255 Output Parameter: 5256 . 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 5257 numerical portion. 5258 5259 Level: intermediate 5260 5261 Note: 5262 This is not supported for many matrix types, use `MatTranspose()` in those cases 5263 5264 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5265 @*/ 5266 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B) 5267 { 5268 PetscFunctionBegin; 5269 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5270 PetscValidType(A, 1); 5271 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5272 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5273 PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0)); 5274 PetscUseTypeMethod(A, transposesymbolic, B); 5275 PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0)); 5276 5277 PetscCall(MatTransposeSetPrecursor(A, *B)); 5278 PetscFunctionReturn(PETSC_SUCCESS); 5279 } 5280 5281 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B) 5282 { 5283 PetscContainer rB; 5284 MatParentState *rb; 5285 5286 PetscFunctionBegin; 5287 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5288 PetscValidType(A, 1); 5289 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5290 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5291 PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB)); 5292 PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()"); 5293 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5294 PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5295 PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure"); 5296 PetscFunctionReturn(PETSC_SUCCESS); 5297 } 5298 5299 /*@ 5300 MatIsTranspose - Test whether a matrix is another one's transpose, 5301 or its own, in which case it tests symmetry. 5302 5303 Collective 5304 5305 Input Parameters: 5306 + A - the matrix to test 5307 . B - the matrix to test against, this can equal the first parameter 5308 - tol - tolerance, differences between entries smaller than this are counted as zero 5309 5310 Output Parameter: 5311 . flg - the result 5312 5313 Level: intermediate 5314 5315 Notes: 5316 Only available for `MATAIJ` matrices. 5317 5318 The sequential algorithm has a running time of the order of the number of nonzeros; the parallel 5319 test involves parallel copies of the block-offdiagonal parts of the matrix. 5320 5321 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()` 5322 @*/ 5323 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5324 { 5325 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5326 5327 PetscFunctionBegin; 5328 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5329 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5330 PetscValidBoolPointer(flg, 4); 5331 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f)); 5332 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g)); 5333 *flg = PETSC_FALSE; 5334 if (f && g) { 5335 PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test"); 5336 PetscCall((*f)(A, B, tol, flg)); 5337 } else { 5338 MatType mattype; 5339 5340 PetscCall(MatGetType(f ? B : A, &mattype)); 5341 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype); 5342 } 5343 PetscFunctionReturn(PETSC_SUCCESS); 5344 } 5345 5346 /*@ 5347 MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate. 5348 5349 Collective 5350 5351 Input Parameters: 5352 + mat - the matrix to transpose and complex conjugate 5353 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5354 5355 Output Parameter: 5356 . B - the Hermitian transpose 5357 5358 Level: intermediate 5359 5360 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse` 5361 @*/ 5362 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B) 5363 { 5364 PetscFunctionBegin; 5365 PetscCall(MatTranspose(mat, reuse, B)); 5366 #if defined(PETSC_USE_COMPLEX) 5367 PetscCall(MatConjugate(*B)); 5368 #endif 5369 PetscFunctionReturn(PETSC_SUCCESS); 5370 } 5371 5372 /*@ 5373 MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose, 5374 5375 Collective 5376 5377 Input Parameters: 5378 + A - the matrix to test 5379 . B - the matrix to test against, this can equal the first parameter 5380 - tol - tolerance, differences between entries smaller than this are counted as zero 5381 5382 Output Parameter: 5383 . flg - the result 5384 5385 Level: intermediate 5386 5387 Notes: 5388 Only available for `MATAIJ` matrices. 5389 5390 The sequential algorithm 5391 has a running time of the order of the number of nonzeros; the parallel 5392 test involves parallel copies of the block-offdiagonal parts of the matrix. 5393 5394 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()` 5395 @*/ 5396 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5397 { 5398 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5399 5400 PetscFunctionBegin; 5401 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5402 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5403 PetscValidBoolPointer(flg, 4); 5404 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f)); 5405 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g)); 5406 if (f && g) { 5407 PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test"); 5408 PetscCall((*f)(A, B, tol, flg)); 5409 } 5410 PetscFunctionReturn(PETSC_SUCCESS); 5411 } 5412 5413 /*@ 5414 MatPermute - Creates a new matrix with rows and columns permuted from the 5415 original. 5416 5417 Collective 5418 5419 Input Parameters: 5420 + mat - the matrix to permute 5421 . row - row permutation, each processor supplies only the permutation for its rows 5422 - col - column permutation, each processor supplies only the permutation for its columns 5423 5424 Output Parameter: 5425 . B - the permuted matrix 5426 5427 Level: advanced 5428 5429 Note: 5430 The index sets map from row/col of permuted matrix to row/col of original matrix. 5431 The index sets should be on the same communicator as mat and have the same local sizes. 5432 5433 Developer Note: 5434 If you want to implement `MatPermute()` for a matrix type, and your approach doesn't 5435 exploit the fact that row and col are permutations, consider implementing the 5436 more general `MatCreateSubMatrix()` instead. 5437 5438 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()` 5439 @*/ 5440 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B) 5441 { 5442 PetscFunctionBegin; 5443 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5444 PetscValidType(mat, 1); 5445 PetscValidHeaderSpecific(row, IS_CLASSID, 2); 5446 PetscValidHeaderSpecific(col, IS_CLASSID, 3); 5447 PetscValidPointer(B, 4); 5448 PetscCheckSameComm(mat, 1, row, 2); 5449 if (row != col) PetscCheckSameComm(row, 2, col, 3); 5450 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5451 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5452 PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name); 5453 MatCheckPreallocated(mat, 1); 5454 5455 if (mat->ops->permute) { 5456 PetscUseTypeMethod(mat, permute, row, col, B); 5457 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5458 } else { 5459 PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B)); 5460 } 5461 PetscFunctionReturn(PETSC_SUCCESS); 5462 } 5463 5464 /*@ 5465 MatEqual - Compares two matrices. 5466 5467 Collective 5468 5469 Input Parameters: 5470 + A - the first matrix 5471 - B - the second matrix 5472 5473 Output Parameter: 5474 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise. 5475 5476 Level: intermediate 5477 5478 .seealso: [](ch_matrices), `Mat` 5479 @*/ 5480 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg) 5481 { 5482 PetscFunctionBegin; 5483 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5484 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5485 PetscValidType(A, 1); 5486 PetscValidType(B, 2); 5487 PetscValidBoolPointer(flg, 3); 5488 PetscCheckSameComm(A, 1, B, 2); 5489 MatCheckPreallocated(A, 1); 5490 MatCheckPreallocated(B, 2); 5491 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5492 PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5493 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, 5494 B->cmap->N); 5495 if (A->ops->equal && A->ops->equal == B->ops->equal) { 5496 PetscUseTypeMethod(A, equal, B, flg); 5497 } else { 5498 PetscCall(MatMultEqual(A, B, 10, flg)); 5499 } 5500 PetscFunctionReturn(PETSC_SUCCESS); 5501 } 5502 5503 /*@ 5504 MatDiagonalScale - Scales a matrix on the left and right by diagonal 5505 matrices that are stored as vectors. Either of the two scaling 5506 matrices can be `NULL`. 5507 5508 Collective 5509 5510 Input Parameters: 5511 + mat - the matrix to be scaled 5512 . l - the left scaling vector (or `NULL`) 5513 - r - the right scaling vector (or `NULL`) 5514 5515 Level: intermediate 5516 5517 Note: 5518 `MatDiagonalScale()` computes A = LAR, where 5519 L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector) 5520 The L scales the rows of the matrix, the R scales the columns of the matrix. 5521 5522 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()` 5523 @*/ 5524 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r) 5525 { 5526 PetscFunctionBegin; 5527 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5528 PetscValidType(mat, 1); 5529 if (l) { 5530 PetscValidHeaderSpecific(l, VEC_CLASSID, 2); 5531 PetscCheckSameComm(mat, 1, l, 2); 5532 } 5533 if (r) { 5534 PetscValidHeaderSpecific(r, VEC_CLASSID, 3); 5535 PetscCheckSameComm(mat, 1, r, 3); 5536 } 5537 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5538 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5539 MatCheckPreallocated(mat, 1); 5540 if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS); 5541 5542 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5543 PetscUseTypeMethod(mat, diagonalscale, l, r); 5544 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5545 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5546 if (l != r) mat->symmetric = PETSC_BOOL3_FALSE; 5547 PetscFunctionReturn(PETSC_SUCCESS); 5548 } 5549 5550 /*@ 5551 MatScale - Scales all elements of a matrix by a given number. 5552 5553 Logically Collective 5554 5555 Input Parameters: 5556 + mat - the matrix to be scaled 5557 - a - the scaling value 5558 5559 Level: intermediate 5560 5561 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 5562 @*/ 5563 PetscErrorCode MatScale(Mat mat, PetscScalar a) 5564 { 5565 PetscFunctionBegin; 5566 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5567 PetscValidType(mat, 1); 5568 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5569 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5570 PetscValidLogicalCollectiveScalar(mat, a, 2); 5571 MatCheckPreallocated(mat, 1); 5572 5573 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5574 if (a != (PetscScalar)1.0) { 5575 PetscUseTypeMethod(mat, scale, a); 5576 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5577 } 5578 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5579 PetscFunctionReturn(PETSC_SUCCESS); 5580 } 5581 5582 /*@ 5583 MatNorm - Calculates various norms of a matrix. 5584 5585 Collective 5586 5587 Input Parameters: 5588 + mat - the matrix 5589 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY` 5590 5591 Output Parameter: 5592 . nrm - the resulting norm 5593 5594 Level: intermediate 5595 5596 .seealso: [](ch_matrices), `Mat` 5597 @*/ 5598 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm) 5599 { 5600 PetscFunctionBegin; 5601 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5602 PetscValidType(mat, 1); 5603 PetscValidRealPointer(nrm, 3); 5604 5605 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5606 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5607 MatCheckPreallocated(mat, 1); 5608 5609 PetscUseTypeMethod(mat, norm, type, nrm); 5610 PetscFunctionReturn(PETSC_SUCCESS); 5611 } 5612 5613 /* 5614 This variable is used to prevent counting of MatAssemblyBegin() that 5615 are called from within a MatAssemblyEnd(). 5616 */ 5617 static PetscInt MatAssemblyEnd_InUse = 0; 5618 /*@ 5619 MatAssemblyBegin - Begins assembling the matrix. This routine should 5620 be called after completing all calls to `MatSetValues()`. 5621 5622 Collective 5623 5624 Input Parameters: 5625 + mat - the matrix 5626 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5627 5628 Level: beginner 5629 5630 Notes: 5631 `MatSetValues()` generally caches the values that belong to other MPI ranks. The matrix is ready to 5632 use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called. 5633 5634 Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES` 5635 in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before 5636 using the matrix. 5637 5638 ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the 5639 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 5640 a global collective operation requiring all processes that share the matrix. 5641 5642 Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed 5643 out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros 5644 before `MAT_FINAL_ASSEMBLY` so the space is not compressed out. 5645 5646 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()` 5647 @*/ 5648 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type) 5649 { 5650 PetscFunctionBegin; 5651 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5652 PetscValidType(mat, 1); 5653 MatCheckPreallocated(mat, 1); 5654 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?"); 5655 if (mat->assembled) { 5656 mat->was_assembled = PETSC_TRUE; 5657 mat->assembled = PETSC_FALSE; 5658 } 5659 5660 if (!MatAssemblyEnd_InUse) { 5661 PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0)); 5662 PetscTryTypeMethod(mat, assemblybegin, type); 5663 PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0)); 5664 } else PetscTryTypeMethod(mat, assemblybegin, type); 5665 PetscFunctionReturn(PETSC_SUCCESS); 5666 } 5667 5668 /*@ 5669 MatAssembled - Indicates if a matrix has been assembled and is ready for 5670 use; for example, in matrix-vector product. 5671 5672 Not Collective 5673 5674 Input Parameter: 5675 . mat - the matrix 5676 5677 Output Parameter: 5678 . assembled - `PETSC_TRUE` or `PETSC_FALSE` 5679 5680 Level: advanced 5681 5682 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()` 5683 @*/ 5684 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled) 5685 { 5686 PetscFunctionBegin; 5687 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5688 PetscValidBoolPointer(assembled, 2); 5689 *assembled = mat->assembled; 5690 PetscFunctionReturn(PETSC_SUCCESS); 5691 } 5692 5693 /*@ 5694 MatAssemblyEnd - Completes assembling the matrix. This routine should 5695 be called after `MatAssemblyBegin()`. 5696 5697 Collective 5698 5699 Input Parameters: 5700 + mat - the matrix 5701 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5702 5703 Options Database Keys: 5704 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatEndAssembly()` 5705 . -mat_view ::ascii_info_detail - Prints more detailed info 5706 . -mat_view - Prints matrix in ASCII format 5707 . -mat_view ::ascii_matlab - Prints matrix in Matlab format 5708 . -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 5709 . -display <name> - Sets display name (default is host) 5710 . -draw_pause <sec> - Sets number of seconds to pause after display 5711 . -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See [Using MATLAB with PETSc](ch_matlab)) 5712 . -viewer_socket_machine <machine> - Machine to use for socket 5713 . -viewer_socket_port <port> - Port number to use for socket 5714 - -mat_view binary:filename[:append] - Save matrix to file in binary format 5715 5716 Level: beginner 5717 5718 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()` 5719 @*/ 5720 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type) 5721 { 5722 static PetscInt inassm = 0; 5723 PetscBool flg = PETSC_FALSE; 5724 5725 PetscFunctionBegin; 5726 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5727 PetscValidType(mat, 1); 5728 5729 inassm++; 5730 MatAssemblyEnd_InUse++; 5731 if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */ 5732 PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0)); 5733 PetscTryTypeMethod(mat, assemblyend, type); 5734 PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0)); 5735 } else PetscTryTypeMethod(mat, assemblyend, type); 5736 5737 /* Flush assembly is not a true assembly */ 5738 if (type != MAT_FLUSH_ASSEMBLY) { 5739 if (mat->num_ass) { 5740 if (!mat->symmetry_eternal) { 5741 mat->symmetric = PETSC_BOOL3_UNKNOWN; 5742 mat->hermitian = PETSC_BOOL3_UNKNOWN; 5743 } 5744 if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN; 5745 if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN; 5746 } 5747 mat->num_ass++; 5748 mat->assembled = PETSC_TRUE; 5749 mat->ass_nonzerostate = mat->nonzerostate; 5750 } 5751 5752 mat->insertmode = NOT_SET_VALUES; 5753 MatAssemblyEnd_InUse--; 5754 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5755 if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) { 5756 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 5757 5758 if (mat->checksymmetryonassembly) { 5759 PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg)); 5760 if (flg) { 5761 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5762 } else { 5763 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5764 } 5765 } 5766 if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL)); 5767 } 5768 inassm--; 5769 PetscFunctionReturn(PETSC_SUCCESS); 5770 } 5771 5772 /*@ 5773 MatSetOption - Sets a parameter option for a matrix. Some options 5774 may be specific to certain storage formats. Some options 5775 determine how values will be inserted (or added). Sorted, 5776 row-oriented input will generally assemble the fastest. The default 5777 is row-oriented. 5778 5779 Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption` 5780 5781 Input Parameters: 5782 + mat - the matrix 5783 . option - the option, one of those listed below (and possibly others), 5784 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5785 5786 Options Describing Matrix Structure: 5787 + `MAT_SPD` - symmetric positive definite 5788 . `MAT_SYMMETRIC` - symmetric in terms of both structure and value 5789 . `MAT_HERMITIAN` - transpose is the complex conjugation 5790 . `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure 5791 . `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix 5792 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix 5793 - `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix 5794 5795 These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they 5796 do not need to be computed (usually at a high cost) 5797 5798 Options For Use with `MatSetValues()`: 5799 Insert a logically dense subblock, which can be 5800 . `MAT_ROW_ORIENTED` - row-oriented (default) 5801 5802 These options reflect the data you pass in with `MatSetValues()`; it has 5803 nothing to do with how the data is stored internally in the matrix 5804 data structure. 5805 5806 When (re)assembling a matrix, we can restrict the input for 5807 efficiency/debugging purposes. These options include 5808 + `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow) 5809 . `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated 5810 . `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries 5811 . `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry 5812 . `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly 5813 . `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if 5814 any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves 5815 performance for very large process counts. 5816 - `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset 5817 of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly 5818 functions, instead sending only neighbor messages. 5819 5820 Level: intermediate 5821 5822 Notes: 5823 Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg! 5824 5825 Some options are relevant only for particular matrix types and 5826 are thus ignored by others. Other options are not supported by 5827 certain matrix types and will generate an error message if set. 5828 5829 If using Fortran to compute a matrix, one may need to 5830 use the column-oriented option (or convert to the row-oriented 5831 format). 5832 5833 `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion 5834 that would generate a new entry in the nonzero structure is instead 5835 ignored. Thus, if memory has not already been allocated for this particular 5836 data, then the insertion is ignored. For dense matrices, in which 5837 the entire array is allocated, no entries are ever ignored. 5838 Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction 5839 5840 `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion 5841 that would generate a new entry in the nonzero structure instead produces 5842 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 5843 5844 `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion 5845 that would generate a new entry that has not been preallocated will 5846 instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats 5847 only.) This is a useful flag when debugging matrix memory preallocation. 5848 If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 5849 5850 `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for 5851 other processors should be dropped, rather than stashed. 5852 This is useful if you know that the "owning" processor is also 5853 always generating the correct matrix entries, so that PETSc need 5854 not transfer duplicate entries generated on another processor. 5855 5856 `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the 5857 searches during matrix assembly. When this flag is set, the hash table 5858 is created during the first matrix assembly. This hash table is 5859 used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()` 5860 to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag 5861 should be used with `MAT_USE_HASH_TABLE` flag. This option is currently 5862 supported by `MATMPIBAIJ` format only. 5863 5864 `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries 5865 are kept in the nonzero structure 5866 5867 `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating 5868 a zero location in the matrix 5869 5870 `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types 5871 5872 `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the 5873 zero row routines and thus improves performance for very large process counts. 5874 5875 `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular 5876 part of the matrix (since they should match the upper triangular part). 5877 5878 `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a 5879 single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common 5880 with finite difference schemes with non-periodic boundary conditions. 5881 5882 Developer Note: 5883 `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other 5884 places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRIC` or `MAT_SPD` would need to be changed back 5885 to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had 5886 not changed. 5887 5888 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()` 5889 @*/ 5890 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg) 5891 { 5892 PetscFunctionBegin; 5893 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5894 if (op > 0) { 5895 PetscValidLogicalCollectiveEnum(mat, op, 2); 5896 PetscValidLogicalCollectiveBool(mat, flg, 3); 5897 } 5898 5899 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); 5900 5901 switch (op) { 5902 case MAT_FORCE_DIAGONAL_ENTRIES: 5903 mat->force_diagonals = flg; 5904 PetscFunctionReturn(PETSC_SUCCESS); 5905 case MAT_NO_OFF_PROC_ENTRIES: 5906 mat->nooffprocentries = flg; 5907 PetscFunctionReturn(PETSC_SUCCESS); 5908 case MAT_SUBSET_OFF_PROC_ENTRIES: 5909 mat->assembly_subset = flg; 5910 if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */ 5911 #if !defined(PETSC_HAVE_MPIUNI) 5912 PetscCall(MatStashScatterDestroy_BTS(&mat->stash)); 5913 #endif 5914 mat->stash.first_assembly_done = PETSC_FALSE; 5915 } 5916 PetscFunctionReturn(PETSC_SUCCESS); 5917 case MAT_NO_OFF_PROC_ZERO_ROWS: 5918 mat->nooffproczerorows = flg; 5919 PetscFunctionReturn(PETSC_SUCCESS); 5920 case MAT_SPD: 5921 if (flg) { 5922 mat->spd = PETSC_BOOL3_TRUE; 5923 mat->symmetric = PETSC_BOOL3_TRUE; 5924 mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5925 } else { 5926 mat->spd = PETSC_BOOL3_FALSE; 5927 } 5928 break; 5929 case MAT_SYMMETRIC: 5930 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5931 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5932 #if !defined(PETSC_USE_COMPLEX) 5933 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5934 #endif 5935 break; 5936 case MAT_HERMITIAN: 5937 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5938 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5939 #if !defined(PETSC_USE_COMPLEX) 5940 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5941 #endif 5942 break; 5943 case MAT_STRUCTURALLY_SYMMETRIC: 5944 mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5945 break; 5946 case MAT_SYMMETRY_ETERNAL: 5947 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"); 5948 mat->symmetry_eternal = flg; 5949 if (flg) mat->structural_symmetry_eternal = PETSC_TRUE; 5950 break; 5951 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 5952 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"); 5953 mat->structural_symmetry_eternal = flg; 5954 break; 5955 case MAT_SPD_ETERNAL: 5956 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"); 5957 mat->spd_eternal = flg; 5958 if (flg) { 5959 mat->structural_symmetry_eternal = PETSC_TRUE; 5960 mat->symmetry_eternal = PETSC_TRUE; 5961 } 5962 break; 5963 case MAT_STRUCTURE_ONLY: 5964 mat->structure_only = flg; 5965 break; 5966 case MAT_SORTED_FULL: 5967 mat->sortedfull = flg; 5968 break; 5969 default: 5970 break; 5971 } 5972 PetscTryTypeMethod(mat, setoption, op, flg); 5973 PetscFunctionReturn(PETSC_SUCCESS); 5974 } 5975 5976 /*@ 5977 MatGetOption - Gets a parameter option that has been set for a matrix. 5978 5979 Logically Collective 5980 5981 Input Parameters: 5982 + mat - the matrix 5983 - option - the option, this only responds to certain options, check the code for which ones 5984 5985 Output Parameter: 5986 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5987 5988 Level: intermediate 5989 5990 Notes: 5991 Can only be called after `MatSetSizes()` and `MatSetType()` have been set. 5992 5993 Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or 5994 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 5995 5996 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, 5997 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 5998 @*/ 5999 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg) 6000 { 6001 PetscFunctionBegin; 6002 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6003 PetscValidType(mat, 1); 6004 6005 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); 6006 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()"); 6007 6008 switch (op) { 6009 case MAT_NO_OFF_PROC_ENTRIES: 6010 *flg = mat->nooffprocentries; 6011 break; 6012 case MAT_NO_OFF_PROC_ZERO_ROWS: 6013 *flg = mat->nooffproczerorows; 6014 break; 6015 case MAT_SYMMETRIC: 6016 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()"); 6017 break; 6018 case MAT_HERMITIAN: 6019 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()"); 6020 break; 6021 case MAT_STRUCTURALLY_SYMMETRIC: 6022 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()"); 6023 break; 6024 case MAT_SPD: 6025 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()"); 6026 break; 6027 case MAT_SYMMETRY_ETERNAL: 6028 *flg = mat->symmetry_eternal; 6029 break; 6030 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6031 *flg = mat->symmetry_eternal; 6032 break; 6033 default: 6034 break; 6035 } 6036 PetscFunctionReturn(PETSC_SUCCESS); 6037 } 6038 6039 /*@ 6040 MatZeroEntries - Zeros all entries of a matrix. For sparse matrices 6041 this routine retains the old nonzero structure. 6042 6043 Logically Collective 6044 6045 Input Parameter: 6046 . mat - the matrix 6047 6048 Level: intermediate 6049 6050 Note: 6051 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. 6052 See the Performance chapter of the users manual for information on preallocating matrices. 6053 6054 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()` 6055 @*/ 6056 PetscErrorCode MatZeroEntries(Mat mat) 6057 { 6058 PetscFunctionBegin; 6059 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6060 PetscValidType(mat, 1); 6061 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6062 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"); 6063 MatCheckPreallocated(mat, 1); 6064 6065 PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0)); 6066 PetscUseTypeMethod(mat, zeroentries); 6067 PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0)); 6068 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6069 PetscFunctionReturn(PETSC_SUCCESS); 6070 } 6071 6072 /*@ 6073 MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal) 6074 of a set of rows and columns of a matrix. 6075 6076 Collective 6077 6078 Input Parameters: 6079 + mat - the matrix 6080 . numRows - the number of rows/columns to zero 6081 . rows - the global row indices 6082 . diag - value put in the diagonal of the eliminated rows 6083 . x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call 6084 - b - optional vector of the right hand side, that will be adjusted by provided solution entries 6085 6086 Level: intermediate 6087 6088 Notes: 6089 This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6090 6091 For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`. 6092 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 6093 6094 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6095 Krylov method to take advantage of the known solution on the zeroed rows. 6096 6097 For the parallel case, all processes that share the matrix (i.e., 6098 those in the communicator used for matrix creation) MUST call this 6099 routine, regardless of whether any rows being zeroed are owned by 6100 them. 6101 6102 Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix. 6103 6104 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6105 list only rows local to itself). 6106 6107 The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine. 6108 6109 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6110 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6111 @*/ 6112 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6113 { 6114 PetscFunctionBegin; 6115 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6116 PetscValidType(mat, 1); 6117 if (numRows) PetscValidIntPointer(rows, 3); 6118 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6119 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6120 MatCheckPreallocated(mat, 1); 6121 6122 PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b); 6123 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6124 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6125 PetscFunctionReturn(PETSC_SUCCESS); 6126 } 6127 6128 /*@ 6129 MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal) 6130 of a set of rows and columns of a matrix. 6131 6132 Collective 6133 6134 Input Parameters: 6135 + mat - the matrix 6136 . is - the rows to zero 6137 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6138 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6139 - b - optional vector of right hand side, that will be adjusted by provided solution 6140 6141 Level: intermediate 6142 6143 Note: 6144 See `MatZeroRowsColumns()` for details on how this routine operates. 6145 6146 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6147 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()` 6148 @*/ 6149 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6150 { 6151 PetscInt numRows; 6152 const PetscInt *rows; 6153 6154 PetscFunctionBegin; 6155 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6156 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6157 PetscValidType(mat, 1); 6158 PetscValidType(is, 2); 6159 PetscCall(ISGetLocalSize(is, &numRows)); 6160 PetscCall(ISGetIndices(is, &rows)); 6161 PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b)); 6162 PetscCall(ISRestoreIndices(is, &rows)); 6163 PetscFunctionReturn(PETSC_SUCCESS); 6164 } 6165 6166 /*@ 6167 MatZeroRows - Zeros all entries (except possibly the main diagonal) 6168 of a set of rows of a matrix. 6169 6170 Collective 6171 6172 Input Parameters: 6173 + mat - the matrix 6174 . numRows - the number of rows to zero 6175 . rows - the global row indices 6176 . diag - value put in the diagonal of the zeroed rows 6177 . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call 6178 - b - optional vector of right hand side, that will be adjusted by provided solution entries 6179 6180 Level: intermediate 6181 6182 Notes: 6183 This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6184 6185 For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`. 6186 6187 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6188 Krylov method to take advantage of the known solution on the zeroed rows. 6189 6190 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) 6191 from the matrix. 6192 6193 Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix 6194 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 6195 formats this does not alter the nonzero structure. 6196 6197 If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure 6198 of the matrix is not changed the values are 6199 merely zeroed. 6200 6201 The user can set a value in the diagonal entry (or for the `MATAIJ` format 6202 formats can optionally remove the main diagonal entry from the 6203 nonzero structure as well, by passing 0.0 as the final argument). 6204 6205 For the parallel case, all processes that share the matrix (i.e., 6206 those in the communicator used for matrix creation) MUST call this 6207 routine, regardless of whether any rows being zeroed are owned by 6208 them. 6209 6210 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6211 list only rows local to itself). 6212 6213 You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it 6214 owns that are to be zeroed. This saves a global synchronization in the implementation. 6215 6216 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6217 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE` 6218 @*/ 6219 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6220 { 6221 PetscFunctionBegin; 6222 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6223 PetscValidType(mat, 1); 6224 if (numRows) PetscValidIntPointer(rows, 3); 6225 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6226 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6227 MatCheckPreallocated(mat, 1); 6228 6229 PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b); 6230 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6231 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6232 PetscFunctionReturn(PETSC_SUCCESS); 6233 } 6234 6235 /*@ 6236 MatZeroRowsIS - Zeros all entries (except possibly the main diagonal) 6237 of a set of rows of a matrix. 6238 6239 Collective 6240 6241 Input Parameters: 6242 + mat - the matrix 6243 . is - index set of rows to remove (if `NULL` then no row is removed) 6244 . diag - value put in all diagonals of eliminated rows 6245 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6246 - b - optional vector of right hand side, that will be adjusted by provided solution 6247 6248 Level: intermediate 6249 6250 Note: 6251 See `MatZeroRows()` for details on how this routine operates. 6252 6253 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6254 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6255 @*/ 6256 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6257 { 6258 PetscInt numRows = 0; 6259 const PetscInt *rows = NULL; 6260 6261 PetscFunctionBegin; 6262 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6263 PetscValidType(mat, 1); 6264 if (is) { 6265 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6266 PetscCall(ISGetLocalSize(is, &numRows)); 6267 PetscCall(ISGetIndices(is, &rows)); 6268 } 6269 PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b)); 6270 if (is) PetscCall(ISRestoreIndices(is, &rows)); 6271 PetscFunctionReturn(PETSC_SUCCESS); 6272 } 6273 6274 /*@ 6275 MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal) 6276 of a set of rows of a matrix. These rows must be local to the process. 6277 6278 Collective 6279 6280 Input Parameters: 6281 + mat - the matrix 6282 . numRows - the number of rows to remove 6283 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6284 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6285 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6286 - b - optional vector of right hand side, that will be adjusted by provided solution 6287 6288 Level: intermediate 6289 6290 Notes: 6291 See `MatZeroRows()` for details on how this routine operates. 6292 6293 The grid coordinates are across the entire grid, not just the local portion 6294 6295 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6296 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6297 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6298 `DM_BOUNDARY_PERIODIC` boundary type. 6299 6300 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 6301 a single value per point) you can skip filling those indices. 6302 6303 Fortran Note: 6304 `idxm` and `idxn` should be declared as 6305 $ MatStencil idxm(4, m) 6306 and the values inserted using 6307 .vb 6308 idxm(MatStencil_i, 1) = i 6309 idxm(MatStencil_j, 1) = j 6310 idxm(MatStencil_k, 1) = k 6311 idxm(MatStencil_c, 1) = c 6312 etc 6313 .ve 6314 6315 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6316 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6317 @*/ 6318 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6319 { 6320 PetscInt dim = mat->stencil.dim; 6321 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6322 PetscInt *dims = mat->stencil.dims + 1; 6323 PetscInt *starts = mat->stencil.starts; 6324 PetscInt *dxm = (PetscInt *)rows; 6325 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6326 6327 PetscFunctionBegin; 6328 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6329 PetscValidType(mat, 1); 6330 if (numRows) PetscValidPointer(rows, 3); 6331 6332 PetscCall(PetscMalloc1(numRows, &jdxm)); 6333 for (i = 0; i < numRows; ++i) { 6334 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6335 for (j = 0; j < 3 - sdim; ++j) dxm++; 6336 /* Local index in X dir */ 6337 tmp = *dxm++ - starts[0]; 6338 /* Loop over remaining dimensions */ 6339 for (j = 0; j < dim - 1; ++j) { 6340 /* If nonlocal, set index to be negative */ 6341 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6342 /* Update local index */ 6343 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6344 } 6345 /* Skip component slot if necessary */ 6346 if (mat->stencil.noc) dxm++; 6347 /* Local row number */ 6348 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6349 } 6350 PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b)); 6351 PetscCall(PetscFree(jdxm)); 6352 PetscFunctionReturn(PETSC_SUCCESS); 6353 } 6354 6355 /*@ 6356 MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal) 6357 of a set of rows and columns of a matrix. 6358 6359 Collective 6360 6361 Input Parameters: 6362 + mat - the matrix 6363 . numRows - the number of rows/columns to remove 6364 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6365 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6366 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6367 - b - optional vector of right hand side, that will be adjusted by provided solution 6368 6369 Level: intermediate 6370 6371 Notes: 6372 See `MatZeroRowsColumns()` for details on how this routine operates. 6373 6374 The grid coordinates are across the entire grid, not just the local portion 6375 6376 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6377 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6378 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6379 `DM_BOUNDARY_PERIODIC` boundary type. 6380 6381 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 6382 a single value per point) you can skip filling those indices. 6383 6384 Fortran Note: 6385 `idxm` and `idxn` should be declared as 6386 $ MatStencil idxm(4, m) 6387 and the values inserted using 6388 .vb 6389 idxm(MatStencil_i, 1) = i 6390 idxm(MatStencil_j, 1) = j 6391 idxm(MatStencil_k, 1) = k 6392 idxm(MatStencil_c, 1) = c 6393 etc 6394 .ve 6395 6396 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6397 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()` 6398 @*/ 6399 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6400 { 6401 PetscInt dim = mat->stencil.dim; 6402 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6403 PetscInt *dims = mat->stencil.dims + 1; 6404 PetscInt *starts = mat->stencil.starts; 6405 PetscInt *dxm = (PetscInt *)rows; 6406 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6407 6408 PetscFunctionBegin; 6409 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6410 PetscValidType(mat, 1); 6411 if (numRows) PetscValidPointer(rows, 3); 6412 6413 PetscCall(PetscMalloc1(numRows, &jdxm)); 6414 for (i = 0; i < numRows; ++i) { 6415 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6416 for (j = 0; j < 3 - sdim; ++j) dxm++; 6417 /* Local index in X dir */ 6418 tmp = *dxm++ - starts[0]; 6419 /* Loop over remaining dimensions */ 6420 for (j = 0; j < dim - 1; ++j) { 6421 /* If nonlocal, set index to be negative */ 6422 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6423 /* Update local index */ 6424 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6425 } 6426 /* Skip component slot if necessary */ 6427 if (mat->stencil.noc) dxm++; 6428 /* Local row number */ 6429 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6430 } 6431 PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b)); 6432 PetscCall(PetscFree(jdxm)); 6433 PetscFunctionReturn(PETSC_SUCCESS); 6434 } 6435 6436 /*@C 6437 MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal) 6438 of a set of rows of a matrix; using local numbering of rows. 6439 6440 Collective 6441 6442 Input Parameters: 6443 + mat - the matrix 6444 . numRows - the number of rows to remove 6445 . rows - the local row indices 6446 . diag - value put in all diagonals of eliminated rows 6447 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6448 - b - optional vector of right hand side, that will be adjusted by provided solution 6449 6450 Level: intermediate 6451 6452 Notes: 6453 Before calling `MatZeroRowsLocal()`, the user must first set the 6454 local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`. 6455 6456 See `MatZeroRows()` for details on how this routine operates. 6457 6458 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`, 6459 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6460 @*/ 6461 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6462 { 6463 PetscFunctionBegin; 6464 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6465 PetscValidType(mat, 1); 6466 if (numRows) PetscValidIntPointer(rows, 3); 6467 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6468 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6469 MatCheckPreallocated(mat, 1); 6470 6471 if (mat->ops->zerorowslocal) { 6472 PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b); 6473 } else { 6474 IS is, newis; 6475 const PetscInt *newRows; 6476 6477 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6478 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6479 PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis)); 6480 PetscCall(ISGetIndices(newis, &newRows)); 6481 PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b); 6482 PetscCall(ISRestoreIndices(newis, &newRows)); 6483 PetscCall(ISDestroy(&newis)); 6484 PetscCall(ISDestroy(&is)); 6485 } 6486 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6487 PetscFunctionReturn(PETSC_SUCCESS); 6488 } 6489 6490 /*@ 6491 MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal) 6492 of a set of rows of a matrix; using local numbering of rows. 6493 6494 Collective 6495 6496 Input Parameters: 6497 + mat - the matrix 6498 . is - index set of rows to remove 6499 . diag - value put in all diagonals of eliminated rows 6500 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6501 - b - optional vector of right hand side, that will be adjusted by provided solution 6502 6503 Level: intermediate 6504 6505 Notes: 6506 Before calling `MatZeroRowsLocalIS()`, the user must first set the 6507 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6508 6509 See `MatZeroRows()` for details on how this routine operates. 6510 6511 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6512 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6513 @*/ 6514 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6515 { 6516 PetscInt numRows; 6517 const PetscInt *rows; 6518 6519 PetscFunctionBegin; 6520 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6521 PetscValidType(mat, 1); 6522 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6523 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6524 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6525 MatCheckPreallocated(mat, 1); 6526 6527 PetscCall(ISGetLocalSize(is, &numRows)); 6528 PetscCall(ISGetIndices(is, &rows)); 6529 PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b)); 6530 PetscCall(ISRestoreIndices(is, &rows)); 6531 PetscFunctionReturn(PETSC_SUCCESS); 6532 } 6533 6534 /*@ 6535 MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal) 6536 of a set of rows and columns of a matrix; using local numbering of rows. 6537 6538 Collective 6539 6540 Input Parameters: 6541 + mat - the matrix 6542 . numRows - the number of rows to remove 6543 . rows - the global row indices 6544 . diag - value put in all diagonals of eliminated rows 6545 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6546 - b - optional vector of right hand side, that will be adjusted by provided solution 6547 6548 Level: intermediate 6549 6550 Notes: 6551 Before calling `MatZeroRowsColumnsLocal()`, the user must first set the 6552 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6553 6554 See `MatZeroRowsColumns()` for details on how this routine operates. 6555 6556 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6557 `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6558 @*/ 6559 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6560 { 6561 IS is, newis; 6562 const PetscInt *newRows; 6563 6564 PetscFunctionBegin; 6565 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6566 PetscValidType(mat, 1); 6567 if (numRows) PetscValidIntPointer(rows, 3); 6568 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6569 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6570 MatCheckPreallocated(mat, 1); 6571 6572 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6573 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6574 PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis)); 6575 PetscCall(ISGetIndices(newis, &newRows)); 6576 PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b); 6577 PetscCall(ISRestoreIndices(newis, &newRows)); 6578 PetscCall(ISDestroy(&newis)); 6579 PetscCall(ISDestroy(&is)); 6580 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6581 PetscFunctionReturn(PETSC_SUCCESS); 6582 } 6583 6584 /*@ 6585 MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal) 6586 of a set of rows and columns of a matrix; using local numbering of rows. 6587 6588 Collective 6589 6590 Input Parameters: 6591 + mat - the matrix 6592 . is - index set of rows to remove 6593 . diag - value put in all diagonals of eliminated rows 6594 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6595 - b - optional vector of right hand side, that will be adjusted by provided solution 6596 6597 Level: intermediate 6598 6599 Notes: 6600 Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the 6601 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6602 6603 See `MatZeroRowsColumns()` for details on how this routine operates. 6604 6605 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6606 `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6607 @*/ 6608 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6609 { 6610 PetscInt numRows; 6611 const PetscInt *rows; 6612 6613 PetscFunctionBegin; 6614 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6615 PetscValidType(mat, 1); 6616 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6617 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6618 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6619 MatCheckPreallocated(mat, 1); 6620 6621 PetscCall(ISGetLocalSize(is, &numRows)); 6622 PetscCall(ISGetIndices(is, &rows)); 6623 PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b)); 6624 PetscCall(ISRestoreIndices(is, &rows)); 6625 PetscFunctionReturn(PETSC_SUCCESS); 6626 } 6627 6628 /*@C 6629 MatGetSize - Returns the numbers of rows and columns in a matrix. 6630 6631 Not Collective 6632 6633 Input Parameter: 6634 . mat - the matrix 6635 6636 Output Parameters: 6637 + m - the number of global rows 6638 - n - the number of global columns 6639 6640 Level: beginner 6641 6642 Note: 6643 Both output parameters can be `NULL` on input. 6644 6645 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()` 6646 @*/ 6647 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n) 6648 { 6649 PetscFunctionBegin; 6650 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6651 if (m) *m = mat->rmap->N; 6652 if (n) *n = mat->cmap->N; 6653 PetscFunctionReturn(PETSC_SUCCESS); 6654 } 6655 6656 /*@C 6657 MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns 6658 of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`. 6659 6660 Not Collective 6661 6662 Input Parameter: 6663 . mat - the matrix 6664 6665 Output Parameters: 6666 + m - the number of local rows, use `NULL` to not obtain this value 6667 - n - the number of local columns, use `NULL` to not obtain this value 6668 6669 Level: beginner 6670 6671 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()` 6672 @*/ 6673 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n) 6674 { 6675 PetscFunctionBegin; 6676 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6677 if (m) PetscValidIntPointer(m, 2); 6678 if (n) PetscValidIntPointer(n, 3); 6679 if (m) *m = mat->rmap->n; 6680 if (n) *n = mat->cmap->n; 6681 PetscFunctionReturn(PETSC_SUCCESS); 6682 } 6683 6684 /*@C 6685 MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by 6686 this processor. (The columns of the "diagonal block" for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts. 6687 6688 Not Collective, unless matrix has not been allocated, then collective 6689 6690 Input Parameter: 6691 . mat - the matrix 6692 6693 Output Parameters: 6694 + m - the global index of the first local column, use `NULL` to not obtain this value 6695 - n - one more than the global index of the last local column, use `NULL` to not obtain this value 6696 6697 Level: developer 6698 6699 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout` 6700 @*/ 6701 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n) 6702 { 6703 PetscFunctionBegin; 6704 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6705 PetscValidType(mat, 1); 6706 if (m) PetscValidIntPointer(m, 2); 6707 if (n) PetscValidIntPointer(n, 3); 6708 MatCheckPreallocated(mat, 1); 6709 if (m) *m = mat->cmap->rstart; 6710 if (n) *n = mat->cmap->rend; 6711 PetscFunctionReturn(PETSC_SUCCESS); 6712 } 6713 6714 /*@C 6715 MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6716 this MPI rank. For all matrices it returns the range of matrix rows associated with rows of a vector that would contain the result of a matrix 6717 vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts 6718 6719 Not Collective 6720 6721 Input Parameter: 6722 . mat - the matrix 6723 6724 Output Parameters: 6725 + m - the global index of the first local row, use `NULL` to not obtain this value 6726 - n - one more than the global index of the last local row, use `NULL` to not obtain this value 6727 6728 Level: beginner 6729 6730 Note: 6731 This function requires that the matrix be preallocated. If you have not preallocated, consider using 6732 `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N) 6733 and then `MPI_Scan()` to calculate prefix sums of the local sizes. 6734 6735 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, 6736 `PetscLayout` 6737 @*/ 6738 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n) 6739 { 6740 PetscFunctionBegin; 6741 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6742 PetscValidType(mat, 1); 6743 if (m) PetscValidIntPointer(m, 2); 6744 if (n) PetscValidIntPointer(n, 3); 6745 MatCheckPreallocated(mat, 1); 6746 if (m) *m = mat->rmap->rstart; 6747 if (n) *n = mat->rmap->rend; 6748 PetscFunctionReturn(PETSC_SUCCESS); 6749 } 6750 6751 /*@C 6752 MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6753 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 6754 vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts 6755 6756 Not Collective, unless matrix has not been allocated 6757 6758 Input Parameter: 6759 . mat - the matrix 6760 6761 Output Parameter: 6762 . ranges - start of each processors portion plus one more than the total length at the end 6763 6764 Level: beginner 6765 6766 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout` 6767 @*/ 6768 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges) 6769 { 6770 PetscFunctionBegin; 6771 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6772 PetscValidType(mat, 1); 6773 MatCheckPreallocated(mat, 1); 6774 PetscCall(PetscLayoutGetRanges(mat->rmap, ranges)); 6775 PetscFunctionReturn(PETSC_SUCCESS); 6776 } 6777 6778 /*@C 6779 MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by 6780 each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts. 6781 6782 Not Collective, unless matrix has not been allocated 6783 6784 Input Parameter: 6785 . mat - the matrix 6786 6787 Output Parameter: 6788 . ranges - start of each processors portion plus one more then the total length at the end 6789 6790 Level: beginner 6791 6792 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()` 6793 @*/ 6794 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges) 6795 { 6796 PetscFunctionBegin; 6797 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6798 PetscValidType(mat, 1); 6799 MatCheckPreallocated(mat, 1); 6800 PetscCall(PetscLayoutGetRanges(mat->cmap, ranges)); 6801 PetscFunctionReturn(PETSC_SUCCESS); 6802 } 6803 6804 /*@C 6805 MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this 6806 corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership 6807 is more complicated. See :any:`<sec_matlayout>` for details on matrix layouts. 6808 6809 Not Collective 6810 6811 Input Parameter: 6812 . A - matrix 6813 6814 Output Parameters: 6815 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value 6816 - cols - columns in which this process owns elements, use `NULL` to not obtain this value 6817 6818 Level: intermediate 6819 6820 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK`` 6821 @*/ 6822 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols) 6823 { 6824 PetscErrorCode (*f)(Mat, IS *, IS *); 6825 6826 PetscFunctionBegin; 6827 MatCheckPreallocated(A, 1); 6828 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f)); 6829 if (f) { 6830 PetscCall((*f)(A, rows, cols)); 6831 } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */ 6832 if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows)); 6833 if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols)); 6834 } 6835 PetscFunctionReturn(PETSC_SUCCESS); 6836 } 6837 6838 /*@C 6839 MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()` 6840 Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()` 6841 to complete the factorization. 6842 6843 Collective 6844 6845 Input Parameters: 6846 + fact - the factorized matrix obtained with `MatGetFactor()` 6847 . mat - the matrix 6848 . row - row permutation 6849 . col - column permutation 6850 - info - structure containing 6851 .vb 6852 levels - number of levels of fill. 6853 expected fill - as ratio of original fill. 6854 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 6855 missing diagonal entries) 6856 .ve 6857 6858 Level: developer 6859 6860 Notes: 6861 See [Matrix Factorization](sec_matfactor) for additional information. 6862 6863 Most users should employ the `KSP` interface for linear solvers 6864 instead of working directly with matrix algebra routines such as this. 6865 See, e.g., `KSPCreate()`. 6866 6867 Uses the definition of level of fill as in Y. Saad, 2003 6868 6869 Developer Note: 6870 The Fortran interface is not autogenerated as the 6871 interface definition cannot be generated correctly [due to `MatFactorInfo`] 6872 6873 References: 6874 . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003 6875 6876 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 6877 `MatGetOrdering()`, `MatFactorInfo` 6878 @*/ 6879 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 6880 { 6881 PetscFunctionBegin; 6882 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 6883 PetscValidType(mat, 2); 6884 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 6885 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 6886 PetscValidPointer(info, 5); 6887 PetscValidPointer(fact, 1); 6888 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels); 6889 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 6890 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6891 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6892 MatCheckPreallocated(mat, 2); 6893 6894 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0)); 6895 PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info); 6896 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0)); 6897 PetscFunctionReturn(PETSC_SUCCESS); 6898 } 6899 6900 /*@C 6901 MatICCFactorSymbolic - Performs symbolic incomplete 6902 Cholesky factorization for a symmetric matrix. Use 6903 `MatCholeskyFactorNumeric()` to complete the factorization. 6904 6905 Collective 6906 6907 Input Parameters: 6908 + fact - the factorized matrix obtained with `MatGetFactor()` 6909 . mat - the matrix to be factored 6910 . perm - row and column permutation 6911 - info - structure containing 6912 .vb 6913 levels - number of levels of fill. 6914 expected fill - as ratio of original fill. 6915 .ve 6916 6917 Level: developer 6918 6919 Notes: 6920 Most users should employ the `KSP` interface for linear solvers 6921 instead of working directly with matrix algebra routines such as this. 6922 See, e.g., `KSPCreate()`. 6923 6924 This uses the definition of level of fill as in Y. Saad, 2003 6925 6926 Developer Note: 6927 The Fortran interface is not autogenerated as the 6928 interface definition cannot be generated correctly [due to `MatFactorInfo`] 6929 6930 References: 6931 . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003 6932 6933 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 6934 @*/ 6935 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 6936 { 6937 PetscFunctionBegin; 6938 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 6939 PetscValidType(mat, 2); 6940 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 6941 PetscValidPointer(info, 4); 6942 PetscValidPointer(fact, 1); 6943 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6944 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels); 6945 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 6946 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6947 MatCheckPreallocated(mat, 2); 6948 6949 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 6950 PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info); 6951 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 6952 PetscFunctionReturn(PETSC_SUCCESS); 6953 } 6954 6955 /*@C 6956 MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat 6957 points to an array of valid matrices, they may be reused to store the new 6958 submatrices. 6959 6960 Collective 6961 6962 Input Parameters: 6963 + mat - the matrix 6964 . n - the number of submatrixes to be extracted (on this processor, may be zero) 6965 . irow - index set of rows to extract 6966 . icol - index set of columns to extract 6967 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 6968 6969 Output Parameter: 6970 . submat - the array of submatrices 6971 6972 Level: advanced 6973 6974 Notes: 6975 `MatCreateSubMatrices()` can extract ONLY sequential submatrices 6976 (from both sequential and parallel matrices). Use `MatCreateSubMatrix()` 6977 to extract a parallel submatrix. 6978 6979 Some matrix types place restrictions on the row and column 6980 indices, such as that they be sorted or that they be equal to each other. 6981 6982 The index sets may not have duplicate entries. 6983 6984 When extracting submatrices from a parallel matrix, each processor can 6985 form a different submatrix by setting the rows and columns of its 6986 individual index sets according to the local submatrix desired. 6987 6988 When finished using the submatrices, the user should destroy 6989 them with `MatDestroySubMatrices()`. 6990 6991 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 6992 original matrix has not changed from that last call to `MatCreateSubMatrices()`. 6993 6994 This routine creates the matrices in submat; you should NOT create them before 6995 calling it. It also allocates the array of matrix pointers submat. 6996 6997 For `MATBAIJ` matrices the index sets must respect the block structure, that is if they 6998 request one row/column in a block, they must request all rows/columns that are in 6999 that block. For example, if the block size is 2 you cannot request just row 0 and 7000 column 0. 7001 7002 Fortran Note: 7003 The Fortran interface is slightly different from that given below; it 7004 requires one to pass in as `submat` a `Mat` (integer) array of size at least n+1. 7005 7006 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7007 @*/ 7008 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7009 { 7010 PetscInt i; 7011 PetscBool eq; 7012 7013 PetscFunctionBegin; 7014 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7015 PetscValidType(mat, 1); 7016 if (n) { 7017 PetscValidPointer(irow, 3); 7018 for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3); 7019 PetscValidPointer(icol, 4); 7020 for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4); 7021 } 7022 PetscValidPointer(submat, 6); 7023 if (n && scall == MAT_REUSE_MATRIX) { 7024 PetscValidPointer(*submat, 6); 7025 for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6); 7026 } 7027 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7028 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7029 MatCheckPreallocated(mat, 1); 7030 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7031 PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat); 7032 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7033 for (i = 0; i < n; i++) { 7034 (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */ 7035 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7036 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7037 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 7038 if (mat->boundtocpu && mat->bindingpropagates) { 7039 PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE)); 7040 PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE)); 7041 } 7042 #endif 7043 } 7044 PetscFunctionReturn(PETSC_SUCCESS); 7045 } 7046 7047 /*@C 7048 MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms). 7049 7050 Collective 7051 7052 Input Parameters: 7053 + mat - the matrix 7054 . n - the number of submatrixes to be extracted 7055 . irow - index set of rows to extract 7056 . icol - index set of columns to extract 7057 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7058 7059 Output Parameter: 7060 . submat - the array of submatrices 7061 7062 Level: advanced 7063 7064 Note: 7065 This is used by `PCGASM` 7066 7067 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7068 @*/ 7069 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7070 { 7071 PetscInt i; 7072 PetscBool eq; 7073 7074 PetscFunctionBegin; 7075 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7076 PetscValidType(mat, 1); 7077 if (n) { 7078 PetscValidPointer(irow, 3); 7079 PetscValidHeaderSpecific(*irow, IS_CLASSID, 3); 7080 PetscValidPointer(icol, 4); 7081 PetscValidHeaderSpecific(*icol, IS_CLASSID, 4); 7082 } 7083 PetscValidPointer(submat, 6); 7084 if (n && scall == MAT_REUSE_MATRIX) { 7085 PetscValidPointer(*submat, 6); 7086 PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6); 7087 } 7088 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7089 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7090 MatCheckPreallocated(mat, 1); 7091 7092 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7093 PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat); 7094 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7095 for (i = 0; i < n; i++) { 7096 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7097 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7098 } 7099 PetscFunctionReturn(PETSC_SUCCESS); 7100 } 7101 7102 /*@C 7103 MatDestroyMatrices - Destroys an array of matrices. 7104 7105 Collective 7106 7107 Input Parameters: 7108 + n - the number of local matrices 7109 - mat - the matrices (this is a pointer to the array of matrices) 7110 7111 Level: advanced 7112 7113 Note: 7114 Frees not only the matrices, but also the array that contains the matrices 7115 7116 Fortran Note: 7117 This does not free the array. 7118 7119 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()` 7120 @*/ 7121 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[]) 7122 { 7123 PetscInt i; 7124 7125 PetscFunctionBegin; 7126 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7127 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7128 PetscValidPointer(mat, 2); 7129 7130 for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i])); 7131 7132 /* memory is allocated even if n = 0 */ 7133 PetscCall(PetscFree(*mat)); 7134 PetscFunctionReturn(PETSC_SUCCESS); 7135 } 7136 7137 /*@C 7138 MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`. 7139 7140 Collective 7141 7142 Input Parameters: 7143 + n - the number of local matrices 7144 - mat - the matrices (this is a pointer to the array of matrices, just to match the calling 7145 sequence of `MatCreateSubMatrices()`) 7146 7147 Level: advanced 7148 7149 Note: 7150 Frees not only the matrices, but also the array that contains the matrices 7151 7152 Fortran Note: 7153 This does not free the array. 7154 7155 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7156 @*/ 7157 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[]) 7158 { 7159 Mat mat0; 7160 7161 PetscFunctionBegin; 7162 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7163 /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */ 7164 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7165 PetscValidPointer(mat, 2); 7166 7167 mat0 = (*mat)[0]; 7168 if (mat0 && mat0->ops->destroysubmatrices) { 7169 PetscCall((*mat0->ops->destroysubmatrices)(n, mat)); 7170 } else { 7171 PetscCall(MatDestroyMatrices(n, mat)); 7172 } 7173 PetscFunctionReturn(PETSC_SUCCESS); 7174 } 7175 7176 /*@C 7177 MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process 7178 7179 Collective 7180 7181 Input Parameter: 7182 . mat - the matrix 7183 7184 Output Parameter: 7185 . matstruct - the sequential matrix with the nonzero structure of mat 7186 7187 Level: developer 7188 7189 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7190 @*/ 7191 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct) 7192 { 7193 PetscFunctionBegin; 7194 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7195 PetscValidPointer(matstruct, 2); 7196 7197 PetscValidType(mat, 1); 7198 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7199 MatCheckPreallocated(mat, 1); 7200 7201 PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7202 PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct); 7203 PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7204 PetscFunctionReturn(PETSC_SUCCESS); 7205 } 7206 7207 /*@C 7208 MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`. 7209 7210 Collective 7211 7212 Input Parameter: 7213 . mat - the matrix (this is a pointer to the array of matrices, just to match the calling 7214 sequence of `MatGetSeqNonzeroStructure()`) 7215 7216 Level: advanced 7217 7218 Note: 7219 Frees not only the matrices, but also the array that contains the matrices 7220 7221 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()` 7222 @*/ 7223 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat) 7224 { 7225 PetscFunctionBegin; 7226 PetscValidPointer(mat, 1); 7227 PetscCall(MatDestroy(mat)); 7228 PetscFunctionReturn(PETSC_SUCCESS); 7229 } 7230 7231 /*@ 7232 MatIncreaseOverlap - Given a set of submatrices indicated by index sets, 7233 replaces the index sets by larger ones that represent submatrices with 7234 additional overlap. 7235 7236 Collective 7237 7238 Input Parameters: 7239 + mat - the matrix 7240 . n - the number of index sets 7241 . is - the array of index sets (these index sets will changed during the call) 7242 - ov - the additional overlap requested 7243 7244 Options Database Key: 7245 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7246 7247 Level: developer 7248 7249 Note: 7250 The computed overlap preserves the matrix block sizes when the blocks are square. 7251 That is: if a matrix nonzero for a given block would increase the overlap all columns associated with 7252 that block are included in the overlap regardless of whether each specific column would increase the overlap. 7253 7254 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()` 7255 @*/ 7256 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov) 7257 { 7258 PetscInt i, bs, cbs; 7259 7260 PetscFunctionBegin; 7261 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7262 PetscValidType(mat, 1); 7263 PetscValidLogicalCollectiveInt(mat, n, 2); 7264 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7265 if (n) { 7266 PetscValidPointer(is, 3); 7267 for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3); 7268 } 7269 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7270 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7271 MatCheckPreallocated(mat, 1); 7272 7273 if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS); 7274 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7275 PetscUseTypeMethod(mat, increaseoverlap, n, is, ov); 7276 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7277 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 7278 if (bs == cbs) { 7279 for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs)); 7280 } 7281 PetscFunctionReturn(PETSC_SUCCESS); 7282 } 7283 7284 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt); 7285 7286 /*@ 7287 MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across 7288 a sub communicator, replaces the index sets by larger ones that represent submatrices with 7289 additional overlap. 7290 7291 Collective 7292 7293 Input Parameters: 7294 + mat - the matrix 7295 . n - the number of index sets 7296 . is - the array of index sets (these index sets will changed during the call) 7297 - ov - the additional overlap requested 7298 7299 ` Options Database Key: 7300 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7301 7302 Level: developer 7303 7304 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()` 7305 @*/ 7306 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov) 7307 { 7308 PetscInt i; 7309 7310 PetscFunctionBegin; 7311 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7312 PetscValidType(mat, 1); 7313 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7314 if (n) { 7315 PetscValidPointer(is, 3); 7316 PetscValidHeaderSpecific(*is, IS_CLASSID, 3); 7317 } 7318 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7319 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7320 MatCheckPreallocated(mat, 1); 7321 if (!ov) PetscFunctionReturn(PETSC_SUCCESS); 7322 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7323 for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov)); 7324 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7325 PetscFunctionReturn(PETSC_SUCCESS); 7326 } 7327 7328 /*@ 7329 MatGetBlockSize - Returns the matrix block size. 7330 7331 Not Collective 7332 7333 Input Parameter: 7334 . mat - the matrix 7335 7336 Output Parameter: 7337 . bs - block size 7338 7339 Level: intermediate 7340 7341 Notes: 7342 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7343 7344 If the block size has not been set yet this routine returns 1. 7345 7346 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()` 7347 @*/ 7348 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs) 7349 { 7350 PetscFunctionBegin; 7351 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7352 PetscValidIntPointer(bs, 2); 7353 *bs = PetscAbs(mat->rmap->bs); 7354 PetscFunctionReturn(PETSC_SUCCESS); 7355 } 7356 7357 /*@ 7358 MatGetBlockSizes - Returns the matrix block row and column sizes. 7359 7360 Not Collective 7361 7362 Input Parameter: 7363 . mat - the matrix 7364 7365 Output Parameters: 7366 + rbs - row block size 7367 - cbs - column block size 7368 7369 Level: intermediate 7370 7371 Notes: 7372 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7373 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7374 7375 If a block size has not been set yet this routine returns 1. 7376 7377 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()` 7378 @*/ 7379 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs) 7380 { 7381 PetscFunctionBegin; 7382 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7383 if (rbs) PetscValidIntPointer(rbs, 2); 7384 if (cbs) PetscValidIntPointer(cbs, 3); 7385 if (rbs) *rbs = PetscAbs(mat->rmap->bs); 7386 if (cbs) *cbs = PetscAbs(mat->cmap->bs); 7387 PetscFunctionReturn(PETSC_SUCCESS); 7388 } 7389 7390 /*@ 7391 MatSetBlockSize - Sets the matrix block size. 7392 7393 Logically Collective 7394 7395 Input Parameters: 7396 + mat - the matrix 7397 - bs - block size 7398 7399 Level: intermediate 7400 7401 Notes: 7402 Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix. 7403 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7404 7405 For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size 7406 is compatible with the matrix local sizes. 7407 7408 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()` 7409 @*/ 7410 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs) 7411 { 7412 PetscFunctionBegin; 7413 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7414 PetscValidLogicalCollectiveInt(mat, bs, 2); 7415 PetscCall(MatSetBlockSizes(mat, bs, bs)); 7416 PetscFunctionReturn(PETSC_SUCCESS); 7417 } 7418 7419 typedef struct { 7420 PetscInt n; 7421 IS *is; 7422 Mat *mat; 7423 PetscObjectState nonzerostate; 7424 Mat C; 7425 } EnvelopeData; 7426 7427 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata) 7428 { 7429 for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i])); 7430 PetscCall(PetscFree(edata->is)); 7431 PetscCall(PetscFree(edata)); 7432 return PETSC_SUCCESS; 7433 } 7434 7435 /* 7436 MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores 7437 the sizes of these blocks in the matrix. An individual block may lie over several processes. 7438 7439 Collective 7440 7441 Input Parameter: 7442 . mat - the matrix 7443 7444 Notes: 7445 There can be zeros within the blocks 7446 7447 The blocks can overlap between processes, including laying on more than two processes 7448 7449 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()` 7450 */ 7451 static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat) 7452 { 7453 PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend; 7454 PetscInt *diag, *odiag, sc; 7455 VecScatter scatter; 7456 PetscScalar *seqv; 7457 const PetscScalar *parv; 7458 const PetscInt *ia, *ja; 7459 PetscBool set, flag, done; 7460 Mat AA = mat, A; 7461 MPI_Comm comm; 7462 PetscMPIInt rank, size, tag; 7463 MPI_Status status; 7464 PetscContainer container; 7465 EnvelopeData *edata; 7466 Vec seq, par; 7467 IS isglobal; 7468 7469 PetscFunctionBegin; 7470 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7471 PetscCall(MatIsSymmetricKnown(mat, &set, &flag)); 7472 if (!set || !flag) { 7473 /* TOO: only needs nonzero structure of transpose */ 7474 PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA)); 7475 PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN)); 7476 } 7477 PetscCall(MatAIJGetLocalMat(AA, &A)); 7478 PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7479 PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix"); 7480 7481 PetscCall(MatGetLocalSize(mat, &n, NULL)); 7482 PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag)); 7483 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 7484 PetscCallMPI(MPI_Comm_size(comm, &size)); 7485 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7486 7487 PetscCall(PetscMalloc2(n, &sizes, n, &starts)); 7488 7489 if (rank > 0) { 7490 PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7491 PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7492 } 7493 PetscCall(MatGetOwnershipRange(mat, &rstart, NULL)); 7494 for (i = 0; i < n; i++) { 7495 env = PetscMax(env, ja[ia[i + 1] - 1]); 7496 II = rstart + i; 7497 if (env == II) { 7498 starts[lblocks] = tbs; 7499 sizes[lblocks++] = 1 + II - tbs; 7500 tbs = 1 + II; 7501 } 7502 } 7503 if (rank < size - 1) { 7504 PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm)); 7505 PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm)); 7506 } 7507 7508 PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7509 if (!set || !flag) PetscCall(MatDestroy(&AA)); 7510 PetscCall(MatDestroy(&A)); 7511 7512 PetscCall(PetscNew(&edata)); 7513 PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate)); 7514 edata->n = lblocks; 7515 /* create IS needed for extracting blocks from the original matrix */ 7516 PetscCall(PetscMalloc1(lblocks, &edata->is)); 7517 for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i])); 7518 7519 /* Create the resulting inverse matrix structure with preallocation information */ 7520 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C)); 7521 PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 7522 PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat)); 7523 PetscCall(MatSetType(edata->C, MATAIJ)); 7524 7525 /* Communicate the start and end of each row, from each block to the correct rank */ 7526 /* TODO: Use PetscSF instead of VecScatter */ 7527 for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i]; 7528 PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq)); 7529 PetscCall(VecGetArrayWrite(seq, &seqv)); 7530 for (PetscInt i = 0; i < lblocks; i++) { 7531 for (PetscInt j = 0; j < sizes[i]; j++) { 7532 seqv[cnt] = starts[i]; 7533 seqv[cnt + 1] = starts[i] + sizes[i]; 7534 cnt += 2; 7535 } 7536 } 7537 PetscCall(VecRestoreArrayWrite(seq, &seqv)); 7538 PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 7539 sc -= cnt; 7540 PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par)); 7541 PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal)); 7542 PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter)); 7543 PetscCall(ISDestroy(&isglobal)); 7544 PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7545 PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7546 PetscCall(VecScatterDestroy(&scatter)); 7547 PetscCall(VecDestroy(&seq)); 7548 PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend)); 7549 PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag)); 7550 PetscCall(VecGetArrayRead(par, &parv)); 7551 cnt = 0; 7552 PetscCall(MatGetSize(mat, NULL, &n)); 7553 for (PetscInt i = 0; i < mat->rmap->n; i++) { 7554 PetscInt start, end, d = 0, od = 0; 7555 7556 start = (PetscInt)PetscRealPart(parv[cnt]); 7557 end = (PetscInt)PetscRealPart(parv[cnt + 1]); 7558 cnt += 2; 7559 7560 if (start < cstart) { 7561 od += cstart - start + n - cend; 7562 d += cend - cstart; 7563 } else if (start < cend) { 7564 od += n - cend; 7565 d += cend - start; 7566 } else od += n - start; 7567 if (end <= cstart) { 7568 od -= cstart - end + n - cend; 7569 d -= cend - cstart; 7570 } else if (end < cend) { 7571 od -= n - cend; 7572 d -= cend - end; 7573 } else od -= n - end; 7574 7575 odiag[i] = od; 7576 diag[i] = d; 7577 } 7578 PetscCall(VecRestoreArrayRead(par, &parv)); 7579 PetscCall(VecDestroy(&par)); 7580 PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL)); 7581 PetscCall(PetscFree2(diag, odiag)); 7582 PetscCall(PetscFree2(sizes, starts)); 7583 7584 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container)); 7585 PetscCall(PetscContainerSetPointer(container, edata)); 7586 PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy)); 7587 PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container)); 7588 PetscCall(PetscObjectDereference((PetscObject)container)); 7589 PetscFunctionReturn(PETSC_SUCCESS); 7590 } 7591 7592 /*@ 7593 MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A 7594 7595 Collective 7596 7597 Input Parameters: 7598 + A - the matrix 7599 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine 7600 7601 Output Parameter: 7602 . C - matrix with inverted block diagonal of `A` 7603 7604 Level: advanced 7605 7606 Note: 7607 For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal. 7608 7609 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()` 7610 @*/ 7611 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C) 7612 { 7613 PetscContainer container; 7614 EnvelopeData *edata; 7615 PetscObjectState nonzerostate; 7616 7617 PetscFunctionBegin; 7618 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7619 if (!container) { 7620 PetscCall(MatComputeVariableBlockEnvelope(A)); 7621 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7622 } 7623 PetscCall(PetscContainerGetPointer(container, (void **)&edata)); 7624 PetscCall(MatGetNonzeroState(A, &nonzerostate)); 7625 PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure"); 7626 PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output"); 7627 7628 PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat)); 7629 *C = edata->C; 7630 7631 for (PetscInt i = 0; i < edata->n; i++) { 7632 Mat D; 7633 PetscScalar *dvalues; 7634 7635 PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D)); 7636 PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE)); 7637 PetscCall(MatSeqDenseInvert(D)); 7638 PetscCall(MatDenseGetArray(D, &dvalues)); 7639 PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES)); 7640 PetscCall(MatDestroy(&D)); 7641 } 7642 PetscCall(MatDestroySubMatrices(edata->n, &edata->mat)); 7643 PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY)); 7644 PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY)); 7645 PetscFunctionReturn(PETSC_SUCCESS); 7646 } 7647 7648 /*@ 7649 MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size 7650 7651 Logically Collective 7652 7653 Input Parameters: 7654 + mat - the matrix 7655 . nblocks - the number of blocks on this process, each block can only exist on a single process 7656 - bsizes - the block sizes 7657 7658 Level: intermediate 7659 7660 Notes: 7661 Currently used by `PCVPBJACOBI` for `MATAIJ` matrices 7662 7663 Each variable point-block set of degrees of freedom must live on a single MPI rank. That is a point block cannot straddle two MPI ranks. 7664 7665 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, 7666 `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI` 7667 @*/ 7668 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes) 7669 { 7670 PetscInt i, ncnt = 0, nlocal; 7671 7672 PetscFunctionBegin; 7673 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7674 PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero"); 7675 PetscCall(MatGetLocalSize(mat, &nlocal, NULL)); 7676 for (i = 0; i < nblocks; i++) ncnt += bsizes[i]; 7677 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); 7678 PetscCall(PetscFree(mat->bsizes)); 7679 mat->nblocks = nblocks; 7680 PetscCall(PetscMalloc1(nblocks, &mat->bsizes)); 7681 PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks)); 7682 PetscFunctionReturn(PETSC_SUCCESS); 7683 } 7684 7685 /*@C 7686 MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size 7687 7688 Logically Collective; No Fortran Support 7689 7690 Input Parameter: 7691 . mat - the matrix 7692 7693 Output Parameters: 7694 + nblocks - the number of blocks on this process 7695 - bsizes - the block sizes 7696 7697 Level: intermediate 7698 7699 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()` 7700 @*/ 7701 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes) 7702 { 7703 PetscFunctionBegin; 7704 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7705 *nblocks = mat->nblocks; 7706 *bsizes = mat->bsizes; 7707 PetscFunctionReturn(PETSC_SUCCESS); 7708 } 7709 7710 /*@ 7711 MatSetBlockSizes - Sets the matrix block row and column sizes. 7712 7713 Logically Collective 7714 7715 Input Parameters: 7716 + mat - the matrix 7717 . rbs - row block size 7718 - cbs - column block size 7719 7720 Level: intermediate 7721 7722 Notes: 7723 Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix. 7724 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7725 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7726 7727 For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes 7728 are compatible with the matrix local sizes. 7729 7730 The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`. 7731 7732 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()` 7733 @*/ 7734 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs) 7735 { 7736 PetscFunctionBegin; 7737 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7738 PetscValidLogicalCollectiveInt(mat, rbs, 2); 7739 PetscValidLogicalCollectiveInt(mat, cbs, 3); 7740 PetscTryTypeMethod(mat, setblocksizes, rbs, cbs); 7741 if (mat->rmap->refcnt) { 7742 ISLocalToGlobalMapping l2g = NULL; 7743 PetscLayout nmap = NULL; 7744 7745 PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap)); 7746 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g)); 7747 PetscCall(PetscLayoutDestroy(&mat->rmap)); 7748 mat->rmap = nmap; 7749 mat->rmap->mapping = l2g; 7750 } 7751 if (mat->cmap->refcnt) { 7752 ISLocalToGlobalMapping l2g = NULL; 7753 PetscLayout nmap = NULL; 7754 7755 PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap)); 7756 if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g)); 7757 PetscCall(PetscLayoutDestroy(&mat->cmap)); 7758 mat->cmap = nmap; 7759 mat->cmap->mapping = l2g; 7760 } 7761 PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs)); 7762 PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs)); 7763 PetscFunctionReturn(PETSC_SUCCESS); 7764 } 7765 7766 /*@ 7767 MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices 7768 7769 Logically Collective 7770 7771 Input Parameters: 7772 + mat - the matrix 7773 . fromRow - matrix from which to copy row block size 7774 - fromCol - matrix from which to copy column block size (can be same as fromRow) 7775 7776 Level: developer 7777 7778 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()` 7779 @*/ 7780 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol) 7781 { 7782 PetscFunctionBegin; 7783 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7784 PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2); 7785 PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3); 7786 if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs)); 7787 if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs)); 7788 PetscFunctionReturn(PETSC_SUCCESS); 7789 } 7790 7791 /*@ 7792 MatResidual - Default routine to calculate the residual r = b - Ax 7793 7794 Collective 7795 7796 Input Parameters: 7797 + mat - the matrix 7798 . b - the right-hand-side 7799 - x - the approximate solution 7800 7801 Output Parameter: 7802 . r - location to store the residual 7803 7804 Level: developer 7805 7806 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()` 7807 @*/ 7808 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r) 7809 { 7810 PetscFunctionBegin; 7811 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7812 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 7813 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 7814 PetscValidHeaderSpecific(r, VEC_CLASSID, 4); 7815 PetscValidType(mat, 1); 7816 MatCheckPreallocated(mat, 1); 7817 PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0)); 7818 if (!mat->ops->residual) { 7819 PetscCall(MatMult(mat, x, r)); 7820 PetscCall(VecAYPX(r, -1.0, b)); 7821 } else { 7822 PetscUseTypeMethod(mat, residual, b, x, r); 7823 } 7824 PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0)); 7825 PetscFunctionReturn(PETSC_SUCCESS); 7826 } 7827 7828 /*MC 7829 MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix 7830 7831 Synopsis: 7832 MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 7833 7834 Not Collective 7835 7836 Input Parameters: 7837 + A - the matrix 7838 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7839 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7840 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7841 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7842 always used. 7843 7844 Output Parameters: 7845 + n - number of local rows in the (possibly compressed) matrix 7846 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 7847 . ja - the column indices 7848 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7849 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7850 7851 Level: developer 7852 7853 Note: 7854 Use `MatRestoreRowIJF90()` when you no longer need access to the data 7855 7856 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()` 7857 M*/ 7858 7859 /*MC 7860 MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()` 7861 7862 Synopsis: 7863 MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 7864 7865 Not Collective 7866 7867 Input Parameters: 7868 + A - the matrix 7869 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7870 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7871 inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7872 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7873 always used. 7874 . n - number of local rows in the (possibly compressed) matrix 7875 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 7876 . ja - the column indices 7877 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7878 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7879 7880 Level: developer 7881 7882 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()` 7883 M*/ 7884 7885 /*@C 7886 MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix 7887 7888 Collective 7889 7890 Input Parameters: 7891 + mat - the matrix 7892 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7893 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7894 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7895 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7896 always used. 7897 7898 Output Parameters: 7899 + n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed 7900 . 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 7901 . ja - the column indices, use `NULL` if not needed 7902 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7903 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7904 7905 Level: developer 7906 7907 Notes: 7908 You CANNOT change any of the ia[] or ja[] values. 7909 7910 Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values. 7911 7912 Fortran Notes: 7913 Use 7914 .vb 7915 PetscInt, pointer :: ia(:),ja(:) 7916 call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr) 7917 ! Access the ith and jth entries via ia(i) and ja(j) 7918 .ve 7919 `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()` 7920 7921 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()` 7922 @*/ 7923 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7924 { 7925 PetscFunctionBegin; 7926 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7927 PetscValidType(mat, 1); 7928 if (n) PetscValidIntPointer(n, 5); 7929 if (ia) PetscValidPointer(ia, 6); 7930 if (ja) PetscValidPointer(ja, 7); 7931 if (done) PetscValidBoolPointer(done, 8); 7932 MatCheckPreallocated(mat, 1); 7933 if (!mat->ops->getrowij && done) *done = PETSC_FALSE; 7934 else { 7935 if (done) *done = PETSC_TRUE; 7936 PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0)); 7937 PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done); 7938 PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0)); 7939 } 7940 PetscFunctionReturn(PETSC_SUCCESS); 7941 } 7942 7943 /*@C 7944 MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices. 7945 7946 Collective 7947 7948 Input Parameters: 7949 + mat - the matrix 7950 . shift - 1 or zero indicating we want the indices starting at 0 or 1 7951 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be 7952 symmetrized 7953 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7954 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7955 always used. 7956 . n - number of columns in the (possibly compressed) matrix 7957 . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix 7958 - ja - the row indices 7959 7960 Output Parameter: 7961 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned 7962 7963 Level: developer 7964 7965 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 7966 @*/ 7967 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7968 { 7969 PetscFunctionBegin; 7970 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7971 PetscValidType(mat, 1); 7972 PetscValidIntPointer(n, 5); 7973 if (ia) PetscValidPointer(ia, 6); 7974 if (ja) PetscValidPointer(ja, 7); 7975 PetscValidBoolPointer(done, 8); 7976 MatCheckPreallocated(mat, 1); 7977 if (!mat->ops->getcolumnij) *done = PETSC_FALSE; 7978 else { 7979 *done = PETSC_TRUE; 7980 PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 7981 } 7982 PetscFunctionReturn(PETSC_SUCCESS); 7983 } 7984 7985 /*@C 7986 MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`. 7987 7988 Collective 7989 7990 Input Parameters: 7991 + mat - the matrix 7992 . shift - 1 or zero indicating we want the indices starting at 0 or 1 7993 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7994 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7995 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7996 always used. 7997 . n - size of (possibly compressed) matrix 7998 . ia - the row pointers 7999 - ja - the column indices 8000 8001 Output Parameter: 8002 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8003 8004 Level: developer 8005 8006 Note: 8007 This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental 8008 us of the array after it has been restored. If you pass `NULL`, it will 8009 not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid. 8010 8011 Fortran Note: 8012 `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()` 8013 8014 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()` 8015 @*/ 8016 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8017 { 8018 PetscFunctionBegin; 8019 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8020 PetscValidType(mat, 1); 8021 if (ia) PetscValidPointer(ia, 6); 8022 if (ja) PetscValidPointer(ja, 7); 8023 if (done) PetscValidBoolPointer(done, 8); 8024 MatCheckPreallocated(mat, 1); 8025 8026 if (!mat->ops->restorerowij && done) *done = PETSC_FALSE; 8027 else { 8028 if (done) *done = PETSC_TRUE; 8029 PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8030 if (n) *n = 0; 8031 if (ia) *ia = NULL; 8032 if (ja) *ja = NULL; 8033 } 8034 PetscFunctionReturn(PETSC_SUCCESS); 8035 } 8036 8037 /*@C 8038 MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`. 8039 8040 Collective 8041 8042 Input Parameters: 8043 + mat - the matrix 8044 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8045 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8046 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8047 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8048 always used. 8049 8050 Output Parameters: 8051 + n - size of (possibly compressed) matrix 8052 . ia - the column pointers 8053 . ja - the row indices 8054 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8055 8056 Level: developer 8057 8058 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()` 8059 @*/ 8060 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8061 { 8062 PetscFunctionBegin; 8063 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8064 PetscValidType(mat, 1); 8065 if (ia) PetscValidPointer(ia, 6); 8066 if (ja) PetscValidPointer(ja, 7); 8067 PetscValidBoolPointer(done, 8); 8068 MatCheckPreallocated(mat, 1); 8069 8070 if (!mat->ops->restorecolumnij) *done = PETSC_FALSE; 8071 else { 8072 *done = PETSC_TRUE; 8073 PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8074 if (n) *n = 0; 8075 if (ia) *ia = NULL; 8076 if (ja) *ja = NULL; 8077 } 8078 PetscFunctionReturn(PETSC_SUCCESS); 8079 } 8080 8081 /*@C 8082 MatColoringPatch -Used inside matrix coloring routines that use `MatGetRowIJ()` and/or `MatGetColumnIJ()`. 8083 8084 Collective 8085 8086 Input Parameters: 8087 + mat - the matrix 8088 . ncolors - maximum color value 8089 . n - number of entries in colorarray 8090 - colorarray - array indicating color for each column 8091 8092 Output Parameter: 8093 . iscoloring - coloring generated using colorarray information 8094 8095 Level: developer 8096 8097 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()` 8098 @*/ 8099 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring) 8100 { 8101 PetscFunctionBegin; 8102 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8103 PetscValidType(mat, 1); 8104 PetscValidIntPointer(colorarray, 4); 8105 PetscValidPointer(iscoloring, 5); 8106 MatCheckPreallocated(mat, 1); 8107 8108 if (!mat->ops->coloringpatch) { 8109 PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring)); 8110 } else { 8111 PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring); 8112 } 8113 PetscFunctionReturn(PETSC_SUCCESS); 8114 } 8115 8116 /*@ 8117 MatSetUnfactored - Resets a factored matrix to be treated as unfactored. 8118 8119 Logically Collective 8120 8121 Input Parameter: 8122 . mat - the factored matrix to be reset 8123 8124 Level: developer 8125 8126 Notes: 8127 This routine should be used only with factored matrices formed by in-place 8128 factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE` 8129 format). This option can save memory, for example, when solving nonlinear 8130 systems with a matrix-free Newton-Krylov method and a matrix-based, in-place 8131 ILU(0) preconditioner. 8132 8133 One can specify in-place ILU(0) factorization by calling 8134 .vb 8135 PCType(pc,PCILU); 8136 PCFactorSeUseInPlace(pc); 8137 .ve 8138 or by using the options -pc_type ilu -pc_factor_in_place 8139 8140 In-place factorization ILU(0) can also be used as a local 8141 solver for the blocks within the block Jacobi or additive Schwarz 8142 methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc 8143 for details on setting local solver options. 8144 8145 Most users should employ the `KSP` interface for linear solvers 8146 instead of working directly with matrix algebra routines such as this. 8147 See, e.g., `KSPCreate()`. 8148 8149 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()` 8150 @*/ 8151 PetscErrorCode MatSetUnfactored(Mat mat) 8152 { 8153 PetscFunctionBegin; 8154 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8155 PetscValidType(mat, 1); 8156 MatCheckPreallocated(mat, 1); 8157 mat->factortype = MAT_FACTOR_NONE; 8158 if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS); 8159 PetscUseTypeMethod(mat, setunfactored); 8160 PetscFunctionReturn(PETSC_SUCCESS); 8161 } 8162 8163 /*MC 8164 MatDenseGetArrayF90 - Accesses a matrix array from Fortran 8165 8166 Synopsis: 8167 MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8168 8169 Not Collective 8170 8171 Input Parameter: 8172 . x - matrix 8173 8174 Output Parameters: 8175 + xx_v - the Fortran pointer to the array 8176 - ierr - error code 8177 8178 Example of Usage: 8179 .vb 8180 PetscScalar, pointer xx_v(:,:) 8181 .... 8182 call MatDenseGetArrayF90(x,xx_v,ierr) 8183 a = xx_v(3) 8184 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8185 .ve 8186 8187 Level: advanced 8188 8189 .seealso: [](ch_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()` 8190 M*/ 8191 8192 /*MC 8193 MatDenseRestoreArrayF90 - Restores a matrix array that has been 8194 accessed with `MatDenseGetArrayF90()`. 8195 8196 Synopsis: 8197 MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8198 8199 Not Collective 8200 8201 Input Parameters: 8202 + x - matrix 8203 - xx_v - the Fortran90 pointer to the array 8204 8205 Output Parameter: 8206 . ierr - error code 8207 8208 Example of Usage: 8209 .vb 8210 PetscScalar, pointer xx_v(:,:) 8211 .... 8212 call MatDenseGetArrayF90(x,xx_v,ierr) 8213 a = xx_v(3) 8214 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8215 .ve 8216 8217 Level: advanced 8218 8219 .seealso: [](ch_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()` 8220 M*/ 8221 8222 /*MC 8223 MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran. 8224 8225 Synopsis: 8226 MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8227 8228 Not Collective 8229 8230 Input Parameter: 8231 . x - matrix 8232 8233 Output Parameters: 8234 + xx_v - the Fortran pointer to the array 8235 - ierr - error code 8236 8237 Example of Usage: 8238 .vb 8239 PetscScalar, pointer xx_v(:) 8240 .... 8241 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8242 a = xx_v(3) 8243 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8244 .ve 8245 8246 Level: advanced 8247 8248 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()` 8249 M*/ 8250 8251 /*MC 8252 MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been 8253 accessed with `MatSeqAIJGetArrayF90()`. 8254 8255 Synopsis: 8256 MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8257 8258 Not Collective 8259 8260 Input Parameters: 8261 + x - matrix 8262 - xx_v - the Fortran90 pointer to the array 8263 8264 Output Parameter: 8265 . ierr - error code 8266 8267 Example of Usage: 8268 .vb 8269 PetscScalar, pointer xx_v(:) 8270 .... 8271 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8272 a = xx_v(3) 8273 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8274 .ve 8275 8276 Level: advanced 8277 8278 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()` 8279 M*/ 8280 8281 /*@ 8282 MatCreateSubMatrix - Gets a single submatrix on the same number of processors 8283 as the original matrix. 8284 8285 Collective 8286 8287 Input Parameters: 8288 + mat - the original matrix 8289 . isrow - parallel `IS` containing the rows this processor should obtain 8290 . 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. 8291 - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 8292 8293 Output Parameter: 8294 . newmat - the new submatrix, of the same type as the original matrix 8295 8296 Level: advanced 8297 8298 Notes: 8299 The submatrix will be able to be multiplied with vectors using the same layout as `iscol`. 8300 8301 Some matrix types place restrictions on the row and column indices, such 8302 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; 8303 for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row. 8304 8305 The index sets may not have duplicate entries. 8306 8307 The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`, 8308 the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls 8309 to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX` 8310 will reuse the matrix generated the first time. You should call `MatDestroy()` on `newmat` when 8311 you are finished using it. 8312 8313 The communicator of the newly obtained matrix is ALWAYS the same as the communicator of 8314 the input matrix. 8315 8316 If `iscol` is `NULL` then all columns are obtained (not supported in Fortran). 8317 8318 Example usage: 8319 Consider the following 8x8 matrix with 34 non-zero values, that is 8320 assembled across 3 processors. Let's assume that proc0 owns 3 rows, 8321 proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 8322 as follows 8323 .vb 8324 1 2 0 | 0 3 0 | 0 4 8325 Proc0 0 5 6 | 7 0 0 | 8 0 8326 9 0 10 | 11 0 0 | 12 0 8327 ------------------------------------- 8328 13 0 14 | 15 16 17 | 0 0 8329 Proc1 0 18 0 | 19 20 21 | 0 0 8330 0 0 0 | 22 23 0 | 24 0 8331 ------------------------------------- 8332 Proc2 25 26 27 | 0 0 28 | 29 0 8333 30 0 0 | 31 32 33 | 0 34 8334 .ve 8335 8336 Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6]. The resulting submatrix is 8337 8338 .vb 8339 2 0 | 0 3 0 | 0 8340 Proc0 5 6 | 7 0 0 | 8 8341 ------------------------------- 8342 Proc1 18 0 | 19 20 21 | 0 8343 ------------------------------- 8344 Proc2 26 27 | 0 0 28 | 29 8345 0 0 | 31 32 33 | 0 8346 .ve 8347 8348 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()` 8349 @*/ 8350 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat) 8351 { 8352 PetscMPIInt size; 8353 Mat *local; 8354 IS iscoltmp; 8355 PetscBool flg; 8356 8357 PetscFunctionBegin; 8358 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8359 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 8360 if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 8361 PetscValidPointer(newmat, 5); 8362 if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5); 8363 PetscValidType(mat, 1); 8364 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8365 PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX"); 8366 8367 MatCheckPreallocated(mat, 1); 8368 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8369 8370 if (!iscol || isrow == iscol) { 8371 PetscBool stride; 8372 PetscMPIInt grabentirematrix = 0, grab; 8373 PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride)); 8374 if (stride) { 8375 PetscInt first, step, n, rstart, rend; 8376 PetscCall(ISStrideGetInfo(isrow, &first, &step)); 8377 if (step == 1) { 8378 PetscCall(MatGetOwnershipRange(mat, &rstart, &rend)); 8379 if (rstart == first) { 8380 PetscCall(ISGetLocalSize(isrow, &n)); 8381 if (n == rend - rstart) grabentirematrix = 1; 8382 } 8383 } 8384 } 8385 PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat))); 8386 if (grab) { 8387 PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n")); 8388 if (cll == MAT_INITIAL_MATRIX) { 8389 *newmat = mat; 8390 PetscCall(PetscObjectReference((PetscObject)mat)); 8391 } 8392 PetscFunctionReturn(PETSC_SUCCESS); 8393 } 8394 } 8395 8396 if (!iscol) { 8397 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp)); 8398 } else { 8399 iscoltmp = iscol; 8400 } 8401 8402 /* if original matrix is on just one processor then use submatrix generated */ 8403 if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) { 8404 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat)); 8405 goto setproperties; 8406 } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) { 8407 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local)); 8408 *newmat = *local; 8409 PetscCall(PetscFree(local)); 8410 goto setproperties; 8411 } else if (!mat->ops->createsubmatrix) { 8412 /* Create a new matrix type that implements the operation using the full matrix */ 8413 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8414 switch (cll) { 8415 case MAT_INITIAL_MATRIX: 8416 PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat)); 8417 break; 8418 case MAT_REUSE_MATRIX: 8419 PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp)); 8420 break; 8421 default: 8422 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX"); 8423 } 8424 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8425 goto setproperties; 8426 } 8427 8428 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8429 PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat); 8430 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8431 8432 setproperties: 8433 PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg)); 8434 if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat)); 8435 if (!iscol) PetscCall(ISDestroy(&iscoltmp)); 8436 if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat)); 8437 PetscFunctionReturn(PETSC_SUCCESS); 8438 } 8439 8440 /*@ 8441 MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix 8442 8443 Not Collective 8444 8445 Input Parameters: 8446 + A - the matrix we wish to propagate options from 8447 - B - the matrix we wish to propagate options to 8448 8449 Level: beginner 8450 8451 Note: 8452 Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL` 8453 8454 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, MatIsStructurallySymmetricKnown()` 8455 @*/ 8456 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B) 8457 { 8458 PetscFunctionBegin; 8459 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8460 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 8461 B->symmetry_eternal = A->symmetry_eternal; 8462 B->structural_symmetry_eternal = A->structural_symmetry_eternal; 8463 B->symmetric = A->symmetric; 8464 B->structurally_symmetric = A->structurally_symmetric; 8465 B->spd = A->spd; 8466 B->hermitian = A->hermitian; 8467 PetscFunctionReturn(PETSC_SUCCESS); 8468 } 8469 8470 /*@ 8471 MatStashSetInitialSize - sets the sizes of the matrix stash, that is 8472 used during the assembly process to store values that belong to 8473 other processors. 8474 8475 Not Collective 8476 8477 Input Parameters: 8478 + mat - the matrix 8479 . size - the initial size of the stash. 8480 - bsize - the initial size of the block-stash(if used). 8481 8482 Options Database Keys: 8483 + -matstash_initial_size <size> or <size0,size1,...sizep-1> 8484 - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1> 8485 8486 Level: intermediate 8487 8488 Notes: 8489 The block-stash is used for values set with `MatSetValuesBlocked()` while 8490 the stash is used for values set with `MatSetValues()` 8491 8492 Run with the option -info and look for output of the form 8493 MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs. 8494 to determine the appropriate value, MM, to use for size and 8495 MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs. 8496 to determine the value, BMM to use for bsize 8497 8498 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()` 8499 @*/ 8500 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize) 8501 { 8502 PetscFunctionBegin; 8503 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8504 PetscValidType(mat, 1); 8505 PetscCall(MatStashSetInitialSize_Private(&mat->stash, size)); 8506 PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize)); 8507 PetscFunctionReturn(PETSC_SUCCESS); 8508 } 8509 8510 /*@ 8511 MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of 8512 the matrix 8513 8514 Neighbor-wise Collective 8515 8516 Input Parameters: 8517 + mat - the matrix 8518 . x - the vector to be multiplied by the interpolation operator 8519 - y - the vector to be added to the result 8520 8521 Output Parameter: 8522 . w - the resulting vector 8523 8524 Level: intermediate 8525 8526 Notes: 8527 `w` may be the same vector as `y`. 8528 8529 This allows one to use either the restriction or interpolation (its transpose) 8530 matrix to do the interpolation 8531 8532 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8533 @*/ 8534 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w) 8535 { 8536 PetscInt M, N, Ny; 8537 8538 PetscFunctionBegin; 8539 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8540 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8541 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8542 PetscValidHeaderSpecific(w, VEC_CLASSID, 4); 8543 PetscCall(MatGetSize(A, &M, &N)); 8544 PetscCall(VecGetSize(y, &Ny)); 8545 if (M == Ny) { 8546 PetscCall(MatMultAdd(A, x, y, w)); 8547 } else { 8548 PetscCall(MatMultTransposeAdd(A, x, y, w)); 8549 } 8550 PetscFunctionReturn(PETSC_SUCCESS); 8551 } 8552 8553 /*@ 8554 MatInterpolate - y = A*x or A'*x depending on the shape of 8555 the matrix 8556 8557 Neighbor-wise Collective 8558 8559 Input Parameters: 8560 + mat - the matrix 8561 - x - the vector to be interpolated 8562 8563 Output Parameter: 8564 . y - the resulting vector 8565 8566 Level: intermediate 8567 8568 Note: 8569 This allows one to use either the restriction or interpolation (its transpose) 8570 matrix to do the interpolation 8571 8572 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8573 @*/ 8574 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y) 8575 { 8576 PetscInt M, N, Ny; 8577 8578 PetscFunctionBegin; 8579 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8580 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8581 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8582 PetscCall(MatGetSize(A, &M, &N)); 8583 PetscCall(VecGetSize(y, &Ny)); 8584 if (M == Ny) { 8585 PetscCall(MatMult(A, x, y)); 8586 } else { 8587 PetscCall(MatMultTranspose(A, x, y)); 8588 } 8589 PetscFunctionReturn(PETSC_SUCCESS); 8590 } 8591 8592 /*@ 8593 MatRestrict - y = A*x or A'*x 8594 8595 Neighbor-wise Collective 8596 8597 Input Parameters: 8598 + mat - the matrix 8599 - x - the vector to be restricted 8600 8601 Output Parameter: 8602 . y - the resulting vector 8603 8604 Level: intermediate 8605 8606 Note: 8607 This allows one to use either the restriction or interpolation (its transpose) 8608 matrix to do the restriction 8609 8610 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG` 8611 @*/ 8612 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y) 8613 { 8614 PetscInt M, N, Ny; 8615 8616 PetscFunctionBegin; 8617 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8618 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8619 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8620 PetscCall(MatGetSize(A, &M, &N)); 8621 PetscCall(VecGetSize(y, &Ny)); 8622 if (M == Ny) { 8623 PetscCall(MatMult(A, x, y)); 8624 } else { 8625 PetscCall(MatMultTranspose(A, x, y)); 8626 } 8627 PetscFunctionReturn(PETSC_SUCCESS); 8628 } 8629 8630 /*@ 8631 MatMatInterpolateAdd - Y = W + A*X or W + A'*X 8632 8633 Neighbor-wise Collective 8634 8635 Input Parameters: 8636 + mat - the matrix 8637 . x - the input dense matrix to be multiplied 8638 - w - the input dense matrix to be added to the result 8639 8640 Output Parameter: 8641 . y - the output dense matrix 8642 8643 Level: intermediate 8644 8645 Note: 8646 This allows one to use either the restriction or interpolation (its transpose) 8647 matrix to do the interpolation. y matrix can be reused if already created with the proper sizes, 8648 otherwise it will be recreated. y must be initialized to `NULL` if not supplied. 8649 8650 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG` 8651 @*/ 8652 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y) 8653 { 8654 PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0; 8655 PetscBool trans = PETSC_TRUE; 8656 MatReuse reuse = MAT_INITIAL_MATRIX; 8657 8658 PetscFunctionBegin; 8659 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8660 PetscValidHeaderSpecific(x, MAT_CLASSID, 2); 8661 PetscValidType(x, 2); 8662 if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3); 8663 if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4); 8664 PetscCall(MatGetSize(A, &M, &N)); 8665 PetscCall(MatGetSize(x, &Mx, &Nx)); 8666 if (N == Mx) trans = PETSC_FALSE; 8667 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); 8668 Mo = trans ? N : M; 8669 if (*y) { 8670 PetscCall(MatGetSize(*y, &My, &Ny)); 8671 if (Mo == My && Nx == Ny) { 8672 reuse = MAT_REUSE_MATRIX; 8673 } else { 8674 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); 8675 PetscCall(MatDestroy(y)); 8676 } 8677 } 8678 8679 if (w && *y == w) { /* this is to minimize changes in PCMG */ 8680 PetscBool flg; 8681 8682 PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w)); 8683 if (w) { 8684 PetscInt My, Ny, Mw, Nw; 8685 8686 PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg)); 8687 PetscCall(MatGetSize(*y, &My, &Ny)); 8688 PetscCall(MatGetSize(w, &Mw, &Nw)); 8689 if (!flg || My != Mw || Ny != Nw) w = NULL; 8690 } 8691 if (!w) { 8692 PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w)); 8693 PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w)); 8694 PetscCall(PetscObjectDereference((PetscObject)w)); 8695 } else { 8696 PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN)); 8697 } 8698 } 8699 if (!trans) { 8700 PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8701 } else { 8702 PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8703 } 8704 if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN)); 8705 PetscFunctionReturn(PETSC_SUCCESS); 8706 } 8707 8708 /*@ 8709 MatMatInterpolate - Y = A*X or A'*X 8710 8711 Neighbor-wise Collective 8712 8713 Input Parameters: 8714 + mat - the matrix 8715 - x - the input dense matrix 8716 8717 Output Parameter: 8718 . y - the output dense matrix 8719 8720 Level: intermediate 8721 8722 Note: 8723 This allows one to use either the restriction or interpolation (its transpose) 8724 matrix to do the interpolation. y matrix can be reused if already created with the proper sizes, 8725 otherwise it will be recreated. y must be initialized to `NULL` if not supplied. 8726 8727 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG` 8728 @*/ 8729 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y) 8730 { 8731 PetscFunctionBegin; 8732 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8733 PetscFunctionReturn(PETSC_SUCCESS); 8734 } 8735 8736 /*@ 8737 MatMatRestrict - Y = A*X or A'*X 8738 8739 Neighbor-wise Collective 8740 8741 Input Parameters: 8742 + mat - the matrix 8743 - x - the input dense matrix 8744 8745 Output Parameter: 8746 . y - the output dense matrix 8747 8748 Level: intermediate 8749 8750 Note: 8751 This allows one to use either the restriction or interpolation (its transpose) 8752 matrix to do the restriction. y matrix can be reused if already created with the proper sizes, 8753 otherwise it will be recreated. y must be initialized to `NULL` if not supplied. 8754 8755 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG` 8756 @*/ 8757 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y) 8758 { 8759 PetscFunctionBegin; 8760 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8761 PetscFunctionReturn(PETSC_SUCCESS); 8762 } 8763 8764 /*@ 8765 MatGetNullSpace - retrieves the null space of a matrix. 8766 8767 Logically Collective 8768 8769 Input Parameters: 8770 + mat - the matrix 8771 - nullsp - the null space object 8772 8773 Level: developer 8774 8775 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace` 8776 @*/ 8777 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp) 8778 { 8779 PetscFunctionBegin; 8780 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8781 PetscValidPointer(nullsp, 2); 8782 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp; 8783 PetscFunctionReturn(PETSC_SUCCESS); 8784 } 8785 8786 /*@ 8787 MatSetNullSpace - attaches a null space to a matrix. 8788 8789 Logically Collective 8790 8791 Input Parameters: 8792 + mat - the matrix 8793 - nullsp - the null space object 8794 8795 Level: advanced 8796 8797 Notes: 8798 This null space is used by the `KSP` linear solvers to solve singular systems. 8799 8800 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` 8801 8802 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 8803 to zero but the linear system will still be solved in a least squares sense. 8804 8805 The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that 8806 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). 8807 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 8808 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 8809 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). 8810 This \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix. 8811 8812 If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called 8813 `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this 8814 routine also automatically calls `MatSetTransposeNullSpace()`. 8815 8816 The user should call `MatNullSpaceDestroy()`. 8817 8818 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, 8819 `KSPSetPCSide()` 8820 @*/ 8821 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp) 8822 { 8823 PetscFunctionBegin; 8824 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8825 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8826 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8827 PetscCall(MatNullSpaceDestroy(&mat->nullsp)); 8828 mat->nullsp = nullsp; 8829 if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp)); 8830 PetscFunctionReturn(PETSC_SUCCESS); 8831 } 8832 8833 /*@ 8834 MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix. 8835 8836 Logically Collective 8837 8838 Input Parameters: 8839 + mat - the matrix 8840 - nullsp - the null space object 8841 8842 Level: developer 8843 8844 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()` 8845 @*/ 8846 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp) 8847 { 8848 PetscFunctionBegin; 8849 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8850 PetscValidType(mat, 1); 8851 PetscValidPointer(nullsp, 2); 8852 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp; 8853 PetscFunctionReturn(PETSC_SUCCESS); 8854 } 8855 8856 /*@ 8857 MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix 8858 8859 Logically Collective 8860 8861 Input Parameters: 8862 + mat - the matrix 8863 - nullsp - the null space object 8864 8865 Level: advanced 8866 8867 Notes: 8868 This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning. 8869 8870 See `MatSetNullSpace()` 8871 8872 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()` 8873 @*/ 8874 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp) 8875 { 8876 PetscFunctionBegin; 8877 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8878 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8879 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8880 PetscCall(MatNullSpaceDestroy(&mat->transnullsp)); 8881 mat->transnullsp = nullsp; 8882 PetscFunctionReturn(PETSC_SUCCESS); 8883 } 8884 8885 /*@ 8886 MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions 8887 This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix. 8888 8889 Logically Collective 8890 8891 Input Parameters: 8892 + mat - the matrix 8893 - nullsp - the null space object 8894 8895 Level: advanced 8896 8897 Notes: 8898 Overwrites any previous near null space that may have been attached 8899 8900 You can remove the null space by calling this routine with an nullsp of `NULL` 8901 8902 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()` 8903 @*/ 8904 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp) 8905 { 8906 PetscFunctionBegin; 8907 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8908 PetscValidType(mat, 1); 8909 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8910 MatCheckPreallocated(mat, 1); 8911 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8912 PetscCall(MatNullSpaceDestroy(&mat->nearnullsp)); 8913 mat->nearnullsp = nullsp; 8914 PetscFunctionReturn(PETSC_SUCCESS); 8915 } 8916 8917 /*@ 8918 MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()` 8919 8920 Not Collective 8921 8922 Input Parameter: 8923 . mat - the matrix 8924 8925 Output Parameter: 8926 . nullsp - the null space object, `NULL` if not set 8927 8928 Level: advanced 8929 8930 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()` 8931 @*/ 8932 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp) 8933 { 8934 PetscFunctionBegin; 8935 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8936 PetscValidType(mat, 1); 8937 PetscValidPointer(nullsp, 2); 8938 MatCheckPreallocated(mat, 1); 8939 *nullsp = mat->nearnullsp; 8940 PetscFunctionReturn(PETSC_SUCCESS); 8941 } 8942 8943 /*@C 8944 MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix. 8945 8946 Collective 8947 8948 Input Parameters: 8949 + mat - the matrix 8950 . row - row/column permutation 8951 - info - information on desired factorization process 8952 8953 Level: developer 8954 8955 Notes: 8956 Probably really in-place only when level of fill is zero, otherwise allocates 8957 new space to store factored matrix and deletes previous memory. 8958 8959 Most users should employ the `KSP` interface for linear solvers 8960 instead of working directly with matrix algebra routines such as this. 8961 See, e.g., `KSPCreate()`. 8962 8963 Developer Note: 8964 The Fortran interface is not autogenerated as the 8965 interface definition cannot be generated correctly [due to `MatFactorInfo`] 8966 8967 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 8968 @*/ 8969 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info) 8970 { 8971 PetscFunctionBegin; 8972 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8973 PetscValidType(mat, 1); 8974 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 8975 PetscValidPointer(info, 3); 8976 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 8977 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 8978 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8979 MatCheckPreallocated(mat, 1); 8980 PetscUseTypeMethod(mat, iccfactor, row, info); 8981 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 8982 PetscFunctionReturn(PETSC_SUCCESS); 8983 } 8984 8985 /*@ 8986 MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the 8987 ghosted ones. 8988 8989 Not Collective 8990 8991 Input Parameters: 8992 + mat - the matrix 8993 - diag - the diagonal values, including ghost ones 8994 8995 Level: developer 8996 8997 Notes: 8998 Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices 8999 9000 This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()` 9001 9002 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 9003 @*/ 9004 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag) 9005 { 9006 PetscMPIInt size; 9007 9008 PetscFunctionBegin; 9009 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9010 PetscValidHeaderSpecific(diag, VEC_CLASSID, 2); 9011 PetscValidType(mat, 1); 9012 9013 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled"); 9014 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 9015 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 9016 if (size == 1) { 9017 PetscInt n, m; 9018 PetscCall(VecGetSize(diag, &n)); 9019 PetscCall(MatGetSize(mat, NULL, &m)); 9020 PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions"); 9021 PetscCall(MatDiagonalScale(mat, NULL, diag)); 9022 } else { 9023 PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag)); 9024 } 9025 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 9026 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9027 PetscFunctionReturn(PETSC_SUCCESS); 9028 } 9029 9030 /*@ 9031 MatGetInertia - Gets the inertia from a factored matrix 9032 9033 Collective 9034 9035 Input Parameter: 9036 . mat - the matrix 9037 9038 Output Parameters: 9039 + nneg - number of negative eigenvalues 9040 . nzero - number of zero eigenvalues 9041 - npos - number of positive eigenvalues 9042 9043 Level: advanced 9044 9045 Note: 9046 Matrix must have been factored by `MatCholeskyFactor()` 9047 9048 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()` 9049 @*/ 9050 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos) 9051 { 9052 PetscFunctionBegin; 9053 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9054 PetscValidType(mat, 1); 9055 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9056 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled"); 9057 PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos); 9058 PetscFunctionReturn(PETSC_SUCCESS); 9059 } 9060 9061 /*@C 9062 MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors 9063 9064 Neighbor-wise Collective 9065 9066 Input Parameters: 9067 + mat - the factored matrix obtained with `MatGetFactor()` 9068 - b - the right-hand-side vectors 9069 9070 Output Parameter: 9071 . x - the result vectors 9072 9073 Level: developer 9074 9075 Note: 9076 The vectors `b` and `x` cannot be the same. I.e., one cannot 9077 call `MatSolves`(A,x,x). 9078 9079 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()` 9080 @*/ 9081 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x) 9082 { 9083 PetscFunctionBegin; 9084 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9085 PetscValidType(mat, 1); 9086 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 9087 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9088 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 9089 9090 MatCheckPreallocated(mat, 1); 9091 PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0)); 9092 PetscUseTypeMethod(mat, solves, b, x); 9093 PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0)); 9094 PetscFunctionReturn(PETSC_SUCCESS); 9095 } 9096 9097 /*@ 9098 MatIsSymmetric - Test whether a matrix is symmetric 9099 9100 Collective 9101 9102 Input Parameters: 9103 + A - the matrix to test 9104 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose) 9105 9106 Output Parameter: 9107 . flg - the result 9108 9109 Level: intermediate 9110 9111 Notes: 9112 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9113 9114 If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()` 9115 9116 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9117 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9118 9119 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`, 9120 `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()` 9121 @*/ 9122 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg) 9123 { 9124 PetscFunctionBegin; 9125 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9126 PetscValidBoolPointer(flg, 3); 9127 9128 if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE; 9129 else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE; 9130 else { 9131 PetscUseTypeMethod(A, issymmetric, tol, flg); 9132 if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg)); 9133 } 9134 PetscFunctionReturn(PETSC_SUCCESS); 9135 } 9136 9137 /*@ 9138 MatIsHermitian - Test whether a matrix is Hermitian 9139 9140 Collective 9141 9142 Input Parameters: 9143 + A - the matrix to test 9144 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian) 9145 9146 Output Parameter: 9147 . flg - the result 9148 9149 Level: intermediate 9150 9151 Notes: 9152 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9153 9154 If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()` 9155 9156 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9157 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`) 9158 9159 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, 9160 `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()` 9161 @*/ 9162 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg) 9163 { 9164 PetscFunctionBegin; 9165 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9166 PetscValidBoolPointer(flg, 3); 9167 9168 if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE; 9169 else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE; 9170 else { 9171 PetscUseTypeMethod(A, ishermitian, tol, flg); 9172 if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg)); 9173 } 9174 PetscFunctionReturn(PETSC_SUCCESS); 9175 } 9176 9177 /*@ 9178 MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state 9179 9180 Not Collective 9181 9182 Input Parameter: 9183 . A - the matrix to check 9184 9185 Output Parameters: 9186 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid) 9187 - flg - the result (only valid if set is `PETSC_TRUE`) 9188 9189 Level: advanced 9190 9191 Notes: 9192 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()` 9193 if you want it explicitly checked 9194 9195 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9196 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9197 9198 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9199 @*/ 9200 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9201 { 9202 PetscFunctionBegin; 9203 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9204 PetscValidBoolPointer(set, 2); 9205 PetscValidBoolPointer(flg, 3); 9206 if (A->symmetric != PETSC_BOOL3_UNKNOWN) { 9207 *set = PETSC_TRUE; 9208 *flg = PetscBool3ToBool(A->symmetric); 9209 } else { 9210 *set = PETSC_FALSE; 9211 } 9212 PetscFunctionReturn(PETSC_SUCCESS); 9213 } 9214 9215 /*@ 9216 MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state 9217 9218 Not Collective 9219 9220 Input Parameter: 9221 . A - the matrix to check 9222 9223 Output Parameters: 9224 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid) 9225 - flg - the result (only valid if set is `PETSC_TRUE`) 9226 9227 Level: advanced 9228 9229 Notes: 9230 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). 9231 9232 One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD 9233 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`) 9234 9235 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9236 @*/ 9237 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg) 9238 { 9239 PetscFunctionBegin; 9240 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9241 PetscValidBoolPointer(set, 2); 9242 PetscValidBoolPointer(flg, 3); 9243 if (A->spd != PETSC_BOOL3_UNKNOWN) { 9244 *set = PETSC_TRUE; 9245 *flg = PetscBool3ToBool(A->spd); 9246 } else { 9247 *set = PETSC_FALSE; 9248 } 9249 PetscFunctionReturn(PETSC_SUCCESS); 9250 } 9251 9252 /*@ 9253 MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state 9254 9255 Not Collective 9256 9257 Input Parameter: 9258 . A - the matrix to check 9259 9260 Output Parameters: 9261 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid) 9262 - flg - the result (only valid if set is `PETSC_TRUE`) 9263 9264 Level: advanced 9265 9266 Notes: 9267 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()` 9268 if you want it explicitly checked 9269 9270 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9271 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9272 9273 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()` 9274 @*/ 9275 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg) 9276 { 9277 PetscFunctionBegin; 9278 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9279 PetscValidBoolPointer(set, 2); 9280 PetscValidBoolPointer(flg, 3); 9281 if (A->hermitian != PETSC_BOOL3_UNKNOWN) { 9282 *set = PETSC_TRUE; 9283 *flg = PetscBool3ToBool(A->hermitian); 9284 } else { 9285 *set = PETSC_FALSE; 9286 } 9287 PetscFunctionReturn(PETSC_SUCCESS); 9288 } 9289 9290 /*@ 9291 MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric 9292 9293 Collective 9294 9295 Input Parameter: 9296 . A - the matrix to test 9297 9298 Output Parameter: 9299 . flg - the result 9300 9301 Level: intermediate 9302 9303 Notes: 9304 If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()` 9305 9306 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 9307 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9308 9309 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()` 9310 @*/ 9311 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg) 9312 { 9313 PetscFunctionBegin; 9314 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9315 PetscValidBoolPointer(flg, 2); 9316 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9317 *flg = PetscBool3ToBool(A->structurally_symmetric); 9318 } else { 9319 PetscUseTypeMethod(A, isstructurallysymmetric, flg); 9320 PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg)); 9321 } 9322 PetscFunctionReturn(PETSC_SUCCESS); 9323 } 9324 9325 /*@ 9326 MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state 9327 9328 Not Collective 9329 9330 Input Parameter: 9331 . A - the matrix to check 9332 9333 Output Parameters: 9334 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid) 9335 - flg - the result (only valid if set is PETSC_TRUE) 9336 9337 Level: advanced 9338 9339 Notes: 9340 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 9341 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9342 9343 Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation) 9344 9345 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9346 @*/ 9347 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9348 { 9349 PetscFunctionBegin; 9350 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9351 PetscValidBoolPointer(set, 2); 9352 PetscValidBoolPointer(flg, 3); 9353 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9354 *set = PETSC_TRUE; 9355 *flg = PetscBool3ToBool(A->structurally_symmetric); 9356 } else { 9357 *set = PETSC_FALSE; 9358 } 9359 PetscFunctionReturn(PETSC_SUCCESS); 9360 } 9361 9362 /*@ 9363 MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need 9364 to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process 9365 9366 Not Collective 9367 9368 Input Parameter: 9369 . mat - the matrix 9370 9371 Output Parameters: 9372 + nstash - the size of the stash 9373 . reallocs - the number of additional mallocs incurred. 9374 . bnstash - the size of the block stash 9375 - breallocs - the number of additional mallocs incurred.in the block stash 9376 9377 Level: advanced 9378 9379 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()` 9380 @*/ 9381 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs) 9382 { 9383 PetscFunctionBegin; 9384 PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs)); 9385 PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs)); 9386 PetscFunctionReturn(PETSC_SUCCESS); 9387 } 9388 9389 /*@C 9390 MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same 9391 parallel layout, `PetscLayout` for rows and columns 9392 9393 Collective 9394 9395 Input Parameter: 9396 . mat - the matrix 9397 9398 Output Parameters: 9399 + right - (optional) vector that the matrix can be multiplied against 9400 - left - (optional) vector that the matrix vector product can be stored in 9401 9402 Level: advanced 9403 9404 Notes: 9405 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()`. 9406 9407 These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed 9408 9409 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()` 9410 @*/ 9411 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left) 9412 { 9413 PetscFunctionBegin; 9414 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9415 PetscValidType(mat, 1); 9416 if (mat->ops->getvecs) { 9417 PetscUseTypeMethod(mat, getvecs, right, left); 9418 } else { 9419 PetscInt rbs, cbs; 9420 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 9421 if (right) { 9422 PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup"); 9423 PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), right)); 9424 PetscCall(VecSetSizes(*right, mat->cmap->n, PETSC_DETERMINE)); 9425 PetscCall(VecSetBlockSize(*right, cbs)); 9426 PetscCall(VecSetType(*right, mat->defaultvectype)); 9427 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9428 if (mat->boundtocpu && mat->bindingpropagates) { 9429 PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE)); 9430 PetscCall(VecBindToCPU(*right, PETSC_TRUE)); 9431 } 9432 #endif 9433 PetscCall(PetscLayoutReference(mat->cmap, &(*right)->map)); 9434 } 9435 if (left) { 9436 PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup"); 9437 PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), left)); 9438 PetscCall(VecSetSizes(*left, mat->rmap->n, PETSC_DETERMINE)); 9439 PetscCall(VecSetBlockSize(*left, rbs)); 9440 PetscCall(VecSetType(*left, mat->defaultvectype)); 9441 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9442 if (mat->boundtocpu && mat->bindingpropagates) { 9443 PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE)); 9444 PetscCall(VecBindToCPU(*left, PETSC_TRUE)); 9445 } 9446 #endif 9447 PetscCall(PetscLayoutReference(mat->rmap, &(*left)->map)); 9448 } 9449 } 9450 PetscFunctionReturn(PETSC_SUCCESS); 9451 } 9452 9453 /*@C 9454 MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure 9455 with default values. 9456 9457 Not Collective 9458 9459 Input Parameter: 9460 . info - the `MatFactorInfo` data structure 9461 9462 Level: developer 9463 9464 Notes: 9465 The solvers are generally used through the `KSP` and `PC` objects, for example 9466 `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC` 9467 9468 Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed 9469 9470 Developer Note: 9471 The Fortran interface is not autogenerated as the 9472 interface definition cannot be generated correctly [due to `MatFactorInfo`] 9473 9474 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo` 9475 @*/ 9476 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info) 9477 { 9478 PetscFunctionBegin; 9479 PetscCall(PetscMemzero(info, sizeof(MatFactorInfo))); 9480 PetscFunctionReturn(PETSC_SUCCESS); 9481 } 9482 9483 /*@ 9484 MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed 9485 9486 Collective 9487 9488 Input Parameters: 9489 + mat - the factored matrix 9490 - is - the index set defining the Schur indices (0-based) 9491 9492 Level: advanced 9493 9494 Notes: 9495 Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system. 9496 9497 You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call. 9498 9499 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9500 9501 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`, 9502 `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9503 @*/ 9504 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is) 9505 { 9506 PetscErrorCode (*f)(Mat, IS); 9507 9508 PetscFunctionBegin; 9509 PetscValidType(mat, 1); 9510 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9511 PetscValidType(is, 2); 9512 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 9513 PetscCheckSameComm(mat, 1, is, 2); 9514 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 9515 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f)); 9516 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO"); 9517 PetscCall(MatDestroy(&mat->schur)); 9518 PetscCall((*f)(mat, is)); 9519 PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created"); 9520 PetscFunctionReturn(PETSC_SUCCESS); 9521 } 9522 9523 /*@ 9524 MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step 9525 9526 Logically Collective 9527 9528 Input Parameters: 9529 + F - the factored matrix obtained by calling `MatGetFactor()` 9530 . S - location where to return the Schur complement, can be `NULL` 9531 - status - the status of the Schur complement matrix, can be `NULL` 9532 9533 Level: advanced 9534 9535 Notes: 9536 You must call `MatFactorSetSchurIS()` before calling this routine. 9537 9538 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9539 9540 The routine provides a copy of the Schur matrix stored within the solver data structures. 9541 The caller must destroy the object when it is no longer needed. 9542 If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse. 9543 9544 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) 9545 9546 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9547 9548 Developer Note: 9549 The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc 9550 matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix. 9551 9552 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9553 @*/ 9554 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9555 { 9556 PetscFunctionBegin; 9557 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9558 if (S) PetscValidPointer(S, 2); 9559 if (status) PetscValidPointer(status, 3); 9560 if (S) { 9561 PetscErrorCode (*f)(Mat, Mat *); 9562 9563 PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f)); 9564 if (f) { 9565 PetscCall((*f)(F, S)); 9566 } else { 9567 PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S)); 9568 } 9569 } 9570 if (status) *status = F->schur_status; 9571 PetscFunctionReturn(PETSC_SUCCESS); 9572 } 9573 9574 /*@ 9575 MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix 9576 9577 Logically Collective 9578 9579 Input Parameters: 9580 + F - the factored matrix obtained by calling `MatGetFactor()` 9581 . *S - location where to return the Schur complement, can be `NULL` 9582 - status - the status of the Schur complement matrix, can be `NULL` 9583 9584 Level: advanced 9585 9586 Notes: 9587 You must call `MatFactorSetSchurIS()` before calling this routine. 9588 9589 Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS` 9590 9591 The routine returns a the Schur Complement stored within the data structures of the solver. 9592 9593 If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement. 9594 9595 The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed. 9596 9597 Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix 9598 9599 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9600 9601 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9602 @*/ 9603 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9604 { 9605 PetscFunctionBegin; 9606 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9607 if (S) PetscValidPointer(S, 2); 9608 if (status) PetscValidPointer(status, 3); 9609 if (S) *S = F->schur; 9610 if (status) *status = F->schur_status; 9611 PetscFunctionReturn(PETSC_SUCCESS); 9612 } 9613 9614 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F) 9615 { 9616 Mat S = F->schur; 9617 9618 PetscFunctionBegin; 9619 switch (F->schur_status) { 9620 case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through 9621 case MAT_FACTOR_SCHUR_INVERTED: 9622 if (S) { 9623 S->ops->solve = NULL; 9624 S->ops->matsolve = NULL; 9625 S->ops->solvetranspose = NULL; 9626 S->ops->matsolvetranspose = NULL; 9627 S->ops->solveadd = NULL; 9628 S->ops->solvetransposeadd = NULL; 9629 S->factortype = MAT_FACTOR_NONE; 9630 PetscCall(PetscFree(S->solvertype)); 9631 } 9632 case MAT_FACTOR_SCHUR_FACTORED: // fall-through 9633 break; 9634 default: 9635 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9636 } 9637 PetscFunctionReturn(PETSC_SUCCESS); 9638 } 9639 9640 /*@ 9641 MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()` 9642 9643 Logically Collective 9644 9645 Input Parameters: 9646 + F - the factored matrix obtained by calling `MatGetFactor()` 9647 . *S - location where the Schur complement is stored 9648 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`) 9649 9650 Level: advanced 9651 9652 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9653 @*/ 9654 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status) 9655 { 9656 PetscFunctionBegin; 9657 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9658 if (S) { 9659 PetscValidHeaderSpecific(*S, MAT_CLASSID, 2); 9660 *S = NULL; 9661 } 9662 F->schur_status = status; 9663 PetscCall(MatFactorUpdateSchurStatus_Private(F)); 9664 PetscFunctionReturn(PETSC_SUCCESS); 9665 } 9666 9667 /*@ 9668 MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step 9669 9670 Logically Collective 9671 9672 Input Parameters: 9673 + F - the factored matrix obtained by calling `MatGetFactor()` 9674 . rhs - location where the right hand side of the Schur complement system is stored 9675 - sol - location where the solution of the Schur complement system has to be returned 9676 9677 Level: advanced 9678 9679 Notes: 9680 The sizes of the vectors should match the size of the Schur complement 9681 9682 Must be called after `MatFactorSetSchurIS()` 9683 9684 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()` 9685 @*/ 9686 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol) 9687 { 9688 PetscFunctionBegin; 9689 PetscValidType(F, 1); 9690 PetscValidType(rhs, 2); 9691 PetscValidType(sol, 3); 9692 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9693 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9694 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9695 PetscCheckSameComm(F, 1, rhs, 2); 9696 PetscCheckSameComm(F, 1, sol, 3); 9697 PetscCall(MatFactorFactorizeSchurComplement(F)); 9698 switch (F->schur_status) { 9699 case MAT_FACTOR_SCHUR_FACTORED: 9700 PetscCall(MatSolveTranspose(F->schur, rhs, sol)); 9701 break; 9702 case MAT_FACTOR_SCHUR_INVERTED: 9703 PetscCall(MatMultTranspose(F->schur, rhs, sol)); 9704 break; 9705 default: 9706 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9707 } 9708 PetscFunctionReturn(PETSC_SUCCESS); 9709 } 9710 9711 /*@ 9712 MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step 9713 9714 Logically Collective 9715 9716 Input Parameters: 9717 + F - the factored matrix obtained by calling `MatGetFactor()` 9718 . rhs - location where the right hand side of the Schur complement system is stored 9719 - sol - location where the solution of the Schur complement system has to be returned 9720 9721 Level: advanced 9722 9723 Notes: 9724 The sizes of the vectors should match the size of the Schur complement 9725 9726 Must be called after `MatFactorSetSchurIS()` 9727 9728 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()` 9729 @*/ 9730 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol) 9731 { 9732 PetscFunctionBegin; 9733 PetscValidType(F, 1); 9734 PetscValidType(rhs, 2); 9735 PetscValidType(sol, 3); 9736 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9737 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9738 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9739 PetscCheckSameComm(F, 1, rhs, 2); 9740 PetscCheckSameComm(F, 1, sol, 3); 9741 PetscCall(MatFactorFactorizeSchurComplement(F)); 9742 switch (F->schur_status) { 9743 case MAT_FACTOR_SCHUR_FACTORED: 9744 PetscCall(MatSolve(F->schur, rhs, sol)); 9745 break; 9746 case MAT_FACTOR_SCHUR_INVERTED: 9747 PetscCall(MatMult(F->schur, rhs, sol)); 9748 break; 9749 default: 9750 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9751 } 9752 PetscFunctionReturn(PETSC_SUCCESS); 9753 } 9754 9755 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat); 9756 #if PetscDefined(HAVE_CUDA) 9757 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat); 9758 #endif 9759 9760 /* Schur status updated in the interface */ 9761 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F) 9762 { 9763 Mat S = F->schur; 9764 9765 PetscFunctionBegin; 9766 if (S) { 9767 PetscMPIInt size; 9768 PetscBool isdense, isdensecuda; 9769 9770 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size)); 9771 PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented"); 9772 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense)); 9773 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda)); 9774 PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name); 9775 PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0)); 9776 if (isdense) { 9777 PetscCall(MatSeqDenseInvertFactors_Private(S)); 9778 } else if (isdensecuda) { 9779 #if defined(PETSC_HAVE_CUDA) 9780 PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S)); 9781 #endif 9782 } 9783 // HIP?????????????? 9784 PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0)); 9785 } 9786 PetscFunctionReturn(PETSC_SUCCESS); 9787 } 9788 9789 /*@ 9790 MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step 9791 9792 Logically Collective 9793 9794 Input Parameter: 9795 . F - the factored matrix obtained by calling `MatGetFactor()` 9796 9797 Level: advanced 9798 9799 Notes: 9800 Must be called after `MatFactorSetSchurIS()`. 9801 9802 Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it. 9803 9804 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()` 9805 @*/ 9806 PetscErrorCode MatFactorInvertSchurComplement(Mat F) 9807 { 9808 PetscFunctionBegin; 9809 PetscValidType(F, 1); 9810 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9811 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS); 9812 PetscCall(MatFactorFactorizeSchurComplement(F)); 9813 PetscCall(MatFactorInvertSchurComplement_Private(F)); 9814 F->schur_status = MAT_FACTOR_SCHUR_INVERTED; 9815 PetscFunctionReturn(PETSC_SUCCESS); 9816 } 9817 9818 /*@ 9819 MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step 9820 9821 Logically Collective 9822 9823 Input Parameter: 9824 . F - the factored matrix obtained by calling `MatGetFactor()` 9825 9826 Level: advanced 9827 9828 Note: 9829 Must be called after `MatFactorSetSchurIS()` 9830 9831 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()` 9832 @*/ 9833 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F) 9834 { 9835 MatFactorInfo info; 9836 9837 PetscFunctionBegin; 9838 PetscValidType(F, 1); 9839 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9840 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS); 9841 PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0)); 9842 PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo))); 9843 if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */ 9844 PetscCall(MatCholeskyFactor(F->schur, NULL, &info)); 9845 } else { 9846 PetscCall(MatLUFactor(F->schur, NULL, NULL, &info)); 9847 } 9848 PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0)); 9849 F->schur_status = MAT_FACTOR_SCHUR_FACTORED; 9850 PetscFunctionReturn(PETSC_SUCCESS); 9851 } 9852 9853 /*@ 9854 MatPtAP - Creates the matrix product C = P^T * A * P 9855 9856 Neighbor-wise Collective 9857 9858 Input Parameters: 9859 + A - the matrix 9860 . P - the projection matrix 9861 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9862 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate 9863 if the result is a dense matrix this is irrelevant 9864 9865 Output Parameter: 9866 . C - the product matrix 9867 9868 Level: intermediate 9869 9870 Notes: 9871 C will be created and must be destroyed by the user with `MatDestroy()`. 9872 9873 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9874 9875 Developer Note: 9876 For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`. 9877 9878 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()` 9879 @*/ 9880 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C) 9881 { 9882 PetscFunctionBegin; 9883 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 9884 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9885 9886 if (scall == MAT_INITIAL_MATRIX) { 9887 PetscCall(MatProductCreate(A, P, NULL, C)); 9888 PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP)); 9889 PetscCall(MatProductSetAlgorithm(*C, "default")); 9890 PetscCall(MatProductSetFill(*C, fill)); 9891 9892 (*C)->product->api_user = PETSC_TRUE; 9893 PetscCall(MatProductSetFromOptions(*C)); 9894 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); 9895 PetscCall(MatProductSymbolic(*C)); 9896 } else { /* scall == MAT_REUSE_MATRIX */ 9897 PetscCall(MatProductReplaceMats(A, P, NULL, *C)); 9898 } 9899 9900 PetscCall(MatProductNumeric(*C)); 9901 (*C)->symmetric = A->symmetric; 9902 (*C)->spd = A->spd; 9903 PetscFunctionReturn(PETSC_SUCCESS); 9904 } 9905 9906 /*@ 9907 MatRARt - Creates the matrix product C = R * A * R^T 9908 9909 Neighbor-wise Collective 9910 9911 Input Parameters: 9912 + A - the matrix 9913 . R - the projection matrix 9914 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9915 - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate 9916 if the result is a dense matrix this is irrelevant 9917 9918 Output Parameter: 9919 . C - the product matrix 9920 9921 Level: intermediate 9922 9923 Notes: 9924 C will be created and must be destroyed by the user with `MatDestroy()`. 9925 9926 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9927 9928 This routine is currently only implemented for pairs of `MATAIJ` matrices and classes 9929 which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes, 9930 parallel MatRARt is implemented via explicit transpose of R, which could be very expensive. 9931 We recommend using MatPtAP(). 9932 9933 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()` 9934 @*/ 9935 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C) 9936 { 9937 PetscFunctionBegin; 9938 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 9939 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9940 9941 if (scall == MAT_INITIAL_MATRIX) { 9942 PetscCall(MatProductCreate(A, R, NULL, C)); 9943 PetscCall(MatProductSetType(*C, MATPRODUCT_RARt)); 9944 PetscCall(MatProductSetAlgorithm(*C, "default")); 9945 PetscCall(MatProductSetFill(*C, fill)); 9946 9947 (*C)->product->api_user = PETSC_TRUE; 9948 PetscCall(MatProductSetFromOptions(*C)); 9949 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); 9950 PetscCall(MatProductSymbolic(*C)); 9951 } else { /* scall == MAT_REUSE_MATRIX */ 9952 PetscCall(MatProductReplaceMats(A, R, NULL, *C)); 9953 } 9954 9955 PetscCall(MatProductNumeric(*C)); 9956 if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 9957 PetscFunctionReturn(PETSC_SUCCESS); 9958 } 9959 9960 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C) 9961 { 9962 PetscFunctionBegin; 9963 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9964 9965 if (scall == MAT_INITIAL_MATRIX) { 9966 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype])); 9967 PetscCall(MatProductCreate(A, B, NULL, C)); 9968 PetscCall(MatProductSetType(*C, ptype)); 9969 PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT)); 9970 PetscCall(MatProductSetFill(*C, fill)); 9971 9972 (*C)->product->api_user = PETSC_TRUE; 9973 PetscCall(MatProductSetFromOptions(*C)); 9974 PetscCall(MatProductSymbolic(*C)); 9975 } else { /* scall == MAT_REUSE_MATRIX */ 9976 Mat_Product *product = (*C)->product; 9977 PetscBool isdense; 9978 9979 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, "")); 9980 if (isdense && product && product->type != ptype) { 9981 PetscCall(MatProductClear(*C)); 9982 product = NULL; 9983 } 9984 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype])); 9985 if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */ 9986 PetscCheck(isdense, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first"); 9987 PetscCall(MatProductCreate_Private(A, B, NULL, *C)); 9988 product = (*C)->product; 9989 product->fill = fill; 9990 product->api_user = PETSC_TRUE; 9991 product->clear = PETSC_TRUE; 9992 9993 PetscCall(MatProductSetType(*C, ptype)); 9994 PetscCall(MatProductSetFromOptions(*C)); 9995 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); 9996 PetscCall(MatProductSymbolic(*C)); 9997 } else { /* user may change input matrices A or B when REUSE */ 9998 PetscCall(MatProductReplaceMats(A, B, NULL, *C)); 9999 } 10000 } 10001 PetscCall(MatProductNumeric(*C)); 10002 PetscFunctionReturn(PETSC_SUCCESS); 10003 } 10004 10005 /*@ 10006 MatMatMult - Performs matrix-matrix multiplication C=A*B. 10007 10008 Neighbor-wise Collective 10009 10010 Input Parameters: 10011 + A - the left matrix 10012 . B - the right matrix 10013 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10014 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate 10015 if the result is a dense matrix this is irrelevant 10016 10017 Output Parameter: 10018 . C - the product matrix 10019 10020 Notes: 10021 Unless scall is `MAT_REUSE_MATRIX` C will be created. 10022 10023 `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 10024 call to this function with `MAT_INITIAL_MATRIX`. 10025 10026 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed. 10027 10028 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`, 10029 rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse. 10030 10031 Example of Usage: 10032 .vb 10033 MatProductCreate(A,B,NULL,&C); 10034 MatProductSetType(C,MATPRODUCT_AB); 10035 MatProductSymbolic(C); 10036 MatProductNumeric(C); // compute C=A * B 10037 MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1 10038 MatProductNumeric(C); 10039 MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1 10040 MatProductNumeric(C); 10041 .ve 10042 10043 Level: intermediate 10044 10045 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()` 10046 @*/ 10047 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10048 { 10049 PetscFunctionBegin; 10050 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C)); 10051 PetscFunctionReturn(PETSC_SUCCESS); 10052 } 10053 10054 /*@ 10055 MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T. 10056 10057 Neighbor-wise Collective 10058 10059 Input Parameters: 10060 + A - the left matrix 10061 . B - the right matrix 10062 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10063 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 10064 10065 Output Parameter: 10066 . C - the product matrix 10067 10068 Level: intermediate 10069 10070 Notes: 10071 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10072 10073 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call 10074 10075 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10076 actually needed. 10077 10078 This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class, 10079 and for pairs of `MATMPIDENSE` matrices. 10080 10081 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt` 10082 10083 Options Database Keys: 10084 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the 10085 first redundantly copies the transposed B matrix on each process and requiers O(log P) communication complexity; 10086 the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity. 10087 10088 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductCreate()`, `MatProductAlgorithm`, `MatProductType`, `MATPRODUCT_ABt` 10089 @*/ 10090 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10091 { 10092 PetscFunctionBegin; 10093 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C)); 10094 if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10095 PetscFunctionReturn(PETSC_SUCCESS); 10096 } 10097 10098 /*@ 10099 MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B. 10100 10101 Neighbor-wise Collective 10102 10103 Input Parameters: 10104 + A - the left matrix 10105 . B - the right matrix 10106 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10107 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 10108 10109 Output Parameter: 10110 . C - the product matrix 10111 10112 Level: intermediate 10113 10114 Notes: 10115 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10116 10117 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call. 10118 10119 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB` 10120 10121 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10122 actually needed. 10123 10124 This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes 10125 which inherit from `MATSEQAIJ`. C will be of the same type as the input matrices. 10126 10127 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()` 10128 @*/ 10129 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10130 { 10131 PetscFunctionBegin; 10132 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C)); 10133 PetscFunctionReturn(PETSC_SUCCESS); 10134 } 10135 10136 /*@ 10137 MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C. 10138 10139 Neighbor-wise Collective 10140 10141 Input Parameters: 10142 + A - the left matrix 10143 . B - the middle matrix 10144 . C - the right matrix 10145 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10146 - 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 10147 if the result is a dense matrix this is irrelevant 10148 10149 Output Parameter: 10150 . D - the product matrix 10151 10152 Level: intermediate 10153 10154 Notes: 10155 Unless scall is `MAT_REUSE_MATRIX` D will be created. 10156 10157 `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call 10158 10159 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC` 10160 10161 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10162 actually needed. 10163 10164 If you have many matrices with the same non-zero structure to multiply, you 10165 should use `MAT_REUSE_MATRIX` in all calls but the first 10166 10167 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()` 10168 @*/ 10169 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D) 10170 { 10171 PetscFunctionBegin; 10172 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6); 10173 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10174 10175 if (scall == MAT_INITIAL_MATRIX) { 10176 PetscCall(MatProductCreate(A, B, C, D)); 10177 PetscCall(MatProductSetType(*D, MATPRODUCT_ABC)); 10178 PetscCall(MatProductSetAlgorithm(*D, "default")); 10179 PetscCall(MatProductSetFill(*D, fill)); 10180 10181 (*D)->product->api_user = PETSC_TRUE; 10182 PetscCall(MatProductSetFromOptions(*D)); 10183 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, 10184 ((PetscObject)C)->type_name); 10185 PetscCall(MatProductSymbolic(*D)); 10186 } else { /* user may change input matrices when REUSE */ 10187 PetscCall(MatProductReplaceMats(A, B, C, *D)); 10188 } 10189 PetscCall(MatProductNumeric(*D)); 10190 PetscFunctionReturn(PETSC_SUCCESS); 10191 } 10192 10193 /*@ 10194 MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators. 10195 10196 Collective 10197 10198 Input Parameters: 10199 + mat - the matrix 10200 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices) 10201 . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used) 10202 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10203 10204 Output Parameter: 10205 . matredundant - redundant matrix 10206 10207 Level: advanced 10208 10209 Notes: 10210 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 10211 original matrix has not changed from that last call to MatCreateRedundantMatrix(). 10212 10213 This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before 10214 calling it. 10215 10216 `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be. 10217 10218 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubComm` 10219 @*/ 10220 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant) 10221 { 10222 MPI_Comm comm; 10223 PetscMPIInt size; 10224 PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs; 10225 Mat_Redundant *redund = NULL; 10226 PetscSubcomm psubcomm = NULL; 10227 MPI_Comm subcomm_in = subcomm; 10228 Mat *matseq; 10229 IS isrow, iscol; 10230 PetscBool newsubcomm = PETSC_FALSE; 10231 10232 PetscFunctionBegin; 10233 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10234 if (nsubcomm && reuse == MAT_REUSE_MATRIX) { 10235 PetscValidPointer(*matredundant, 5); 10236 PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5); 10237 } 10238 10239 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10240 if (size == 1 || nsubcomm == 1) { 10241 if (reuse == MAT_INITIAL_MATRIX) { 10242 PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant)); 10243 } else { 10244 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"); 10245 PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN)); 10246 } 10247 PetscFunctionReturn(PETSC_SUCCESS); 10248 } 10249 10250 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10251 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10252 MatCheckPreallocated(mat, 1); 10253 10254 PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0)); 10255 if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */ 10256 /* create psubcomm, then get subcomm */ 10257 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10258 PetscCallMPI(MPI_Comm_size(comm, &size)); 10259 PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size); 10260 10261 PetscCall(PetscSubcommCreate(comm, &psubcomm)); 10262 PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm)); 10263 PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS)); 10264 PetscCall(PetscSubcommSetFromOptions(psubcomm)); 10265 PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL)); 10266 newsubcomm = PETSC_TRUE; 10267 PetscCall(PetscSubcommDestroy(&psubcomm)); 10268 } 10269 10270 /* get isrow, iscol and a local sequential matrix matseq[0] */ 10271 if (reuse == MAT_INITIAL_MATRIX) { 10272 mloc_sub = PETSC_DECIDE; 10273 nloc_sub = PETSC_DECIDE; 10274 if (bs < 1) { 10275 PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M)); 10276 PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N)); 10277 } else { 10278 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M)); 10279 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N)); 10280 } 10281 PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm)); 10282 rstart = rend - mloc_sub; 10283 PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow)); 10284 PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol)); 10285 } else { /* reuse == MAT_REUSE_MATRIX */ 10286 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"); 10287 /* retrieve subcomm */ 10288 PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm)); 10289 redund = (*matredundant)->redundant; 10290 isrow = redund->isrow; 10291 iscol = redund->iscol; 10292 matseq = redund->matseq; 10293 } 10294 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq)); 10295 10296 /* get matredundant over subcomm */ 10297 if (reuse == MAT_INITIAL_MATRIX) { 10298 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant)); 10299 10300 /* create a supporting struct and attach it to C for reuse */ 10301 PetscCall(PetscNew(&redund)); 10302 (*matredundant)->redundant = redund; 10303 redund->isrow = isrow; 10304 redund->iscol = iscol; 10305 redund->matseq = matseq; 10306 if (newsubcomm) { 10307 redund->subcomm = subcomm; 10308 } else { 10309 redund->subcomm = MPI_COMM_NULL; 10310 } 10311 } else { 10312 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant)); 10313 } 10314 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 10315 if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) { 10316 PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE)); 10317 PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE)); 10318 } 10319 #endif 10320 PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0)); 10321 PetscFunctionReturn(PETSC_SUCCESS); 10322 } 10323 10324 /*@C 10325 MatGetMultiProcBlock - Create multiple 'parallel submatrices' from 10326 a given `Mat`. Each submatrix can span multiple procs. 10327 10328 Collective 10329 10330 Input Parameters: 10331 + mat - the matrix 10332 . subcomm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))` 10333 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10334 10335 Output Parameter: 10336 . subMat - parallel sub-matrices each spanning a given `subcomm` 10337 10338 Level: advanced 10339 10340 Notes: 10341 The submatrix partition across processors is dictated by `subComm` a 10342 communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm` 10343 is not restricted to be grouped with consecutive original ranks. 10344 10345 Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices 10346 map directly to the layout of the original matrix [wrt the local 10347 row,col partitioning]. So the original 'DiagonalMat' naturally maps 10348 into the 'DiagonalMat' of the `subMat`, hence it is used directly from 10349 the `subMat`. However the offDiagMat looses some columns - and this is 10350 reconstructed with `MatSetValues()` 10351 10352 This is used by `PCBJACOBI` when a single block spans multiple MPI ranks 10353 10354 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI` 10355 @*/ 10356 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) 10357 { 10358 PetscMPIInt commsize, subCommSize; 10359 10360 PetscFunctionBegin; 10361 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize)); 10362 PetscCallMPI(MPI_Comm_size(subComm, &subCommSize)); 10363 PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize); 10364 10365 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"); 10366 PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10367 PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat); 10368 PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10369 PetscFunctionReturn(PETSC_SUCCESS); 10370 } 10371 10372 /*@ 10373 MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering 10374 10375 Not Collective 10376 10377 Input Parameters: 10378 + mat - matrix to extract local submatrix from 10379 . isrow - local row indices for submatrix 10380 - iscol - local column indices for submatrix 10381 10382 Output Parameter: 10383 . submat - the submatrix 10384 10385 Level: intermediate 10386 10387 Notes: 10388 `submat` should be disposed of with `MatRestoreLocalSubMatrix()`. 10389 10390 Depending on the format of `mat`, the returned submat may not implement `MatMult()`. Its communicator may be 10391 the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of `mat`'s. 10392 10393 `submat` always implements `MatSetValuesLocal()`. If `isrow` and `iscol` have the same block size, then 10394 `MatSetValuesBlockedLocal()` will also be implemented. 10395 10396 `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`. 10397 Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided. 10398 10399 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()` 10400 @*/ 10401 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10402 { 10403 PetscFunctionBegin; 10404 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10405 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10406 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10407 PetscCheckSameComm(isrow, 2, iscol, 3); 10408 PetscValidPointer(submat, 4); 10409 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call"); 10410 10411 if (mat->ops->getlocalsubmatrix) { 10412 PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat); 10413 } else { 10414 PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat)); 10415 } 10416 PetscFunctionReturn(PETSC_SUCCESS); 10417 } 10418 10419 /*@ 10420 MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()` 10421 10422 Not Collective 10423 10424 Input Parameters: 10425 + mat - matrix to extract local submatrix from 10426 . isrow - local row indices for submatrix 10427 . iscol - local column indices for submatrix 10428 - submat - the submatrix 10429 10430 Level: intermediate 10431 10432 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()` 10433 @*/ 10434 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10435 { 10436 PetscFunctionBegin; 10437 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10438 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10439 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10440 PetscCheckSameComm(isrow, 2, iscol, 3); 10441 PetscValidPointer(submat, 4); 10442 if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4); 10443 10444 if (mat->ops->restorelocalsubmatrix) { 10445 PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat); 10446 } else { 10447 PetscCall(MatDestroy(submat)); 10448 } 10449 *submat = NULL; 10450 PetscFunctionReturn(PETSC_SUCCESS); 10451 } 10452 10453 /*@ 10454 MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix 10455 10456 Collective 10457 10458 Input Parameter: 10459 . mat - the matrix 10460 10461 Output Parameter: 10462 . is - if any rows have zero diagonals this contains the list of them 10463 10464 Level: developer 10465 10466 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10467 @*/ 10468 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is) 10469 { 10470 PetscFunctionBegin; 10471 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10472 PetscValidType(mat, 1); 10473 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10474 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10475 10476 if (!mat->ops->findzerodiagonals) { 10477 Vec diag; 10478 const PetscScalar *a; 10479 PetscInt *rows; 10480 PetscInt rStart, rEnd, r, nrow = 0; 10481 10482 PetscCall(MatCreateVecs(mat, &diag, NULL)); 10483 PetscCall(MatGetDiagonal(mat, diag)); 10484 PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd)); 10485 PetscCall(VecGetArrayRead(diag, &a)); 10486 for (r = 0; r < rEnd - rStart; ++r) 10487 if (a[r] == 0.0) ++nrow; 10488 PetscCall(PetscMalloc1(nrow, &rows)); 10489 nrow = 0; 10490 for (r = 0; r < rEnd - rStart; ++r) 10491 if (a[r] == 0.0) rows[nrow++] = r + rStart; 10492 PetscCall(VecRestoreArrayRead(diag, &a)); 10493 PetscCall(VecDestroy(&diag)); 10494 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is)); 10495 } else { 10496 PetscUseTypeMethod(mat, findzerodiagonals, is); 10497 } 10498 PetscFunctionReturn(PETSC_SUCCESS); 10499 } 10500 10501 /*@ 10502 MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size) 10503 10504 Collective 10505 10506 Input Parameter: 10507 . mat - the matrix 10508 10509 Output Parameter: 10510 . is - contains the list of rows with off block diagonal entries 10511 10512 Level: developer 10513 10514 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10515 @*/ 10516 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is) 10517 { 10518 PetscFunctionBegin; 10519 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10520 PetscValidType(mat, 1); 10521 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10522 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10523 10524 PetscUseTypeMethod(mat, findoffblockdiagonalentries, is); 10525 PetscFunctionReturn(PETSC_SUCCESS); 10526 } 10527 10528 /*@C 10529 MatInvertBlockDiagonal - Inverts the block diagonal entries. 10530 10531 Collective; No Fortran Support 10532 10533 Input Parameter: 10534 . mat - the matrix 10535 10536 Output Parameter: 10537 . values - the block inverses in column major order (FORTRAN-like) 10538 10539 Level: advanced 10540 10541 Notes: 10542 The size of the blocks is determined by the block size of the matrix. 10543 10544 The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case 10545 10546 The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size 10547 10548 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()` 10549 @*/ 10550 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values) 10551 { 10552 PetscFunctionBegin; 10553 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10554 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10555 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10556 PetscUseTypeMethod(mat, invertblockdiagonal, values); 10557 PetscFunctionReturn(PETSC_SUCCESS); 10558 } 10559 10560 /*@C 10561 MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries. 10562 10563 Collective; No Fortran Support 10564 10565 Input Parameters: 10566 + mat - the matrix 10567 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()` 10568 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()` 10569 10570 Output Parameter: 10571 . values - the block inverses in column major order (FORTRAN-like) 10572 10573 Level: advanced 10574 10575 Notes: 10576 Use `MatInvertBlockDiagonal()` if all blocks have the same size 10577 10578 The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case 10579 10580 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()` 10581 @*/ 10582 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values) 10583 { 10584 PetscFunctionBegin; 10585 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10586 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10587 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10588 PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values); 10589 PetscFunctionReturn(PETSC_SUCCESS); 10590 } 10591 10592 /*@ 10593 MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A 10594 10595 Collective 10596 10597 Input Parameters: 10598 + A - the matrix 10599 - C - matrix with inverted block diagonal of `A`. This matrix should be created and may have its type set. 10600 10601 Level: advanced 10602 10603 Note: 10604 The blocksize of the matrix is used to determine the blocks on the diagonal of `C` 10605 10606 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()` 10607 @*/ 10608 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C) 10609 { 10610 const PetscScalar *vals; 10611 PetscInt *dnnz; 10612 PetscInt m, rstart, rend, bs, i, j; 10613 10614 PetscFunctionBegin; 10615 PetscCall(MatInvertBlockDiagonal(A, &vals)); 10616 PetscCall(MatGetBlockSize(A, &bs)); 10617 PetscCall(MatGetLocalSize(A, &m, NULL)); 10618 PetscCall(MatSetLayouts(C, A->rmap, A->cmap)); 10619 PetscCall(PetscMalloc1(m / bs, &dnnz)); 10620 for (j = 0; j < m / bs; j++) dnnz[j] = 1; 10621 PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL)); 10622 PetscCall(PetscFree(dnnz)); 10623 PetscCall(MatGetOwnershipRange(C, &rstart, &rend)); 10624 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE)); 10625 for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES)); 10626 PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 10627 PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 10628 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE)); 10629 PetscFunctionReturn(PETSC_SUCCESS); 10630 } 10631 10632 /*@C 10633 MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created 10634 via `MatTransposeColoringCreate()`. 10635 10636 Collective 10637 10638 Input Parameter: 10639 . c - coloring context 10640 10641 Level: intermediate 10642 10643 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()` 10644 @*/ 10645 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c) 10646 { 10647 MatTransposeColoring matcolor = *c; 10648 10649 PetscFunctionBegin; 10650 if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS); 10651 if (--((PetscObject)matcolor)->refct > 0) { 10652 matcolor = NULL; 10653 PetscFunctionReturn(PETSC_SUCCESS); 10654 } 10655 10656 PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow)); 10657 PetscCall(PetscFree(matcolor->rows)); 10658 PetscCall(PetscFree(matcolor->den2sp)); 10659 PetscCall(PetscFree(matcolor->colorforcol)); 10660 PetscCall(PetscFree(matcolor->columns)); 10661 if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart)); 10662 PetscCall(PetscHeaderDestroy(c)); 10663 PetscFunctionReturn(PETSC_SUCCESS); 10664 } 10665 10666 /*@C 10667 MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which 10668 a `MatTransposeColoring` context has been created, computes a dense B^T by applying 10669 `MatTransposeColoring` to sparse B. 10670 10671 Collective 10672 10673 Input Parameters: 10674 + coloring - coloring context created with `MatTransposeColoringCreate()` 10675 - B - sparse matrix 10676 10677 Output Parameter: 10678 . Btdense - dense matrix B^T 10679 10680 Level: developer 10681 10682 Note: 10683 These are used internally for some implementations of `MatRARt()` 10684 10685 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()` 10686 @*/ 10687 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense) 10688 { 10689 PetscFunctionBegin; 10690 PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10691 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 10692 PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3); 10693 10694 PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense)); 10695 PetscFunctionReturn(PETSC_SUCCESS); 10696 } 10697 10698 /*@C 10699 MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which 10700 a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense 10701 in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix 10702 `Csp` from `Cden`. 10703 10704 Collective 10705 10706 Input Parameters: 10707 + matcoloring - coloring context created with `MatTransposeColoringCreate()` 10708 - Cden - matrix product of a sparse matrix and a dense matrix Btdense 10709 10710 Output Parameter: 10711 . Csp - sparse matrix 10712 10713 Level: developer 10714 10715 Note: 10716 These are used internally for some implementations of `MatRARt()` 10717 10718 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()` 10719 @*/ 10720 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp) 10721 { 10722 PetscFunctionBegin; 10723 PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10724 PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2); 10725 PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3); 10726 10727 PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp)); 10728 PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY)); 10729 PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY)); 10730 PetscFunctionReturn(PETSC_SUCCESS); 10731 } 10732 10733 /*@C 10734 MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T. 10735 10736 Collective 10737 10738 Input Parameters: 10739 + mat - the matrix product C 10740 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()` 10741 10742 Output Parameter: 10743 . color - the new coloring context 10744 10745 Level: intermediate 10746 10747 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`, 10748 `MatTransColoringApplyDenToSp()` 10749 @*/ 10750 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color) 10751 { 10752 MatTransposeColoring c; 10753 MPI_Comm comm; 10754 10755 PetscFunctionBegin; 10756 PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10757 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10758 PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL)); 10759 10760 c->ctype = iscoloring->ctype; 10761 PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c); 10762 10763 *color = c; 10764 PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10765 PetscFunctionReturn(PETSC_SUCCESS); 10766 } 10767 10768 /*@ 10769 MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the 10770 matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the 10771 same, otherwise it will be larger 10772 10773 Not Collective 10774 10775 Input Parameter: 10776 . A - the matrix 10777 10778 Output Parameter: 10779 . state - the current state 10780 10781 Level: intermediate 10782 10783 Notes: 10784 You can only compare states from two different calls to the SAME matrix, you cannot compare calls between 10785 different matrices 10786 10787 Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix 10788 10789 Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers. 10790 10791 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()` 10792 @*/ 10793 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state) 10794 { 10795 PetscFunctionBegin; 10796 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10797 *state = mat->nonzerostate; 10798 PetscFunctionReturn(PETSC_SUCCESS); 10799 } 10800 10801 /*@ 10802 MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential 10803 matrices from each processor 10804 10805 Collective 10806 10807 Input Parameters: 10808 + comm - the communicators the parallel matrix will live on 10809 . seqmat - the input sequential matrices 10810 . n - number of local columns (or `PETSC_DECIDE`) 10811 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10812 10813 Output Parameter: 10814 . mpimat - the parallel matrix generated 10815 10816 Level: developer 10817 10818 Note: 10819 The number of columns of the matrix in EACH processor MUST be the same. 10820 10821 .seealso: [](ch_matrices), `Mat` 10822 @*/ 10823 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat) 10824 { 10825 PetscMPIInt size; 10826 10827 PetscFunctionBegin; 10828 PetscCallMPI(MPI_Comm_size(comm, &size)); 10829 if (size == 1) { 10830 if (reuse == MAT_INITIAL_MATRIX) { 10831 PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat)); 10832 } else { 10833 PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN)); 10834 } 10835 PetscFunctionReturn(PETSC_SUCCESS); 10836 } 10837 10838 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"); 10839 10840 PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0)); 10841 PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat)); 10842 PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0)); 10843 PetscFunctionReturn(PETSC_SUCCESS); 10844 } 10845 10846 /*@ 10847 MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent ranks' ownership ranges. 10848 10849 Collective 10850 10851 Input Parameters: 10852 + A - the matrix to create subdomains from 10853 - N - requested number of subdomains 10854 10855 Output Parameters: 10856 + n - number of subdomains resulting on this rank 10857 - iss - `IS` list with indices of subdomains on this rank 10858 10859 Level: advanced 10860 10861 Note: 10862 The number of subdomains must be smaller than the communicator size 10863 10864 .seealso: [](ch_matrices), `Mat`, `IS` 10865 @*/ 10866 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[]) 10867 { 10868 MPI_Comm comm, subcomm; 10869 PetscMPIInt size, rank, color; 10870 PetscInt rstart, rend, k; 10871 10872 PetscFunctionBegin; 10873 PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 10874 PetscCallMPI(MPI_Comm_size(comm, &size)); 10875 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 10876 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); 10877 *n = 1; 10878 k = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */ 10879 color = rank / k; 10880 PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm)); 10881 PetscCall(PetscMalloc1(1, iss)); 10882 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 10883 PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0])); 10884 PetscCallMPI(MPI_Comm_free(&subcomm)); 10885 PetscFunctionReturn(PETSC_SUCCESS); 10886 } 10887 10888 /*@ 10889 MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection. 10890 10891 If the interpolation and restriction operators are the same, uses `MatPtAP()`. 10892 If they are not the same, uses `MatMatMatMult()`. 10893 10894 Once the coarse grid problem is constructed, correct for interpolation operators 10895 that are not of full rank, which can legitimately happen in the case of non-nested 10896 geometric multigrid. 10897 10898 Input Parameters: 10899 + restrct - restriction operator 10900 . dA - fine grid matrix 10901 . interpolate - interpolation operator 10902 . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10903 - fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate 10904 10905 Output Parameter: 10906 . A - the Galerkin coarse matrix 10907 10908 Options Database Key: 10909 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used 10910 10911 Level: developer 10912 10913 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()` 10914 @*/ 10915 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A) 10916 { 10917 IS zerorows; 10918 Vec diag; 10919 10920 PetscFunctionBegin; 10921 PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10922 /* Construct the coarse grid matrix */ 10923 if (interpolate == restrct) { 10924 PetscCall(MatPtAP(dA, interpolate, reuse, fill, A)); 10925 } else { 10926 PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A)); 10927 } 10928 10929 /* If the interpolation matrix is not of full rank, A will have zero rows. 10930 This can legitimately happen in the case of non-nested geometric multigrid. 10931 In that event, we set the rows of the matrix to the rows of the identity, 10932 ignoring the equations (as the RHS will also be zero). */ 10933 10934 PetscCall(MatFindZeroRows(*A, &zerorows)); 10935 10936 if (zerorows != NULL) { /* if there are any zero rows */ 10937 PetscCall(MatCreateVecs(*A, &diag, NULL)); 10938 PetscCall(MatGetDiagonal(*A, diag)); 10939 PetscCall(VecISSet(diag, zerorows, 1.0)); 10940 PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES)); 10941 PetscCall(VecDestroy(&diag)); 10942 PetscCall(ISDestroy(&zerorows)); 10943 } 10944 PetscFunctionReturn(PETSC_SUCCESS); 10945 } 10946 10947 /*@C 10948 MatSetOperation - Allows user to set a matrix operation for any matrix type 10949 10950 Logically Collective 10951 10952 Input Parameters: 10953 + mat - the matrix 10954 . op - the name of the operation 10955 - f - the function that provides the operation 10956 10957 Level: developer 10958 10959 Usage: 10960 .vb 10961 extern PetscErrorCode usermult(Mat, Vec, Vec); 10962 10963 PetscCall(MatCreateXXX(comm, ..., &A)); 10964 PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFunction)usermult)); 10965 .ve 10966 10967 Notes: 10968 See the file `include/petscmat.h` for a complete list of matrix 10969 operations, which all have the form MATOP_<OPERATION>, where 10970 <OPERATION> is the name (in all capital letters) of the 10971 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 10972 10973 All user-provided functions (except for `MATOP_DESTROY`) should have the same calling 10974 sequence as the usual matrix interface routines, since they 10975 are intended to be accessed via the usual matrix interface 10976 routines, e.g., 10977 .vb 10978 MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec) 10979 .ve 10980 10981 In particular each function MUST return `PETSC_SUCCESS` on success and 10982 nonzero on failure. 10983 10984 This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type. 10985 10986 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()` 10987 @*/ 10988 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void)) 10989 { 10990 PetscFunctionBegin; 10991 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10992 if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view; 10993 (((void (**)(void))mat->ops)[op]) = f; 10994 PetscFunctionReturn(PETSC_SUCCESS); 10995 } 10996 10997 /*@C 10998 MatGetOperation - Gets a matrix operation for any matrix type. 10999 11000 Not Collective 11001 11002 Input Parameters: 11003 + mat - the matrix 11004 - op - the name of the operation 11005 11006 Output Parameter: 11007 . f - the function that provides the operation 11008 11009 Level: developer 11010 11011 Usage: 11012 .vb 11013 PetscErrorCode (*usermult)(Mat, Vec, Vec); 11014 MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult); 11015 .ve 11016 11017 Notes: 11018 See the file include/petscmat.h for a complete list of matrix 11019 operations, which all have the form MATOP_<OPERATION>, where 11020 <OPERATION> is the name (in all capital letters) of the 11021 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11022 11023 This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type. 11024 11025 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()` 11026 @*/ 11027 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void)) 11028 { 11029 PetscFunctionBegin; 11030 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11031 *f = (((void (**)(void))mat->ops)[op]); 11032 PetscFunctionReturn(PETSC_SUCCESS); 11033 } 11034 11035 /*@ 11036 MatHasOperation - Determines whether the given matrix supports the particular operation. 11037 11038 Not Collective 11039 11040 Input Parameters: 11041 + mat - the matrix 11042 - op - the operation, for example, `MATOP_GET_DIAGONAL` 11043 11044 Output Parameter: 11045 . has - either `PETSC_TRUE` or `PETSC_FALSE` 11046 11047 Level: advanced 11048 11049 Note: 11050 See `MatSetOperation()` for additional discussion on naming convention and usage of `op`. 11051 11052 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()` 11053 @*/ 11054 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has) 11055 { 11056 PetscFunctionBegin; 11057 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11058 PetscValidBoolPointer(has, 3); 11059 if (mat->ops->hasoperation) { 11060 PetscUseTypeMethod(mat, hasoperation, op, has); 11061 } else { 11062 if (((void **)mat->ops)[op]) *has = PETSC_TRUE; 11063 else { 11064 *has = PETSC_FALSE; 11065 if (op == MATOP_CREATE_SUBMATRIX) { 11066 PetscMPIInt size; 11067 11068 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 11069 if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has)); 11070 } 11071 } 11072 } 11073 PetscFunctionReturn(PETSC_SUCCESS); 11074 } 11075 11076 /*@ 11077 MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent 11078 11079 Collective 11080 11081 Input Parameter: 11082 . mat - the matrix 11083 11084 Output Parameter: 11085 . cong - either `PETSC_TRUE` or `PETSC_FALSE` 11086 11087 Level: beginner 11088 11089 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout` 11090 @*/ 11091 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong) 11092 { 11093 PetscFunctionBegin; 11094 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11095 PetscValidType(mat, 1); 11096 PetscValidBoolPointer(cong, 2); 11097 if (!mat->rmap || !mat->cmap) { 11098 *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE; 11099 PetscFunctionReturn(PETSC_SUCCESS); 11100 } 11101 if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */ 11102 PetscCall(PetscLayoutSetUp(mat->rmap)); 11103 PetscCall(PetscLayoutSetUp(mat->cmap)); 11104 PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong)); 11105 if (*cong) mat->congruentlayouts = 1; 11106 else mat->congruentlayouts = 0; 11107 } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE; 11108 PetscFunctionReturn(PETSC_SUCCESS); 11109 } 11110 11111 PetscErrorCode MatSetInf(Mat A) 11112 { 11113 PetscFunctionBegin; 11114 PetscUseTypeMethod(A, setinf); 11115 PetscFunctionReturn(PETSC_SUCCESS); 11116 } 11117 11118 /*@C 11119 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 11120 and possibly removes small values from the graph structure. 11121 11122 Collective 11123 11124 Input Parameters: 11125 + A - the matrix 11126 . sym - `PETSC_TRUE` indicates that the graph should be symmetrized 11127 . scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry 11128 - filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value 11129 11130 Output Parameter: 11131 . graph - the resulting graph 11132 11133 Level: advanced 11134 11135 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG` 11136 @*/ 11137 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph) 11138 { 11139 PetscFunctionBegin; 11140 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11141 PetscValidType(A, 1); 11142 PetscValidLogicalCollectiveBool(A, scale, 3); 11143 PetscValidPointer(graph, 5); 11144 PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph); 11145 PetscFunctionReturn(PETSC_SUCCESS); 11146 } 11147 11148 /*@ 11149 MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place, 11150 meaning the same memory is used for the matrix, and no new memory is allocated. 11151 11152 Collective 11153 11154 Input Parameter: 11155 . A - the matrix 11156 11157 Level: intermediate 11158 11159 Developer Note: 11160 The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end 11161 of the arrays in the data structure are unneeded. 11162 11163 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatChop()` 11164 @*/ 11165 PetscErrorCode MatEliminateZeros(Mat A) 11166 { 11167 PetscFunctionBegin; 11168 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11169 PetscUseTypeMethod(A, eliminatezeros); 11170 PetscFunctionReturn(PETSC_SUCCESS); 11171 } 11172