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_Mults, 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_Getsymtranspose, MAT_Getsymtransreduced, MAT_GetBrowsOfAcols; 34 PetscLogEvent MAT_GetBrowsOfAocols, MAT_Getlocalmat, MAT_Getlocalmatcondensed, MAT_Seqstompi, MAT_Seqstompinum, MAT_Seqstompisym; 35 PetscLogEvent MAT_Applypapt, MAT_Applypapt_numeric, MAT_Applypapt_symbolic, MAT_GetSequentialNonzeroStructure; 36 PetscLogEvent MAT_GetMultiProcBlock; 37 PetscLogEvent MAT_CUSPARSECopyToGPU, MAT_CUSPARSECopyFromGPU, MAT_CUSPARSEGenerateTranspose, MAT_CUSPARSESolveAnalysis; 38 PetscLogEvent MAT_HIPSPARSECopyToGPU, MAT_HIPSPARSECopyFromGPU, MAT_HIPSPARSEGenerateTranspose, MAT_HIPSPARSESolveAnalysis; 39 PetscLogEvent MAT_PreallCOO, MAT_SetVCOO; 40 PetscLogEvent MAT_SetValuesBatch; 41 PetscLogEvent MAT_ViennaCLCopyToGPU; 42 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU; 43 PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom; 44 PetscLogEvent MAT_FactorFactS, MAT_FactorInvS; 45 PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights; 46 PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR; 47 48 const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL}; 49 50 /*@ 51 MatSetRandom - Sets all components of a matrix to random numbers. 52 53 Logically Collective 54 55 Input Parameters: 56 + x - the matrix 57 - rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or `NULL` and 58 it will create one internally. 59 60 Example: 61 .vb 62 PetscRandomCreate(PETSC_COMM_WORLD,&rctx); 63 MatSetRandom(x,rctx); 64 PetscRandomDestroy(rctx); 65 .ve 66 67 Level: intermediate 68 69 Notes: 70 For sparse matrices that have been preallocated but not been assembled it randomly selects appropriate locations, 71 72 for sparse matrices that already have locations it fills the locations with random numbers. 73 74 It generates an error if used on sparse matrices that have not been preallocated. 75 76 .seealso: [](chapter_matrices), `Mat`, `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomCreate()`, `PetscRandomDestroy()` 77 @*/ 78 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx) 79 { 80 PetscRandom randObj = NULL; 81 82 PetscFunctionBegin; 83 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 84 if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2); 85 PetscValidType(x, 1); 86 MatCheckPreallocated(x, 1); 87 88 if (!rctx) { 89 MPI_Comm comm; 90 PetscCall(PetscObjectGetComm((PetscObject)x, &comm)); 91 PetscCall(PetscRandomCreate(comm, &randObj)); 92 PetscCall(PetscRandomSetType(randObj, x->defaultrandtype)); 93 PetscCall(PetscRandomSetFromOptions(randObj)); 94 rctx = randObj; 95 } 96 PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0)); 97 PetscUseTypeMethod(x, setrandom, rctx); 98 PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0)); 99 100 PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY)); 101 PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY)); 102 PetscCall(PetscRandomDestroy(&randObj)); 103 PetscFunctionReturn(PETSC_SUCCESS); 104 } 105 106 /*@ 107 MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in 108 109 Logically Collective 110 111 Input Parameter: 112 . mat - the factored matrix 113 114 Output Parameters: 115 + pivot - the pivot value computed 116 - row - the row that the zero pivot occurred. This row value must be interpreted carefully due to row reorderings and which processes 117 the share the matrix 118 119 Level: advanced 120 121 Notes: 122 This routine does not work for factorizations done with external packages. 123 124 This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT` 125 126 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 127 128 .seealso: [](chapter_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, 129 `MAT_FACTOR_NUMERIC_ZEROPIVOT` 130 @*/ 131 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row) 132 { 133 PetscFunctionBegin; 134 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 135 PetscValidRealPointer(pivot, 2); 136 PetscValidIntPointer(row, 3); 137 *pivot = mat->factorerror_zeropivot_value; 138 *row = mat->factorerror_zeropivot_row; 139 PetscFunctionReturn(PETSC_SUCCESS); 140 } 141 142 /*@ 143 MatFactorGetError - gets the error code from a factorization 144 145 Logically Collective 146 147 Input Parameter: 148 . mat - the factored matrix 149 150 Output Parameter: 151 . err - the error code 152 153 Level: advanced 154 155 Note: 156 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 157 158 .seealso: [](chapter_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, 159 `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, `MatFactorError` 160 @*/ 161 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err) 162 { 163 PetscFunctionBegin; 164 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 165 PetscValidPointer(err, 2); 166 *err = mat->factorerrortype; 167 PetscFunctionReturn(PETSC_SUCCESS); 168 } 169 170 /*@ 171 MatFactorClearError - clears the error code in a factorization 172 173 Logically Collective 174 175 Input Parameter: 176 . mat - the factored matrix 177 178 Level: developer 179 180 Note: 181 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 182 183 .seealso: [](chapter_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`, 184 `MatGetErrorCode()`, `MatFactorError` 185 @*/ 186 PetscErrorCode MatFactorClearError(Mat mat) 187 { 188 PetscFunctionBegin; 189 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 190 mat->factorerrortype = MAT_FACTOR_NOERROR; 191 mat->factorerror_zeropivot_value = 0.0; 192 mat->factorerror_zeropivot_row = 0; 193 PetscFunctionReturn(PETSC_SUCCESS); 194 } 195 196 PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero) 197 { 198 Vec r, l; 199 const PetscScalar *al; 200 PetscInt i, nz, gnz, N, n; 201 202 PetscFunctionBegin; 203 PetscCall(MatCreateVecs(mat, &r, &l)); 204 if (!cols) { /* nonzero rows */ 205 PetscCall(MatGetSize(mat, &N, NULL)); 206 PetscCall(MatGetLocalSize(mat, &n, NULL)); 207 PetscCall(VecSet(l, 0.0)); 208 PetscCall(VecSetRandom(r, NULL)); 209 PetscCall(MatMult(mat, r, l)); 210 PetscCall(VecGetArrayRead(l, &al)); 211 } else { /* nonzero columns */ 212 PetscCall(MatGetSize(mat, NULL, &N)); 213 PetscCall(MatGetLocalSize(mat, NULL, &n)); 214 PetscCall(VecSet(r, 0.0)); 215 PetscCall(VecSetRandom(l, NULL)); 216 PetscCall(MatMultTranspose(mat, l, r)); 217 PetscCall(VecGetArrayRead(r, &al)); 218 } 219 if (tol <= 0.0) { 220 for (i = 0, nz = 0; i < n; i++) 221 if (al[i] != 0.0) nz++; 222 } else { 223 for (i = 0, nz = 0; i < n; i++) 224 if (PetscAbsScalar(al[i]) > tol) nz++; 225 } 226 PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 227 if (gnz != N) { 228 PetscInt *nzr; 229 PetscCall(PetscMalloc1(nz, &nzr)); 230 if (nz) { 231 if (tol < 0) { 232 for (i = 0, nz = 0; i < n; i++) 233 if (al[i] != 0.0) nzr[nz++] = i; 234 } else { 235 for (i = 0, nz = 0; i < n; i++) 236 if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i; 237 } 238 } 239 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero)); 240 } else *nonzero = NULL; 241 if (!cols) { /* nonzero rows */ 242 PetscCall(VecRestoreArrayRead(l, &al)); 243 } else { 244 PetscCall(VecRestoreArrayRead(r, &al)); 245 } 246 PetscCall(VecDestroy(&l)); 247 PetscCall(VecDestroy(&r)); 248 PetscFunctionReturn(PETSC_SUCCESS); 249 } 250 251 /*@ 252 MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix 253 254 Input Parameter: 255 . A - the matrix 256 257 Output Parameter: 258 . keptrows - the rows that are not completely zero 259 260 Level: intermediate 261 262 Note: 263 `keptrows` is set to `NULL` if all rows are nonzero. 264 265 .seealso: [](chapter_matrices), `Mat`, `MatFindZeroRows()` 266 @*/ 267 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows) 268 { 269 PetscFunctionBegin; 270 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 271 PetscValidType(mat, 1); 272 PetscValidPointer(keptrows, 2); 273 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 274 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 275 if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows); 276 else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows)); 277 PetscFunctionReturn(PETSC_SUCCESS); 278 } 279 280 /*@ 281 MatFindZeroRows - Locate all rows that are completely zero in the matrix 282 283 Input Parameter: 284 . A - the matrix 285 286 Output Parameter: 287 . zerorows - the rows that are completely zero 288 289 Level: intermediate 290 291 Note: 292 `zerorows` is set to `NULL` if no rows are zero. 293 294 .seealso: [](chapter_matrices), `Mat`, `MatFindNonzeroRows()` 295 @*/ 296 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows) 297 { 298 IS keptrows; 299 PetscInt m, n; 300 301 PetscFunctionBegin; 302 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 303 PetscValidType(mat, 1); 304 PetscValidPointer(zerorows, 2); 305 PetscCall(MatFindNonzeroRows(mat, &keptrows)); 306 /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows. 307 In keeping with this convention, we set zerorows to NULL if there are no zero 308 rows. */ 309 if (keptrows == NULL) { 310 *zerorows = NULL; 311 } else { 312 PetscCall(MatGetOwnershipRange(mat, &m, &n)); 313 PetscCall(ISComplement(keptrows, m, n, zerorows)); 314 PetscCall(ISDestroy(&keptrows)); 315 } 316 PetscFunctionReturn(PETSC_SUCCESS); 317 } 318 319 /*@ 320 MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling 321 322 Not Collective 323 324 Input Parameter: 325 . A - the matrix 326 327 Output Parameter: 328 . a - the diagonal part (which is a SEQUENTIAL matrix) 329 330 Level: advanced 331 332 Notes: 333 See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix. 334 335 Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation. 336 337 .seealso: [](chapter_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ` 338 @*/ 339 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a) 340 { 341 PetscFunctionBegin; 342 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 343 PetscValidType(A, 1); 344 PetscValidPointer(a, 2); 345 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 346 if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a); 347 else { 348 PetscMPIInt size; 349 350 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 351 PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name); 352 *a = A; 353 } 354 PetscFunctionReturn(PETSC_SUCCESS); 355 } 356 357 /*@ 358 MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries. 359 360 Collective 361 362 Input Parameter: 363 . mat - the matrix 364 365 Output Parameter: 366 . trace - the sum of the diagonal entries 367 368 Level: advanced 369 370 .seealso: [](chapter_matrices), `Mat` 371 @*/ 372 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace) 373 { 374 Vec diag; 375 376 PetscFunctionBegin; 377 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 378 PetscValidScalarPointer(trace, 2); 379 PetscCall(MatCreateVecs(mat, &diag, NULL)); 380 PetscCall(MatGetDiagonal(mat, diag)); 381 PetscCall(VecSum(diag, trace)); 382 PetscCall(VecDestroy(&diag)); 383 PetscFunctionReturn(PETSC_SUCCESS); 384 } 385 386 /*@ 387 MatRealPart - Zeros out the imaginary part of the matrix 388 389 Logically Collective 390 391 Input Parameter: 392 . mat - the matrix 393 394 Level: advanced 395 396 .seealso: [](chapter_matrices), `Mat`, `MatImaginaryPart()` 397 @*/ 398 PetscErrorCode MatRealPart(Mat mat) 399 { 400 PetscFunctionBegin; 401 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 402 PetscValidType(mat, 1); 403 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 404 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 405 MatCheckPreallocated(mat, 1); 406 PetscUseTypeMethod(mat, realpart); 407 PetscFunctionReturn(PETSC_SUCCESS); 408 } 409 410 /*@C 411 MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix 412 413 Collective 414 415 Input Parameter: 416 . mat - the matrix 417 418 Output Parameters: 419 + nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each block) 420 - ghosts - the global indices of the ghost points 421 422 Level: advanced 423 424 Note: 425 `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()` 426 427 .seealso: [](chapter_matrices), `Mat`, `VecCreateGhost()` 428 @*/ 429 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[]) 430 { 431 PetscFunctionBegin; 432 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 433 PetscValidType(mat, 1); 434 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 435 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 436 if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts); 437 else { 438 if (nghosts) *nghosts = 0; 439 if (ghosts) *ghosts = NULL; 440 } 441 PetscFunctionReturn(PETSC_SUCCESS); 442 } 443 444 /*@ 445 MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part 446 447 Logically Collective 448 449 Input Parameter: 450 . mat - the matrix 451 452 Level: advanced 453 454 .seealso: [](chapter_matrices), `Mat`, `MatRealPart()` 455 @*/ 456 PetscErrorCode MatImaginaryPart(Mat mat) 457 { 458 PetscFunctionBegin; 459 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 460 PetscValidType(mat, 1); 461 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 462 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 463 MatCheckPreallocated(mat, 1); 464 PetscUseTypeMethod(mat, imaginarypart); 465 PetscFunctionReturn(PETSC_SUCCESS); 466 } 467 468 /*@ 469 MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices) 470 471 Not Collective 472 473 Input Parameter: 474 . mat - the matrix 475 476 Output Parameters: 477 + missing - is any diagonal missing 478 - dd - first diagonal entry that is missing (optional) on this process 479 480 Level: advanced 481 482 .seealso: [](chapter_matrices), `Mat` 483 @*/ 484 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd) 485 { 486 PetscFunctionBegin; 487 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 488 PetscValidType(mat, 1); 489 PetscValidBoolPointer(missing, 2); 490 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name); 491 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 492 PetscUseTypeMethod(mat, missingdiagonal, missing, dd); 493 PetscFunctionReturn(PETSC_SUCCESS); 494 } 495 496 /*@C 497 MatGetRow - Gets a row of a matrix. You MUST call `MatRestoreRow()` 498 for each row that you get to ensure that your application does 499 not bleed memory. 500 501 Not Collective 502 503 Input Parameters: 504 + mat - the matrix 505 - row - the row to get 506 507 Output Parameters: 508 + ncols - if not `NULL`, the number of nonzeros in the row 509 . cols - if not `NULL`, the column numbers 510 - vals - if not `NULL`, the values 511 512 Level: advanced 513 514 Notes: 515 This routine is provided for people who need to have direct access 516 to the structure of a matrix. We hope that we provide enough 517 high-level matrix routines that few users will need it. 518 519 `MatGetRow()` always returns 0-based column indices, regardless of 520 whether the internal representation is 0-based (default) or 1-based. 521 522 For better efficiency, set cols and/or vals to `NULL` if you do 523 not wish to extract these quantities. 524 525 The user can only examine the values extracted with `MatGetRow()`; 526 the values cannot be altered. To change the matrix entries, one 527 must use `MatSetValues()`. 528 529 You can only have one call to `MatGetRow()` outstanding for a particular 530 matrix at a time, per processor. `MatGetRow()` can only obtain rows 531 associated with the given processor, it cannot get rows from the 532 other processors; for that we suggest using `MatCreateSubMatrices()`, then 533 MatGetRow() on the submatrix. The row index passed to `MatGetRow()` 534 is in the global number of rows. 535 536 Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix. 537 538 Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly. 539 540 Fortran Note: 541 The calling sequence is 542 .vb 543 MatGetRow(matrix,row,ncols,cols,values,ierr) 544 Mat matrix (input) 545 integer row (input) 546 integer ncols (output) 547 integer cols(maxcols) (output) 548 double precision (or double complex) values(maxcols) output 549 .ve 550 where maxcols >= maximum nonzeros in any row of the matrix. 551 552 Caution: 553 Do not try to change the contents of the output arrays (`cols` and `vals`). 554 In some cases, this may corrupt the matrix. 555 556 .seealso: [](chapter_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()` 557 @*/ 558 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 559 { 560 PetscInt incols; 561 562 PetscFunctionBegin; 563 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 564 PetscValidType(mat, 1); 565 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 566 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 567 MatCheckPreallocated(mat, 1); 568 PetscCheck(row >= mat->rmap->rstart && row < mat->rmap->rend, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Only for local rows, %" PetscInt_FMT " not in [%" PetscInt_FMT ",%" PetscInt_FMT ")", row, mat->rmap->rstart, mat->rmap->rend); 569 PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0)); 570 PetscCall((*mat->ops->getrow)(mat, row, &incols, (PetscInt **)cols, (PetscScalar **)vals)); 571 if (ncols) *ncols = incols; 572 PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0)); 573 PetscFunctionReturn(PETSC_SUCCESS); 574 } 575 576 /*@ 577 MatConjugate - replaces the matrix values with their complex conjugates 578 579 Logically Collective 580 581 Input Parameter: 582 . mat - the matrix 583 584 Level: advanced 585 586 .seealso: [](chapter_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()` 587 @*/ 588 PetscErrorCode MatConjugate(Mat mat) 589 { 590 PetscFunctionBegin; 591 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 592 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 593 if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) { 594 PetscUseTypeMethod(mat, conjugate); 595 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 596 } 597 PetscFunctionReturn(PETSC_SUCCESS); 598 } 599 600 /*@C 601 MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`. 602 603 Not Collective 604 605 Input Parameters: 606 + mat - the matrix 607 . row - the row to get 608 . ncols - the number of nonzeros 609 . cols - the columns of the nonzeros 610 - vals - if nonzero the column values 611 612 Level: advanced 613 614 Notes: 615 This routine should be called after you have finished examining the entries. 616 617 This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental 618 us of the array after it has been restored. If you pass `NULL`, it will 619 not zero the pointers. Use of `cols` or `vals` after `MatRestoreRow()` is invalid. 620 621 Fortran Notes: 622 The calling sequence is 623 .vb 624 MatRestoreRow(matrix,row,ncols,cols,values,ierr) 625 Mat matrix (input) 626 integer row (input) 627 integer ncols (output) 628 integer cols(maxcols) (output) 629 double precision (or double complex) values(maxcols) output 630 .ve 631 Where maxcols >= maximum nonzeros in any row of the matrix. 632 633 In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()` 634 before another call to `MatGetRow()` can be made. 635 636 .seealso: [](chapter_matrices), `Mat`, `MatGetRow()` 637 @*/ 638 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 639 { 640 PetscFunctionBegin; 641 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 642 if (ncols) PetscValidIntPointer(ncols, 3); 643 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 644 if (!mat->ops->restorerow) PetscFunctionReturn(PETSC_SUCCESS); 645 PetscCall((*mat->ops->restorerow)(mat, row, ncols, (PetscInt **)cols, (PetscScalar **)vals)); 646 if (ncols) *ncols = 0; 647 if (cols) *cols = NULL; 648 if (vals) *vals = NULL; 649 PetscFunctionReturn(PETSC_SUCCESS); 650 } 651 652 /*@ 653 MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 654 You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag. 655 656 Not Collective 657 658 Input Parameter: 659 . mat - the matrix 660 661 Level: advanced 662 663 Note: 664 The flag is to ensure that users are aware that `MatGetRow()` only provides the upper triangular part of the row for the matrices in `MATSBAIJ` format. 665 666 .seealso: [](chapter_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()` 667 @*/ 668 PetscErrorCode MatGetRowUpperTriangular(Mat mat) 669 { 670 PetscFunctionBegin; 671 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 672 PetscValidType(mat, 1); 673 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 674 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 675 MatCheckPreallocated(mat, 1); 676 if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS); 677 PetscUseTypeMethod(mat, getrowuppertriangular); 678 PetscFunctionReturn(PETSC_SUCCESS); 679 } 680 681 /*@ 682 MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 683 684 Not Collective 685 686 Input Parameter: 687 . mat - the matrix 688 689 Level: advanced 690 691 Note: 692 This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`. 693 694 .seealso: [](chapter_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()` 695 @*/ 696 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat) 697 { 698 PetscFunctionBegin; 699 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 700 PetscValidType(mat, 1); 701 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 702 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 703 MatCheckPreallocated(mat, 1); 704 if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS); 705 PetscUseTypeMethod(mat, restorerowuppertriangular); 706 PetscFunctionReturn(PETSC_SUCCESS); 707 } 708 709 /*@C 710 MatSetOptionsPrefix - Sets the prefix used for searching for all 711 `Mat` options in the database. 712 713 Logically Collective 714 715 Input Parameters: 716 + A - the matrix 717 - prefix - the prefix to prepend to all option names 718 719 Level: advanced 720 721 Notes: 722 A hyphen (-) must NOT be given at the beginning of the prefix name. 723 The first character of all runtime options is AUTOMATICALLY the hyphen. 724 725 This is NOT used for options for the factorization of the matrix. Normally the 726 prefix is automatically passed in from the PC calling the factorization. To set 727 it directly use `MatSetOptionsPrefixFactor()` 728 729 .seealso: [](chapter_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()` 730 @*/ 731 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[]) 732 { 733 PetscFunctionBegin; 734 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 735 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix)); 736 PetscFunctionReturn(PETSC_SUCCESS); 737 } 738 739 /*@C 740 MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for 741 for matrices created with `MatGetFactor()` 742 743 Logically Collective 744 745 Input Parameters: 746 + A - the matrix 747 - prefix - the prefix to prepend to all option names for the factored matrix 748 749 Level: developer 750 751 Notes: 752 A hyphen (-) must NOT be given at the beginning of the prefix name. 753 The first character of all runtime options is AUTOMATICALLY the hyphen. 754 755 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 756 it directly when not using `KSP`/`PC` use `MatSetOptionsPrefixFactor()` 757 758 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()` 759 @*/ 760 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[]) 761 { 762 PetscFunctionBegin; 763 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 764 if (prefix) { 765 PetscValidCharPointer(prefix, 2); 766 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 767 if (prefix != A->factorprefix) { 768 PetscCall(PetscFree(A->factorprefix)); 769 PetscCall(PetscStrallocpy(prefix, &A->factorprefix)); 770 } 771 } else PetscCall(PetscFree(A->factorprefix)); 772 PetscFunctionReturn(PETSC_SUCCESS); 773 } 774 775 /*@C 776 MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for 777 for matrices created with `MatGetFactor()` 778 779 Logically Collective 780 781 Input Parameters: 782 + A - the matrix 783 - prefix - the prefix to prepend to all option names for the factored matrix 784 785 Level: developer 786 787 Notes: 788 A hyphen (-) must NOT be given at the beginning of the prefix name. 789 The first character of all runtime options is AUTOMATICALLY the hyphen. 790 791 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 792 it directly when not using `KSP`/`PC` use `MatAppendOptionsPrefixFactor()` 793 794 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`, 795 `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`, 796 `MatSetOptionsPrefix()` 797 @*/ 798 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[]) 799 { 800 size_t len1, len2, new_len; 801 802 PetscFunctionBegin; 803 PetscValidHeader(A, 1); 804 if (!prefix) PetscFunctionReturn(PETSC_SUCCESS); 805 if (!A->factorprefix) { 806 PetscCall(MatSetOptionsPrefixFactor(A, prefix)); 807 PetscFunctionReturn(PETSC_SUCCESS); 808 } 809 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 810 811 PetscCall(PetscStrlen(A->factorprefix, &len1)); 812 PetscCall(PetscStrlen(prefix, &len2)); 813 new_len = len1 + len2 + 1; 814 PetscCall(PetscRealloc(new_len * sizeof(*(A->factorprefix)), &A->factorprefix)); 815 PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1)); 816 PetscFunctionReturn(PETSC_SUCCESS); 817 } 818 819 /*@C 820 MatAppendOptionsPrefix - Appends to the prefix used for searching for all 821 matrix options in the database. 822 823 Logically Collective 824 825 Input Parameters: 826 + A - the matrix 827 - prefix - the prefix to prepend to all option names 828 829 Level: advanced 830 831 Note: 832 A hyphen (-) must NOT be given at the beginning of the prefix name. 833 The first character of all runtime options is AUTOMATICALLY the hyphen. 834 835 .seealso: [](chapter_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()` 836 @*/ 837 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[]) 838 { 839 PetscFunctionBegin; 840 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 841 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix)); 842 PetscFunctionReturn(PETSC_SUCCESS); 843 } 844 845 /*@C 846 MatGetOptionsPrefix - Gets the prefix used for searching for all 847 matrix options in the database. 848 849 Not Collective 850 851 Input Parameter: 852 . A - the matrix 853 854 Output Parameter: 855 . prefix - pointer to the prefix string used 856 857 Level: advanced 858 859 Fortran Note: 860 The user should pass in a string `prefix` of 861 sufficient length to hold the prefix. 862 863 .seealso: [](chapter_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()` 864 @*/ 865 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[]) 866 { 867 PetscFunctionBegin; 868 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 869 PetscValidPointer(prefix, 2); 870 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix)); 871 PetscFunctionReturn(PETSC_SUCCESS); 872 } 873 874 /*@ 875 MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by users. 876 877 Collective 878 879 Input Parameter: 880 . A - the matrix 881 882 Level: beginner 883 884 Notes: 885 The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`. 886 887 Users can reset the preallocation to access the original memory. 888 889 Currently only supported for `MATAIJ` matrices. 890 891 .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()` 892 @*/ 893 PetscErrorCode MatResetPreallocation(Mat A) 894 { 895 PetscFunctionBegin; 896 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 897 PetscValidType(A, 1); 898 PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A)); 899 PetscFunctionReturn(PETSC_SUCCESS); 900 } 901 902 /*@ 903 MatSetUp - Sets up the internal matrix data structures for later use. 904 905 Collective 906 907 Input Parameter: 908 . A - the matrix 909 910 Level: intermediate 911 912 Notes: 913 If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of 914 setting values in the matrix. 915 916 If a suitable preallocation routine is used, this function does not need to be called. 917 918 This routine is called internally by other matrix functions when needed so rarely needs to be called by users 919 920 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()` 921 @*/ 922 PetscErrorCode MatSetUp(Mat A) 923 { 924 PetscFunctionBegin; 925 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 926 if (!((PetscObject)A)->type_name) { 927 PetscMPIInt size; 928 929 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 930 PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ)); 931 } 932 if (!A->preallocated) PetscTryTypeMethod(A, setup); 933 PetscCall(PetscLayoutSetUp(A->rmap)); 934 PetscCall(PetscLayoutSetUp(A->cmap)); 935 A->preallocated = PETSC_TRUE; 936 PetscFunctionReturn(PETSC_SUCCESS); 937 } 938 939 #if defined(PETSC_HAVE_SAWS) 940 #include <petscviewersaws.h> 941 #endif 942 943 /*@C 944 MatViewFromOptions - View properties of the matrix based on options set in the options database 945 946 Collective 947 948 Input Parameters: 949 + A - the matrix 950 . obj - optional additional object that provides the options prefix to use 951 - name - command line option 952 953 Options Database Key: 954 . -mat_view [viewertype]:... - the viewer and its options 955 956 Level: intermediate 957 958 Notes: 959 .vb 960 If no value is provided ascii:stdout is used 961 ascii[:[filename][:[format][:append]]] defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab, 962 for example ascii::ascii_info prints just the information about the object not all details 963 unless :append is given filename opens in write mode, overwriting what was already there 964 binary[:[filename][:[format][:append]]] defaults to the file binaryoutput 965 draw[:drawtype[:filename]] for example, draw:tikz, draw:tikz:figure.tex or draw:x 966 socket[:port] defaults to the standard output port 967 saws[:communicatorname] publishes object to the Scientific Application Webserver (SAWs) 968 .ve 969 970 .seealso: [](chapter_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()` 971 @*/ 972 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[]) 973 { 974 PetscFunctionBegin; 975 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 976 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 977 PetscFunctionReturn(PETSC_SUCCESS); 978 } 979 980 /*@C 981 MatView - display information about a matrix in a variety ways 982 983 Collective 984 985 Input Parameters: 986 + mat - the matrix 987 - viewer - visualization context 988 989 Options Database Keys: 990 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 991 . -mat_view ::ascii_info_detail - Prints more detailed info 992 . -mat_view - Prints matrix in ASCII format 993 . -mat_view ::ascii_matlab - Prints matrix in Matlab format 994 . -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 995 . -display <name> - Sets display name (default is host) 996 . -draw_pause <sec> - Sets number of seconds to pause after display 997 . -mat_view socket - Sends matrix to socket, can be accessed from Matlab (see Users-Manual: ch_matlab for details) 998 . -viewer_socket_machine <machine> - 999 . -viewer_socket_port <port> - 1000 . -mat_view binary - save matrix to file in binary format 1001 - -viewer_binary_filename <name> - 1002 1003 Level: beginner 1004 1005 Notes: 1006 The available visualization contexts include 1007 + `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices 1008 . `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD` 1009 . `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm 1010 - `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure 1011 1012 The user can open alternative visualization contexts with 1013 + `PetscViewerASCIIOpen()` - Outputs matrix to a specified file 1014 . `PetscViewerBinaryOpen()` - Outputs matrix in binary to a 1015 specified file; corresponding input uses MatLoad() 1016 . `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to 1017 an X window display 1018 - `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer. 1019 Currently only the sequential dense and AIJ 1020 matrix types support the Socket viewer. 1021 1022 The user can call `PetscViewerPushFormat()` to specify the output 1023 format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`, 1024 `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`). Available formats include 1025 + `PETSC_VIEWER_DEFAULT` - default, prints matrix contents 1026 . `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in Matlab format 1027 . `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros 1028 . `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse 1029 format common among all matrix types 1030 . `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific 1031 format (which is in many cases the same as the default) 1032 . `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix 1033 size and structure (not the matrix entries) 1034 - `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about 1035 the matrix structure 1036 1037 The ASCII viewers are only recommended for small matrices on at most a moderate number of processes, 1038 the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format. 1039 1040 In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer). 1041 1042 See the manual page for `MatLoad()` for the exact format of the binary file when the binary 1043 viewer is used. 1044 1045 See share/petsc/matlab/PetscBinaryRead.m for a Matlab code that can read in the binary file when the binary 1046 viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python. 1047 1048 One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure, 1049 and then use the following mouse functions. 1050 .vb 1051 left mouse: zoom in 1052 middle mouse: zoom out 1053 right mouse: continue with the simulation 1054 .ve 1055 1056 .seealso: [](chapter_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`, 1057 `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()` 1058 @*/ 1059 PetscErrorCode MatView(Mat mat, PetscViewer viewer) 1060 { 1061 PetscInt rows, cols, rbs, cbs; 1062 PetscBool isascii, isstring, issaws; 1063 PetscViewerFormat format; 1064 PetscMPIInt size; 1065 1066 PetscFunctionBegin; 1067 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1068 PetscValidType(mat, 1); 1069 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer)); 1070 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1071 PetscCheckSameComm(mat, 1, viewer, 2); 1072 1073 PetscCall(PetscViewerGetFormat(viewer, &format)); 1074 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 1075 if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS); 1076 1077 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 1078 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 1079 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws)); 1080 PetscCheck((isascii && (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL)) || !mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "No viewers for factored matrix except ASCII, info, or info_detail"); 1081 1082 PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0)); 1083 if (isascii) { 1084 if (!mat->preallocated) { 1085 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n")); 1086 PetscFunctionReturn(PETSC_SUCCESS); 1087 } 1088 if (!mat->assembled) { 1089 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n")); 1090 PetscFunctionReturn(PETSC_SUCCESS); 1091 } 1092 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer)); 1093 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1094 MatNullSpace nullsp, transnullsp; 1095 1096 PetscCall(PetscViewerASCIIPushTab(viewer)); 1097 PetscCall(MatGetSize(mat, &rows, &cols)); 1098 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1099 if (rbs != 1 || cbs != 1) { 1100 if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs)); 1101 else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs)); 1102 } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols)); 1103 if (mat->factortype) { 1104 MatSolverType solver; 1105 PetscCall(MatFactorGetSolverType(mat, &solver)); 1106 PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver)); 1107 } 1108 if (mat->ops->getinfo) { 1109 MatInfo info; 1110 PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info)); 1111 PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated)); 1112 if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs)); 1113 } 1114 PetscCall(MatGetNullSpace(mat, &nullsp)); 1115 PetscCall(MatGetTransposeNullSpace(mat, &transnullsp)); 1116 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached null space\n")); 1117 if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached transposed null space\n")); 1118 PetscCall(MatGetNearNullSpace(mat, &nullsp)); 1119 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached near null space\n")); 1120 PetscCall(PetscViewerASCIIPushTab(viewer)); 1121 PetscCall(MatProductView(mat, viewer)); 1122 PetscCall(PetscViewerASCIIPopTab(viewer)); 1123 } 1124 } else if (issaws) { 1125 #if defined(PETSC_HAVE_SAWS) 1126 PetscMPIInt rank; 1127 1128 PetscCall(PetscObjectName((PetscObject)mat)); 1129 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 1130 if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer)); 1131 #endif 1132 } else if (isstring) { 1133 const char *type; 1134 PetscCall(MatGetType(mat, &type)); 1135 PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type)); 1136 PetscTryTypeMethod(mat, view, viewer); 1137 } 1138 if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) { 1139 PetscCall(PetscViewerASCIIPushTab(viewer)); 1140 PetscUseTypeMethod(mat, viewnative, viewer); 1141 PetscCall(PetscViewerASCIIPopTab(viewer)); 1142 } else if (mat->ops->view) { 1143 PetscCall(PetscViewerASCIIPushTab(viewer)); 1144 PetscUseTypeMethod(mat, view, viewer); 1145 PetscCall(PetscViewerASCIIPopTab(viewer)); 1146 } 1147 if (isascii) { 1148 PetscCall(PetscViewerGetFormat(viewer, &format)); 1149 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer)); 1150 } 1151 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1152 PetscFunctionReturn(PETSC_SUCCESS); 1153 } 1154 1155 #if defined(PETSC_USE_DEBUG) 1156 #include <../src/sys/totalview/tv_data_display.h> 1157 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat) 1158 { 1159 TV_add_row("Local rows", "int", &mat->rmap->n); 1160 TV_add_row("Local columns", "int", &mat->cmap->n); 1161 TV_add_row("Global rows", "int", &mat->rmap->N); 1162 TV_add_row("Global columns", "int", &mat->cmap->N); 1163 TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name); 1164 return TV_format_OK; 1165 } 1166 #endif 1167 1168 /*@C 1169 MatLoad - Loads a matrix that has been stored in binary/HDF5 format 1170 with `MatView()`. The matrix format is determined from the options database. 1171 Generates a parallel MPI matrix if the communicator has more than one 1172 processor. The default matrix type is `MATAIJ`. 1173 1174 Collective 1175 1176 Input Parameters: 1177 + mat - the newly loaded matrix, this needs to have been created with `MatCreate()` 1178 or some related function before a call to `MatLoad()` 1179 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer 1180 1181 Options Database Keys: 1182 Used with block matrix formats (`MATSEQBAIJ`, ...) to specify 1183 block size 1184 . -matload_block_size <bs> - set block size 1185 1186 Level: beginner 1187 1188 Notes: 1189 If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the 1190 `Mat` before calling this routine if you wish to set it from the options database. 1191 1192 `MatLoad()` automatically loads into the options database any options 1193 given in the file filename.info where filename is the name of the file 1194 that was passed to the `PetscViewerBinaryOpen()`. The options in the info 1195 file will be ignored if you use the -viewer_binary_skip_info option. 1196 1197 If the type or size of mat is not set before a call to `MatLoad()`, PETSc 1198 sets the default matrix type AIJ and sets the local and global sizes. 1199 If type and/or size is already set, then the same are used. 1200 1201 In parallel, each processor can load a subset of rows (or the 1202 entire matrix). This routine is especially useful when a large 1203 matrix is stored on disk and only part of it is desired on each 1204 processor. For example, a parallel solver may access only some of 1205 the rows from each processor. The algorithm used here reads 1206 relatively small blocks of data rather than reading the entire 1207 matrix and then subsetting it. 1208 1209 Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`. 1210 Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`, 1211 or the sequence like 1212 .vb 1213 `PetscViewer` v; 1214 `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v); 1215 `PetscViewerSetType`(v,`PETSCVIEWERBINARY`); 1216 `PetscViewerSetFromOptions`(v); 1217 `PetscViewerFileSetMode`(v,`FILE_MODE_READ`); 1218 `PetscViewerFileSetName`(v,"datafile"); 1219 .ve 1220 The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option 1221 $ -viewer_type {binary,hdf5} 1222 1223 See the example src/ksp/ksp/tutorials/ex27.c with the first approach, 1224 and src/mat/tutorials/ex10.c with the second approach. 1225 1226 In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks 1227 is read onto rank 0 and then shipped to its destination rank, one after another. 1228 Multiple objects, both matrices and vectors, can be stored within the same file. 1229 Their PetscObject name is ignored; they are loaded in the order of their storage. 1230 1231 Most users should not need to know the details of the binary storage 1232 format, since `MatLoad()` and `MatView()` completely hide these details. 1233 But for anyone who's interested, the standard binary matrix storage 1234 format is 1235 1236 .vb 1237 PetscInt MAT_FILE_CLASSID 1238 PetscInt number of rows 1239 PetscInt number of columns 1240 PetscInt total number of nonzeros 1241 PetscInt *number nonzeros in each row 1242 PetscInt *column indices of all nonzeros (starting index is zero) 1243 PetscScalar *values of all nonzeros 1244 .ve 1245 1246 PETSc automatically does the byte swapping for 1247 machines that store the bytes reversed. Thus if you write your own binary 1248 read/write routines you have to swap the bytes; see `PetscBinaryRead()` 1249 and `PetscBinaryWrite()` to see how this may be done. 1250 1251 In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used. 1252 Each processor's chunk is loaded independently by its owning rank. 1253 Multiple objects, both matrices and vectors, can be stored within the same file. 1254 They are looked up by their PetscObject name. 1255 1256 As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use 1257 by default the same structure and naming of the AIJ arrays and column count 1258 within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g. 1259 $ save example.mat A b -v7.3 1260 can be directly read by this routine (see Reference 1 for details). 1261 1262 Depending on your MATLAB version, this format might be a default, 1263 otherwise you can set it as default in Preferences. 1264 1265 Unless -nocompression flag is used to save the file in MATLAB, 1266 PETSc must be configured with ZLIB package. 1267 1268 See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c 1269 1270 This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5` 1271 1272 Corresponding `MatView()` is not yet implemented. 1273 1274 The loaded matrix is actually a transpose of the original one in MATLAB, 1275 unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above). 1276 With this format, matrix is automatically transposed by PETSc, 1277 unless the matrix is marked as SPD or symmetric 1278 (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`). 1279 1280 References: 1281 . * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version 1282 1283 .seealso: [](chapter_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()` 1284 @*/ 1285 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer) 1286 { 1287 PetscBool flg; 1288 1289 PetscFunctionBegin; 1290 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1291 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1292 1293 if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ)); 1294 1295 flg = PETSC_FALSE; 1296 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL)); 1297 if (flg) { 1298 PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE)); 1299 PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE)); 1300 } 1301 flg = PETSC_FALSE; 1302 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL)); 1303 if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE)); 1304 1305 PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0)); 1306 PetscUseTypeMethod(mat, load, viewer); 1307 PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0)); 1308 PetscFunctionReturn(PETSC_SUCCESS); 1309 } 1310 1311 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant) 1312 { 1313 Mat_Redundant *redund = *redundant; 1314 1315 PetscFunctionBegin; 1316 if (redund) { 1317 if (redund->matseq) { /* via MatCreateSubMatrices() */ 1318 PetscCall(ISDestroy(&redund->isrow)); 1319 PetscCall(ISDestroy(&redund->iscol)); 1320 PetscCall(MatDestroySubMatrices(1, &redund->matseq)); 1321 } else { 1322 PetscCall(PetscFree2(redund->send_rank, redund->recv_rank)); 1323 PetscCall(PetscFree(redund->sbuf_j)); 1324 PetscCall(PetscFree(redund->sbuf_a)); 1325 for (PetscInt i = 0; i < redund->nrecvs; i++) { 1326 PetscCall(PetscFree(redund->rbuf_j[i])); 1327 PetscCall(PetscFree(redund->rbuf_a[i])); 1328 } 1329 PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a)); 1330 } 1331 1332 if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm)); 1333 PetscCall(PetscFree(redund)); 1334 } 1335 PetscFunctionReturn(PETSC_SUCCESS); 1336 } 1337 1338 /*@C 1339 MatDestroy - Frees space taken by a matrix. 1340 1341 Collective 1342 1343 Input Parameter: 1344 . A - the matrix 1345 1346 Level: beginner 1347 1348 Developer Note: 1349 Some special arrays of matrices are not destroyed in this routine but instead by the routines called by 1350 `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines. 1351 `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes 1352 if changes are needed here. 1353 1354 .seealso: [](chapter_matrices), `Mat`, `MatCreate()` 1355 @*/ 1356 PetscErrorCode MatDestroy(Mat *A) 1357 { 1358 PetscFunctionBegin; 1359 if (!*A) PetscFunctionReturn(PETSC_SUCCESS); 1360 PetscValidHeaderSpecific(*A, MAT_CLASSID, 1); 1361 if (--((PetscObject)(*A))->refct > 0) { 1362 *A = NULL; 1363 PetscFunctionReturn(PETSC_SUCCESS); 1364 } 1365 1366 /* if memory was published with SAWs then destroy it */ 1367 PetscCall(PetscObjectSAWsViewOff((PetscObject)*A)); 1368 PetscTryTypeMethod((*A), destroy); 1369 1370 PetscCall(PetscFree((*A)->factorprefix)); 1371 PetscCall(PetscFree((*A)->defaultvectype)); 1372 PetscCall(PetscFree((*A)->defaultrandtype)); 1373 PetscCall(PetscFree((*A)->bsizes)); 1374 PetscCall(PetscFree((*A)->solvertype)); 1375 for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i])); 1376 if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL; 1377 PetscCall(MatDestroy_Redundant(&(*A)->redundant)); 1378 PetscCall(MatProductClear(*A)); 1379 PetscCall(MatNullSpaceDestroy(&(*A)->nullsp)); 1380 PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp)); 1381 PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp)); 1382 PetscCall(MatDestroy(&(*A)->schur)); 1383 PetscCall(PetscLayoutDestroy(&(*A)->rmap)); 1384 PetscCall(PetscLayoutDestroy(&(*A)->cmap)); 1385 PetscCall(PetscHeaderDestroy(A)); 1386 PetscFunctionReturn(PETSC_SUCCESS); 1387 } 1388 1389 /*@C 1390 MatSetValues - Inserts or adds a block of values into a matrix. 1391 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1392 MUST be called after all calls to `MatSetValues()` have been completed. 1393 1394 Not Collective 1395 1396 Input Parameters: 1397 + mat - the matrix 1398 . v - a logically two-dimensional array of values 1399 . m - the number of rows 1400 . idxm - the global indices of the rows 1401 . n - the number of columns 1402 . idxn - the global indices of the columns 1403 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1404 1405 Level: beginner 1406 1407 Notes: 1408 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1409 1410 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1411 options cannot be mixed without intervening calls to the assembly 1412 routines. 1413 1414 `MatSetValues()` uses 0-based row and column numbers in Fortran 1415 as well as in C. 1416 1417 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1418 simply ignored. This allows easily inserting element stiffness matrices 1419 with homogeneous Dirchlet boundary conditions that you don't want represented 1420 in the matrix. 1421 1422 Efficiency Alert: 1423 The routine `MatSetValuesBlocked()` may offer much better efficiency 1424 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1425 1426 Developer Note: 1427 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1428 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1429 1430 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1431 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1432 @*/ 1433 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1434 { 1435 PetscFunctionBeginHot; 1436 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1437 PetscValidType(mat, 1); 1438 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1439 PetscValidIntPointer(idxm, 3); 1440 PetscValidIntPointer(idxn, 5); 1441 MatCheckPreallocated(mat, 1); 1442 1443 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1444 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1445 1446 if (PetscDefined(USE_DEBUG)) { 1447 PetscInt i, j; 1448 1449 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1450 for (i = 0; i < m; i++) { 1451 for (j = 0; j < n; j++) { 1452 if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j])) 1453 #if defined(PETSC_USE_COMPLEX) 1454 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Inserting %g+i%g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")", (double)PetscRealPart(v[i * n + j]), (double)PetscImaginaryPart(v[i * n + j]), idxm[i], idxn[j]); 1455 #else 1456 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Inserting %g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")", (double)v[i * n + j], idxm[i], idxn[j]); 1457 #endif 1458 } 1459 } 1460 for (i = 0; i < m; i++) PetscCheck(idxm[i] < mat->rmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot insert in row %" PetscInt_FMT ", maximum is %" PetscInt_FMT, idxm[i], mat->rmap->N - 1); 1461 for (i = 0; i < n; i++) PetscCheck(idxn[i] < mat->cmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot insert in column %" PetscInt_FMT ", maximum is %" PetscInt_FMT, idxn[i], mat->cmap->N - 1); 1462 } 1463 1464 if (mat->assembled) { 1465 mat->was_assembled = PETSC_TRUE; 1466 mat->assembled = PETSC_FALSE; 1467 } 1468 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1469 PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv); 1470 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1471 PetscFunctionReturn(PETSC_SUCCESS); 1472 } 1473 1474 /*@C 1475 MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns 1476 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1477 MUST be called after all calls to `MatSetValues()` have been completed. 1478 1479 Not Collective 1480 1481 Input Parameters: 1482 + mat - the matrix 1483 . v - a logically two-dimensional array of values 1484 . ism - the rows to provide 1485 . isn - the columns to provide 1486 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1487 1488 Level: beginner 1489 1490 Notes: 1491 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1492 1493 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1494 options cannot be mixed without intervening calls to the assembly 1495 routines. 1496 1497 `MatSetValues()` uses 0-based row and column numbers in Fortran 1498 as well as in C. 1499 1500 Negative indices may be passed in `ism` and `isn`, these rows and columns are 1501 simply ignored. This allows easily inserting element stiffness matrices 1502 with homogeneous Dirchlet boundary conditions that you don't want represented 1503 in the matrix. 1504 1505 Efficiency Alert: 1506 The routine `MatSetValuesBlocked()` may offer much better efficiency 1507 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1508 1509 This is currently not optimized for any particular `ISType` 1510 1511 Developer Notes: 1512 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1513 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1514 1515 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1516 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()` 1517 @*/ 1518 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv) 1519 { 1520 PetscInt m, n; 1521 const PetscInt *rows, *cols; 1522 1523 PetscFunctionBeginHot; 1524 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1525 PetscCall(ISGetIndices(ism, &rows)); 1526 PetscCall(ISGetIndices(isn, &cols)); 1527 PetscCall(ISGetLocalSize(ism, &m)); 1528 PetscCall(ISGetLocalSize(isn, &n)); 1529 PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv)); 1530 PetscCall(ISRestoreIndices(ism, &rows)); 1531 PetscCall(ISRestoreIndices(isn, &cols)); 1532 PetscFunctionReturn(PETSC_SUCCESS); 1533 } 1534 1535 /*@ 1536 MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1537 values into a matrix 1538 1539 Not Collective 1540 1541 Input Parameters: 1542 + mat - the matrix 1543 . row - the (block) row to set 1544 - v - a logically two-dimensional array of values 1545 1546 Level: intermediate 1547 1548 Notes: 1549 The values, `v`, are column-oriented (for the block version) and sorted 1550 1551 All the nonzeros in the row must be provided 1552 1553 The matrix must have previously had its column indices set, likely by having been assembled. 1554 1555 The row must belong to this process 1556 1557 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1558 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()` 1559 @*/ 1560 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[]) 1561 { 1562 PetscInt globalrow; 1563 1564 PetscFunctionBegin; 1565 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1566 PetscValidType(mat, 1); 1567 PetscValidScalarPointer(v, 3); 1568 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow)); 1569 PetscCall(MatSetValuesRow(mat, globalrow, v)); 1570 PetscFunctionReturn(PETSC_SUCCESS); 1571 } 1572 1573 /*@ 1574 MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1575 values into a matrix 1576 1577 Not Collective 1578 1579 Input Parameters: 1580 + mat - the matrix 1581 . row - the (block) row to set 1582 - v - a logically two-dimensional (column major) array of values for block matrices with blocksize larger than one, otherwise a one dimensional array of values 1583 1584 Level: advanced 1585 1586 Notes: 1587 The values, `v`, are column-oriented for the block version. 1588 1589 All the nonzeros in the row must be provided 1590 1591 THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used. 1592 1593 The row must belong to this process 1594 1595 .seealso: [](chapter_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1596 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()` 1597 @*/ 1598 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[]) 1599 { 1600 PetscFunctionBeginHot; 1601 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1602 PetscValidType(mat, 1); 1603 MatCheckPreallocated(mat, 1); 1604 PetscValidScalarPointer(v, 3); 1605 PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values"); 1606 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1607 mat->insertmode = INSERT_VALUES; 1608 1609 if (mat->assembled) { 1610 mat->was_assembled = PETSC_TRUE; 1611 mat->assembled = PETSC_FALSE; 1612 } 1613 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1614 PetscUseTypeMethod(mat, setvaluesrow, row, v); 1615 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1616 PetscFunctionReturn(PETSC_SUCCESS); 1617 } 1618 1619 /*@ 1620 MatSetValuesStencil - Inserts or adds a block of values into a matrix. 1621 Using structured grid indexing 1622 1623 Not Collective 1624 1625 Input Parameters: 1626 + mat - the matrix 1627 . m - number of rows being entered 1628 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered 1629 . n - number of columns being entered 1630 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered 1631 . v - a logically two-dimensional array of values 1632 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values 1633 1634 Level: beginner 1635 1636 Notes: 1637 By default the values, `v`, are row-oriented. See `MatSetOption()` for other options. 1638 1639 Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1640 options cannot be mixed without intervening calls to the assembly 1641 routines. 1642 1643 The grid coordinates are across the entire grid, not just the local portion 1644 1645 `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran 1646 as well as in C. 1647 1648 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1649 1650 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1651 or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1652 1653 The columns and rows in the stencil passed in MUST be contained within the 1654 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1655 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1656 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1657 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1658 1659 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 1660 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 1661 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 1662 `DM_BOUNDARY_PERIODIC` boundary type. 1663 1664 For indices that don't mean anything for your case (like the k index when working in 2d) or the c index when you have 1665 a single value per point) you can skip filling those indices. 1666 1667 Inspired by the structured grid interface to the HYPRE package 1668 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1669 1670 Efficiency Alert: 1671 The routine `MatSetValuesBlockedStencil()` may offer much better efficiency 1672 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1673 1674 Fortran Note: 1675 `idxm` and `idxn` should be declared as 1676 $ MatStencil idxm(4,m),idxn(4,n) 1677 and the values inserted using 1678 .vb 1679 idxm(MatStencil_i,1) = i 1680 idxm(MatStencil_j,1) = j 1681 idxm(MatStencil_k,1) = k 1682 idxm(MatStencil_c,1) = c 1683 etc 1684 .ve 1685 1686 .seealso: [](chapter_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1687 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil` 1688 @*/ 1689 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1690 { 1691 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1692 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1693 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1694 1695 PetscFunctionBegin; 1696 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1697 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1698 PetscValidType(mat, 1); 1699 PetscValidPointer(idxm, 3); 1700 PetscValidPointer(idxn, 5); 1701 1702 if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 1703 jdxm = buf; 1704 jdxn = buf + m; 1705 } else { 1706 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1707 jdxm = bufm; 1708 jdxn = bufn; 1709 } 1710 for (i = 0; i < m; i++) { 1711 for (j = 0; j < 3 - sdim; j++) dxm++; 1712 tmp = *dxm++ - starts[0]; 1713 for (j = 0; j < dim - 1; j++) { 1714 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1715 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1716 } 1717 if (mat->stencil.noc) dxm++; 1718 jdxm[i] = tmp; 1719 } 1720 for (i = 0; i < n; i++) { 1721 for (j = 0; j < 3 - sdim; j++) dxn++; 1722 tmp = *dxn++ - starts[0]; 1723 for (j = 0; j < dim - 1; j++) { 1724 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1725 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1726 } 1727 if (mat->stencil.noc) dxn++; 1728 jdxn[i] = tmp; 1729 } 1730 PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv)); 1731 PetscCall(PetscFree2(bufm, bufn)); 1732 PetscFunctionReturn(PETSC_SUCCESS); 1733 } 1734 1735 /*@ 1736 MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix. 1737 Using structured grid indexing 1738 1739 Not Collective 1740 1741 Input Parameters: 1742 + mat - the matrix 1743 . m - number of rows being entered 1744 . idxm - grid coordinates for matrix rows being entered 1745 . n - number of columns being entered 1746 . idxn - grid coordinates for matrix columns being entered 1747 . v - a logically two-dimensional array of values 1748 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values 1749 1750 Level: beginner 1751 1752 Notes: 1753 By default the values, `v`, are row-oriented and unsorted. 1754 See `MatSetOption()` for other options. 1755 1756 Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1757 options cannot be mixed without intervening calls to the assembly 1758 routines. 1759 1760 The grid coordinates are across the entire grid, not just the local portion 1761 1762 `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran 1763 as well as in C. 1764 1765 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1766 1767 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1768 or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1769 1770 The columns and rows in the stencil passed in MUST be contained within the 1771 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1772 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1773 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1774 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1775 1776 Negative indices may be passed in idxm and idxn, these rows and columns are 1777 simply ignored. This allows easily inserting element stiffness matrices 1778 with homogeneous Dirchlet boundary conditions that you don't want represented 1779 in the matrix. 1780 1781 Inspired by the structured grid interface to the HYPRE package 1782 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1783 1784 Fortran Note: 1785 `idxm` and `idxn` should be declared as 1786 $ MatStencil idxm(4,m),idxn(4,n) 1787 and the values inserted using 1788 .vb 1789 idxm(MatStencil_i,1) = i 1790 idxm(MatStencil_j,1) = j 1791 idxm(MatStencil_k,1) = k 1792 etc 1793 .ve 1794 1795 .seealso: [](chapter_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1796 `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`, 1797 `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` 1798 @*/ 1799 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1800 { 1801 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1802 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1803 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1804 1805 PetscFunctionBegin; 1806 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1807 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1808 PetscValidType(mat, 1); 1809 PetscValidPointer(idxm, 3); 1810 PetscValidPointer(idxn, 5); 1811 PetscValidScalarPointer(v, 6); 1812 1813 if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 1814 jdxm = buf; 1815 jdxn = buf + m; 1816 } else { 1817 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1818 jdxm = bufm; 1819 jdxn = bufn; 1820 } 1821 for (i = 0; i < m; i++) { 1822 for (j = 0; j < 3 - sdim; j++) dxm++; 1823 tmp = *dxm++ - starts[0]; 1824 for (j = 0; j < sdim - 1; j++) { 1825 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1826 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1827 } 1828 dxm++; 1829 jdxm[i] = tmp; 1830 } 1831 for (i = 0; i < n; i++) { 1832 for (j = 0; j < 3 - sdim; j++) dxn++; 1833 tmp = *dxn++ - starts[0]; 1834 for (j = 0; j < sdim - 1; j++) { 1835 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1836 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1837 } 1838 dxn++; 1839 jdxn[i] = tmp; 1840 } 1841 PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv)); 1842 PetscCall(PetscFree2(bufm, bufn)); 1843 PetscFunctionReturn(PETSC_SUCCESS); 1844 } 1845 1846 /*@ 1847 MatSetStencil - Sets the grid information for setting values into a matrix via 1848 `MatSetValuesStencil()` 1849 1850 Not Collective 1851 1852 Input Parameters: 1853 + mat - the matrix 1854 . dim - dimension of the grid 1, 2, or 3 1855 . dims - number of grid points in x, y, and z direction, including ghost points on your processor 1856 . starts - starting point of ghost nodes on your processor in x, y, and z direction 1857 - dof - number of degrees of freedom per node 1858 1859 Level: beginner 1860 1861 Notes: 1862 Inspired by the structured grid interface to the HYPRE package 1863 (www.llnl.gov/CASC/hyper) 1864 1865 For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the 1866 user. 1867 1868 .seealso: [](chapter_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1869 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()` 1870 @*/ 1871 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof) 1872 { 1873 PetscFunctionBegin; 1874 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1875 PetscValidIntPointer(dims, 3); 1876 PetscValidIntPointer(starts, 4); 1877 1878 mat->stencil.dim = dim + (dof > 1); 1879 for (PetscInt i = 0; i < dim; i++) { 1880 mat->stencil.dims[i] = dims[dim - i - 1]; /* copy the values in backwards */ 1881 mat->stencil.starts[i] = starts[dim - i - 1]; 1882 } 1883 mat->stencil.dims[dim] = dof; 1884 mat->stencil.starts[dim] = 0; 1885 mat->stencil.noc = (PetscBool)(dof == 1); 1886 PetscFunctionReturn(PETSC_SUCCESS); 1887 } 1888 1889 /*@C 1890 MatSetValuesBlocked - Inserts or adds a block of values into a matrix. 1891 1892 Not Collective 1893 1894 Input Parameters: 1895 + mat - the matrix 1896 . v - a logically two-dimensional array of values 1897 . m - the number of block rows 1898 . idxm - the global block indices 1899 . n - the number of block columns 1900 . idxn - the global block indices 1901 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values 1902 1903 Level: intermediate 1904 1905 Notes: 1906 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call 1907 MatXXXXSetPreallocation() or `MatSetUp()` before using this routine. 1908 1909 The `m` and `n` count the NUMBER of blocks in the row direction and column direction, 1910 NOT the total number of rows/columns; for example, if the block size is 2 and 1911 you are passing in values for rows 2,3,4,5 then m would be 2 (not 4). 1912 The values in idxm would be 1 2; that is the first index for each block divided by 1913 the block size. 1914 1915 You must call `MatSetBlockSize()` when constructing this matrix (before 1916 preallocating it). 1917 1918 By default the values, `v`, are row-oriented, so the layout of 1919 `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options. 1920 1921 Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES` 1922 options cannot be mixed without intervening calls to the assembly 1923 routines. 1924 1925 `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran 1926 as well as in C. 1927 1928 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1929 simply ignored. This allows easily inserting element stiffness matrices 1930 with homogeneous Dirchlet boundary conditions that you don't want represented 1931 in the matrix. 1932 1933 Each time an entry is set within a sparse matrix via `MatSetValues()`, 1934 internal searching must be done to determine where to place the 1935 data in the matrix storage space. By instead inserting blocks of 1936 entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is 1937 reduced. 1938 1939 Example: 1940 .vb 1941 Suppose m=n=2 and block size(bs) = 2 The array is 1942 1943 1 2 | 3 4 1944 5 6 | 7 8 1945 - - - | - - - 1946 9 10 | 11 12 1947 13 14 | 15 16 1948 1949 v[] should be passed in like 1950 v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] 1951 1952 If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then 1953 v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16] 1954 .ve 1955 1956 .seealso: [](chapter_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()` 1957 @*/ 1958 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1959 { 1960 PetscFunctionBeginHot; 1961 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1962 PetscValidType(mat, 1); 1963 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1964 PetscValidIntPointer(idxm, 3); 1965 PetscValidIntPointer(idxn, 5); 1966 MatCheckPreallocated(mat, 1); 1967 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1968 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1969 if (PetscDefined(USE_DEBUG)) { 1970 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1971 PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 1972 } 1973 if (PetscDefined(USE_DEBUG)) { 1974 PetscInt rbs, cbs, M, N, i; 1975 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1976 PetscCall(MatGetSize(mat, &M, &N)); 1977 for (i = 0; i < m; i++) PetscCheck(idxm[i] * rbs < M, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row block index %" PetscInt_FMT " (index %" PetscInt_FMT ") greater than row length %" PetscInt_FMT, i, idxm[i], M); 1978 for (i = 0; i < n; i++) PetscCheck(idxn[i] * cbs < N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column block index %" PetscInt_FMT " (index %" PetscInt_FMT ") great than column length %" PetscInt_FMT, i, idxn[i], N); 1979 } 1980 if (mat->assembled) { 1981 mat->was_assembled = PETSC_TRUE; 1982 mat->assembled = PETSC_FALSE; 1983 } 1984 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1985 if (mat->ops->setvaluesblocked) { 1986 PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv); 1987 } else { 1988 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn; 1989 PetscInt i, j, bs, cbs; 1990 1991 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 1992 if (m * bs + n * cbs <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 1993 iidxm = buf; 1994 iidxn = buf + m * bs; 1995 } else { 1996 PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc)); 1997 iidxm = bufr; 1998 iidxn = bufc; 1999 } 2000 for (i = 0; i < m; i++) { 2001 for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j; 2002 } 2003 if (m != n || bs != cbs || idxm != idxn) { 2004 for (i = 0; i < n; i++) { 2005 for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j; 2006 } 2007 } else iidxn = iidxm; 2008 PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv)); 2009 PetscCall(PetscFree2(bufr, bufc)); 2010 } 2011 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2012 PetscFunctionReturn(PETSC_SUCCESS); 2013 } 2014 2015 /*@C 2016 MatGetValues - Gets a block of local values from a matrix. 2017 2018 Not Collective; can only return values that are owned by the give process 2019 2020 Input Parameters: 2021 + mat - the matrix 2022 . v - a logically two-dimensional array for storing the values 2023 . m - the number of rows 2024 . idxm - the global indices of the rows 2025 . n - the number of columns 2026 - idxn - the global indices of the columns 2027 2028 Level: advanced 2029 2030 Notes: 2031 The user must allocate space (m*n `PetscScalar`s) for the values, `v`. 2032 The values, `v`, are then returned in a row-oriented format, 2033 analogous to that used by default in `MatSetValues()`. 2034 2035 `MatGetValues()` uses 0-based row and column numbers in 2036 Fortran as well as in C. 2037 2038 `MatGetValues()` requires that the matrix has been assembled 2039 with `MatAssemblyBegin()`/`MatAssemblyEnd()`. Thus, calls to 2040 `MatSetValues()` and `MatGetValues()` CANNOT be made in succession 2041 without intermediate matrix assembly. 2042 2043 Negative row or column indices will be ignored and those locations in `v` will be 2044 left unchanged. 2045 2046 For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI rank. 2047 That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable 2048 from `MatGetOwnershipRange`(mat,&rstart,&rend). 2049 2050 .seealso: [](chapter_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()` 2051 @*/ 2052 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) 2053 { 2054 PetscFunctionBegin; 2055 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2056 PetscValidType(mat, 1); 2057 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); 2058 PetscValidIntPointer(idxm, 3); 2059 PetscValidIntPointer(idxn, 5); 2060 PetscValidScalarPointer(v, 6); 2061 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2062 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2063 MatCheckPreallocated(mat, 1); 2064 2065 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2066 PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v); 2067 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2068 PetscFunctionReturn(PETSC_SUCCESS); 2069 } 2070 2071 /*@C 2072 MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices 2073 defined previously by `MatSetLocalToGlobalMapping()` 2074 2075 Not Collective 2076 2077 Input Parameters: 2078 + mat - the matrix 2079 . nrow - number of rows 2080 . irow - the row local indices 2081 . ncol - number of columns 2082 - icol - the column local indices 2083 2084 Output Parameter: 2085 . y - a logically two-dimensional array of values 2086 2087 Level: advanced 2088 2089 Notes: 2090 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine. 2091 2092 This routine can only return values that are owned by the requesting MPI rank. That is, for standard matrix formats, rows that, in the global numbering, 2093 are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can 2094 determine if the resulting global row associated with the local row r is owned by the requesting MPI rank by applying the `ISLocalToGlobalMapping` set 2095 with `MatSetLocalToGlobalMapping()`. 2096 2097 Developer Note: 2098 This is labelled with C so does not automatically generate Fortran stubs and interfaces 2099 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2100 2101 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2102 `MatSetValuesLocal()`, `MatGetValues()` 2103 @*/ 2104 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[]) 2105 { 2106 PetscFunctionBeginHot; 2107 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2108 PetscValidType(mat, 1); 2109 MatCheckPreallocated(mat, 1); 2110 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */ 2111 PetscValidIntPointer(irow, 3); 2112 PetscValidIntPointer(icol, 5); 2113 if (PetscDefined(USE_DEBUG)) { 2114 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2115 PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2116 } 2117 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2118 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2119 if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y); 2120 else { 2121 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm; 2122 if ((nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2123 irowm = buf; 2124 icolm = buf + nrow; 2125 } else { 2126 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2127 irowm = bufr; 2128 icolm = bufc; 2129 } 2130 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping())."); 2131 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping())."); 2132 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm)); 2133 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm)); 2134 PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y)); 2135 PetscCall(PetscFree2(bufr, bufc)); 2136 } 2137 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2138 PetscFunctionReturn(PETSC_SUCCESS); 2139 } 2140 2141 /*@ 2142 MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and 2143 the same size. Currently, this can only be called once and creates the given matrix. 2144 2145 Not Collective 2146 2147 Input Parameters: 2148 + mat - the matrix 2149 . nb - the number of blocks 2150 . bs - the number of rows (and columns) in each block 2151 . rows - a concatenation of the rows for each block 2152 - v - a concatenation of logically two-dimensional arrays of values 2153 2154 Level: advanced 2155 2156 Note: 2157 `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values 2158 2159 In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix. 2160 2161 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 2162 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()` 2163 @*/ 2164 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[]) 2165 { 2166 PetscFunctionBegin; 2167 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2168 PetscValidType(mat, 1); 2169 PetscValidIntPointer(rows, 4); 2170 PetscValidScalarPointer(v, 5); 2171 PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2172 2173 PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0)); 2174 if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v); 2175 else { 2176 for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES)); 2177 } 2178 PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0)); 2179 PetscFunctionReturn(PETSC_SUCCESS); 2180 } 2181 2182 /*@ 2183 MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by 2184 the routine `MatSetValuesLocal()` to allow users to insert matrix entries 2185 using a local (per-processor) numbering. 2186 2187 Not Collective 2188 2189 Input Parameters: 2190 + x - the matrix 2191 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()` 2192 - cmapping - column mapping 2193 2194 Level: intermediate 2195 2196 Note: 2197 If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix 2198 2199 .seealso: [](chapter_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()` 2200 @*/ 2201 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping) 2202 { 2203 PetscFunctionBegin; 2204 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 2205 PetscValidType(x, 1); 2206 if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2); 2207 if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3); 2208 if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping); 2209 else { 2210 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping)); 2211 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping)); 2212 } 2213 PetscFunctionReturn(PETSC_SUCCESS); 2214 } 2215 2216 /*@ 2217 MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()` 2218 2219 Not Collective 2220 2221 Input Parameter: 2222 . A - the matrix 2223 2224 Output Parameters: 2225 + rmapping - row mapping 2226 - cmapping - column mapping 2227 2228 Level: advanced 2229 2230 .seealso: [](chapter_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()` 2231 @*/ 2232 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping) 2233 { 2234 PetscFunctionBegin; 2235 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2236 PetscValidType(A, 1); 2237 if (rmapping) { 2238 PetscValidPointer(rmapping, 2); 2239 *rmapping = A->rmap->mapping; 2240 } 2241 if (cmapping) { 2242 PetscValidPointer(cmapping, 3); 2243 *cmapping = A->cmap->mapping; 2244 } 2245 PetscFunctionReturn(PETSC_SUCCESS); 2246 } 2247 2248 /*@ 2249 MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix 2250 2251 Logically Collective 2252 2253 Input Parameters: 2254 + A - the matrix 2255 . rmap - row layout 2256 - cmap - column layout 2257 2258 Level: advanced 2259 2260 Note: 2261 The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called. 2262 2263 .seealso: [](chapter_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()` 2264 @*/ 2265 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap) 2266 { 2267 PetscFunctionBegin; 2268 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2269 PetscCall(PetscLayoutReference(rmap, &A->rmap)); 2270 PetscCall(PetscLayoutReference(cmap, &A->cmap)); 2271 PetscFunctionReturn(PETSC_SUCCESS); 2272 } 2273 2274 /*@ 2275 MatGetLayouts - Gets the `PetscLayout` objects for rows and columns 2276 2277 Not Collective 2278 2279 Input Parameter: 2280 . A - the matrix 2281 2282 Output Parameters: 2283 + rmap - row layout 2284 - cmap - column layout 2285 2286 Level: advanced 2287 2288 .seealso: [](chapter_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()` 2289 @*/ 2290 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap) 2291 { 2292 PetscFunctionBegin; 2293 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2294 PetscValidType(A, 1); 2295 if (rmap) { 2296 PetscValidPointer(rmap, 2); 2297 *rmap = A->rmap; 2298 } 2299 if (cmap) { 2300 PetscValidPointer(cmap, 3); 2301 *cmap = A->cmap; 2302 } 2303 PetscFunctionReturn(PETSC_SUCCESS); 2304 } 2305 2306 /*@C 2307 MatSetValuesLocal - Inserts or adds values into certain locations of a matrix, 2308 using a local numbering of the nodes. 2309 2310 Not Collective 2311 2312 Input Parameters: 2313 + mat - the matrix 2314 . nrow - number of rows 2315 . irow - the row local indices 2316 . ncol - number of columns 2317 . icol - the column local indices 2318 . y - a logically two-dimensional array of values 2319 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2320 2321 Level: intermediate 2322 2323 Notes: 2324 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 2325 `MatSetUp()` before using this routine 2326 2327 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine 2328 2329 Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2330 options cannot be mixed without intervening calls to the assembly 2331 routines. 2332 2333 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2334 MUST be called after all calls to `MatSetValuesLocal()` have been completed. 2335 2336 Developer Note: 2337 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2338 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2339 2340 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2341 `MatGetValuesLocal()` 2342 @*/ 2343 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2344 { 2345 PetscFunctionBeginHot; 2346 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2347 PetscValidType(mat, 1); 2348 MatCheckPreallocated(mat, 1); 2349 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2350 PetscValidIntPointer(irow, 3); 2351 PetscValidIntPointer(icol, 5); 2352 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2353 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2354 if (PetscDefined(USE_DEBUG)) { 2355 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2356 PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2357 } 2358 2359 if (mat->assembled) { 2360 mat->was_assembled = PETSC_TRUE; 2361 mat->assembled = PETSC_FALSE; 2362 } 2363 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2364 if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv); 2365 else { 2366 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2367 const PetscInt *irowm, *icolm; 2368 2369 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2370 bufr = buf; 2371 bufc = buf + nrow; 2372 irowm = bufr; 2373 icolm = bufc; 2374 } else { 2375 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2376 irowm = bufr; 2377 icolm = bufc; 2378 } 2379 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr)); 2380 else irowm = irow; 2381 if (mat->cmap->mapping) { 2382 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2383 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc)); 2384 } else icolm = irowm; 2385 } else icolm = icol; 2386 PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv)); 2387 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2388 } 2389 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2390 PetscFunctionReturn(PETSC_SUCCESS); 2391 } 2392 2393 /*@C 2394 MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix, 2395 using a local ordering of the nodes a block at a time. 2396 2397 Not Collective 2398 2399 Input Parameters: 2400 + x - the matrix 2401 . nrow - number of rows 2402 . irow - the row local indices 2403 . ncol - number of columns 2404 . icol - the column local indices 2405 . y - a logically two-dimensional array of values 2406 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2407 2408 Level: intermediate 2409 2410 Notes: 2411 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 2412 `MatSetUp()` before using this routine 2413 2414 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()` 2415 before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the 2416 2417 Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2418 options cannot be mixed without intervening calls to the assembly 2419 routines. 2420 2421 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2422 MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed. 2423 2424 Developer Note: 2425 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2426 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2427 2428 .seealso: [](chapter_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, 2429 `MatSetValuesLocal()`, `MatSetValuesBlocked()` 2430 @*/ 2431 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2432 { 2433 PetscFunctionBeginHot; 2434 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2435 PetscValidType(mat, 1); 2436 MatCheckPreallocated(mat, 1); 2437 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2438 PetscValidIntPointer(irow, 3); 2439 PetscValidIntPointer(icol, 5); 2440 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2441 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2442 if (PetscDefined(USE_DEBUG)) { 2443 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2444 PetscCheck(mat->ops->setvaluesblockedlocal || mat->ops->setvaluesblocked || mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2445 } 2446 2447 if (mat->assembled) { 2448 mat->was_assembled = PETSC_TRUE; 2449 mat->assembled = PETSC_FALSE; 2450 } 2451 if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */ 2452 PetscInt irbs, rbs; 2453 PetscCall(MatGetBlockSizes(mat, &rbs, NULL)); 2454 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs)); 2455 PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs); 2456 } 2457 if (PetscUnlikelyDebug(mat->cmap->mapping)) { 2458 PetscInt icbs, cbs; 2459 PetscCall(MatGetBlockSizes(mat, NULL, &cbs)); 2460 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs)); 2461 PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs); 2462 } 2463 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2464 if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv); 2465 else { 2466 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2467 const PetscInt *irowm, *icolm; 2468 2469 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2470 bufr = buf; 2471 bufc = buf + nrow; 2472 irowm = bufr; 2473 icolm = bufc; 2474 } else { 2475 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2476 irowm = bufr; 2477 icolm = bufc; 2478 } 2479 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr)); 2480 else irowm = irow; 2481 if (mat->cmap->mapping) { 2482 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2483 PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc)); 2484 } else icolm = irowm; 2485 } else icolm = icol; 2486 PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv)); 2487 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2488 } 2489 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2490 PetscFunctionReturn(PETSC_SUCCESS); 2491 } 2492 2493 /*@ 2494 MatMultDiagonalBlock - Computes the matrix-vector product, y = Dx. Where D is defined by the inode or block structure of the diagonal 2495 2496 Collective 2497 2498 Input Parameters: 2499 + mat - the matrix 2500 - x - the vector to be multiplied 2501 2502 Output Parameter: 2503 . y - the result 2504 2505 Level: developer 2506 2507 Note: 2508 The vectors `x` and `y` cannot be the same. I.e., one cannot 2509 call `MatMultDiagonalBlock`(A,y,y). 2510 2511 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2512 @*/ 2513 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y) 2514 { 2515 PetscFunctionBegin; 2516 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2517 PetscValidType(mat, 1); 2518 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2519 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2520 2521 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2522 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2523 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2524 MatCheckPreallocated(mat, 1); 2525 2526 PetscUseTypeMethod(mat, multdiagonalblock, x, y); 2527 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2528 PetscFunctionReturn(PETSC_SUCCESS); 2529 } 2530 2531 /*@ 2532 MatMult - Computes the matrix-vector product, y = Ax. 2533 2534 Neighbor-wise Collective 2535 2536 Input Parameters: 2537 + mat - the matrix 2538 - x - the vector to be multiplied 2539 2540 Output Parameter: 2541 . y - the result 2542 2543 Level: beginner 2544 2545 Note: 2546 The vectors `x` and `y` cannot be the same. I.e., one cannot 2547 call `MatMult`(A,y,y). 2548 2549 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2550 @*/ 2551 PetscErrorCode MatMult(Mat mat, Vec x, Vec y) 2552 { 2553 PetscFunctionBegin; 2554 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2555 PetscValidType(mat, 1); 2556 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2557 VecCheckAssembled(x); 2558 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2559 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2560 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2561 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2562 PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N); 2563 PetscCheck(mat->rmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, y->map->N); 2564 PetscCheck(mat->cmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, x->map->n); 2565 PetscCheck(mat->rmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, y->map->n); 2566 PetscCall(VecSetErrorIfLocked(y, 3)); 2567 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2568 MatCheckPreallocated(mat, 1); 2569 2570 PetscCall(VecLockReadPush(x)); 2571 PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0)); 2572 PetscUseTypeMethod(mat, mult, x, y); 2573 PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0)); 2574 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2575 PetscCall(VecLockReadPop(x)); 2576 PetscFunctionReturn(PETSC_SUCCESS); 2577 } 2578 2579 /*@ 2580 MatMultTranspose - Computes matrix transpose times a vector y = A^T * x. 2581 2582 Neighbor-wise Collective 2583 2584 Input Parameters: 2585 + mat - the matrix 2586 - x - the vector to be multiplied 2587 2588 Output Parameter: 2589 . y - the result 2590 2591 Level: beginner 2592 2593 Notes: 2594 The vectors `x` and `y` cannot be the same. I.e., one cannot 2595 call `MatMultTranspose`(A,y,y). 2596 2597 For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple, 2598 use `MatMultHermitianTranspose()` 2599 2600 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()` 2601 @*/ 2602 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y) 2603 { 2604 PetscErrorCode (*op)(Mat, Vec, Vec) = NULL; 2605 2606 PetscFunctionBegin; 2607 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2608 PetscValidType(mat, 1); 2609 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2610 VecCheckAssembled(x); 2611 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2612 2613 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2614 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2615 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2616 PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N); 2617 PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N); 2618 PetscCheck(mat->cmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, y->map->n); 2619 PetscCheck(mat->rmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, x->map->n); 2620 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2621 MatCheckPreallocated(mat, 1); 2622 2623 if (!mat->ops->multtranspose) { 2624 if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult; 2625 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s does not have a multiply transpose defined or is symmetric and does not have a multiply defined", ((PetscObject)mat)->type_name); 2626 } else op = mat->ops->multtranspose; 2627 PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0)); 2628 PetscCall(VecLockReadPush(x)); 2629 PetscCall((*op)(mat, x, y)); 2630 PetscCall(VecLockReadPop(x)); 2631 PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0)); 2632 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2633 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2634 PetscFunctionReturn(PETSC_SUCCESS); 2635 } 2636 2637 /*@ 2638 MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector. 2639 2640 Neighbor-wise Collective 2641 2642 Input Parameters: 2643 + mat - the matrix 2644 - x - the vector to be multilplied 2645 2646 Output Parameter: 2647 . y - the result 2648 2649 Level: beginner 2650 2651 Notes: 2652 The vectors `x` and `y` cannot be the same. I.e., one cannot 2653 call `MatMultHermitianTranspose`(A,y,y). 2654 2655 Also called the conjugate transpose, complex conjugate transpose, or adjoint. 2656 2657 For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical. 2658 2659 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()` 2660 @*/ 2661 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y) 2662 { 2663 PetscFunctionBegin; 2664 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2665 PetscValidType(mat, 1); 2666 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2667 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2668 2669 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2670 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2671 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2672 PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N); 2673 PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N); 2674 PetscCheck(mat->cmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, y->map->n); 2675 PetscCheck(mat->rmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, x->map->n); 2676 MatCheckPreallocated(mat, 1); 2677 2678 PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0)); 2679 #if defined(PETSC_USE_COMPLEX) 2680 if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) { 2681 PetscCall(VecLockReadPush(x)); 2682 if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y); 2683 else PetscUseTypeMethod(mat, mult, x, y); 2684 PetscCall(VecLockReadPop(x)); 2685 } else { 2686 Vec w; 2687 PetscCall(VecDuplicate(x, &w)); 2688 PetscCall(VecCopy(x, w)); 2689 PetscCall(VecConjugate(w)); 2690 PetscCall(MatMultTranspose(mat, w, y)); 2691 PetscCall(VecDestroy(&w)); 2692 PetscCall(VecConjugate(y)); 2693 } 2694 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2695 #else 2696 PetscCall(MatMultTranspose(mat, x, y)); 2697 #endif 2698 PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0)); 2699 PetscFunctionReturn(PETSC_SUCCESS); 2700 } 2701 2702 /*@ 2703 MatMultAdd - Computes v3 = v2 + A * v1. 2704 2705 Neighbor-wise Collective 2706 2707 Input Parameters: 2708 + mat - the matrix 2709 . v1 - the vector to be multiplied by `mat` 2710 - v2 - the vector to be added to the result 2711 2712 Output Parameter: 2713 . v3 - the result 2714 2715 Level: beginner 2716 2717 Note: 2718 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2719 call `MatMultAdd`(A,v1,v2,v1). 2720 2721 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()` 2722 @*/ 2723 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2724 { 2725 PetscFunctionBegin; 2726 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2727 PetscValidType(mat, 1); 2728 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2729 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2730 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2731 2732 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2733 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2734 PetscCheck(mat->cmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v1->map->N); 2735 /* PetscCheck(mat->rmap->N == v2->map->N,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v2->map->N); 2736 PetscCheck(mat->rmap->N == v3->map->N,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v3->map->N); */ 2737 PetscCheck(mat->rmap->n == v3->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, v3->map->n); 2738 PetscCheck(mat->rmap->n == v2->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, v2->map->n); 2739 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2740 MatCheckPreallocated(mat, 1); 2741 2742 PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3)); 2743 PetscCall(VecLockReadPush(v1)); 2744 PetscUseTypeMethod(mat, multadd, v1, v2, v3); 2745 PetscCall(VecLockReadPop(v1)); 2746 PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3)); 2747 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2748 PetscFunctionReturn(PETSC_SUCCESS); 2749 } 2750 2751 /*@ 2752 MatMultTransposeAdd - Computes v3 = v2 + A' * v1. 2753 2754 Neighbor-wise Collective 2755 2756 Input Parameters: 2757 + mat - the matrix 2758 . v1 - the vector to be multiplied by the transpose of the matrix 2759 - v2 - the vector to be added to the result 2760 2761 Output Parameter: 2762 . v3 - the result 2763 2764 Level: beginner 2765 2766 Note: 2767 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2768 call `MatMultTransposeAdd`(A,v1,v2,v1). 2769 2770 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2771 @*/ 2772 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2773 { 2774 PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd; 2775 2776 PetscFunctionBegin; 2777 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2778 PetscValidType(mat, 1); 2779 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2780 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2781 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2782 2783 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2784 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2785 PetscCheck(mat->rmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, v1->map->N); 2786 PetscCheck(mat->cmap->N == v2->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v2->map->N); 2787 PetscCheck(mat->cmap->N == v3->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v3->map->N); 2788 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2789 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2790 MatCheckPreallocated(mat, 1); 2791 2792 PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2793 PetscCall(VecLockReadPush(v1)); 2794 PetscCall((*op)(mat, v1, v2, v3)); 2795 PetscCall(VecLockReadPop(v1)); 2796 PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2797 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2798 PetscFunctionReturn(PETSC_SUCCESS); 2799 } 2800 2801 /*@ 2802 MatMultHermitianTransposeAdd - Computes v3 = v2 + A^H * v1. 2803 2804 Neighbor-wise Collective 2805 2806 Input Parameters: 2807 + mat - the matrix 2808 . v1 - the vector to be multiplied by the Hermitian transpose 2809 - v2 - the vector to be added to the result 2810 2811 Output Parameter: 2812 . v3 - the result 2813 2814 Level: beginner 2815 2816 Note: 2817 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2818 call `MatMultHermitianTransposeAdd`(A,v1,v2,v1). 2819 2820 .seealso: [](chapter_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2821 @*/ 2822 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2823 { 2824 PetscFunctionBegin; 2825 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2826 PetscValidType(mat, 1); 2827 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2828 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2829 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2830 2831 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2832 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2833 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2834 PetscCheck(mat->rmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, v1->map->N); 2835 PetscCheck(mat->cmap->N == v2->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v2->map->N); 2836 PetscCheck(mat->cmap->N == v3->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v3->map->N); 2837 MatCheckPreallocated(mat, 1); 2838 2839 PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2840 PetscCall(VecLockReadPush(v1)); 2841 if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3); 2842 else { 2843 Vec w, z; 2844 PetscCall(VecDuplicate(v1, &w)); 2845 PetscCall(VecCopy(v1, w)); 2846 PetscCall(VecConjugate(w)); 2847 PetscCall(VecDuplicate(v3, &z)); 2848 PetscCall(MatMultTranspose(mat, w, z)); 2849 PetscCall(VecDestroy(&w)); 2850 PetscCall(VecConjugate(z)); 2851 if (v2 != v3) { 2852 PetscCall(VecWAXPY(v3, 1.0, v2, z)); 2853 } else { 2854 PetscCall(VecAXPY(v3, 1.0, z)); 2855 } 2856 PetscCall(VecDestroy(&z)); 2857 } 2858 PetscCall(VecLockReadPop(v1)); 2859 PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2860 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2861 PetscFunctionReturn(PETSC_SUCCESS); 2862 } 2863 2864 /*@C 2865 MatGetFactorType - gets the type of factorization it is 2866 2867 Not Collective 2868 2869 Input Parameter: 2870 . mat - the matrix 2871 2872 Output Parameter: 2873 . t - the type, one of `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2874 2875 Level: intermediate 2876 2877 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2878 `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2879 @*/ 2880 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t) 2881 { 2882 PetscFunctionBegin; 2883 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2884 PetscValidType(mat, 1); 2885 PetscValidPointer(t, 2); 2886 *t = mat->factortype; 2887 PetscFunctionReturn(PETSC_SUCCESS); 2888 } 2889 2890 /*@C 2891 MatSetFactorType - sets the type of factorization it is 2892 2893 Logically Collective 2894 2895 Input Parameters: 2896 + mat - the matrix 2897 - t - the type, one of `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2898 2899 Level: intermediate 2900 2901 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2902 `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2903 @*/ 2904 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t) 2905 { 2906 PetscFunctionBegin; 2907 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2908 PetscValidType(mat, 1); 2909 mat->factortype = t; 2910 PetscFunctionReturn(PETSC_SUCCESS); 2911 } 2912 2913 /*@C 2914 MatGetInfo - Returns information about matrix storage (number of 2915 nonzeros, memory, etc.). 2916 2917 Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag 2918 2919 Input Parameters: 2920 + mat - the matrix 2921 - flag - flag indicating the type of parameters to be returned (`MAT_LOCAL` - local matrix, `MAT_GLOBAL_MAX` - maximum over all processors, `MAT_GLOBAL_SUM` - sum over all processors) 2922 2923 Output Parameter: 2924 . info - matrix information context 2925 2926 Notes: 2927 The `MatInfo` context contains a variety of matrix data, including 2928 number of nonzeros allocated and used, number of mallocs during 2929 matrix assembly, etc. Additional information for factored matrices 2930 is provided (such as the fill ratio, number of mallocs during 2931 factorization, etc.). Much of this info is printed to `PETSC_STDOUT` 2932 when using the runtime options 2933 $ -info -mat_view ::ascii_info 2934 2935 Example: 2936 See the file ${PETSC_DIR}/include/petscmat.h for a complete list of 2937 data within the MatInfo context. For example, 2938 .vb 2939 MatInfo info; 2940 Mat A; 2941 double mal, nz_a, nz_u; 2942 2943 MatGetInfo(A,MAT_LOCAL,&info); 2944 mal = info.mallocs; 2945 nz_a = info.nz_allocated; 2946 .ve 2947 2948 Fortran users should declare info as a double precision 2949 array of dimension `MAT_INFO_SIZE`, and then extract the parameters 2950 of interest. See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h 2951 a complete list of parameter names. 2952 .vb 2953 double precision info(MAT_INFO_SIZE) 2954 double precision mal, nz_a 2955 Mat A 2956 integer ierr 2957 2958 call MatGetInfo(A,MAT_LOCAL,info,ierr) 2959 mal = info(MAT_INFO_MALLOCS) 2960 nz_a = info(MAT_INFO_NZ_ALLOCATED) 2961 .ve 2962 2963 Level: intermediate 2964 2965 Developer Note: 2966 The Fortran interface is not autogenerated as the 2967 interface definition cannot be generated correctly [due to `MatInfo` argument] 2968 2969 .seealso: [](chapter_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()` 2970 @*/ 2971 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info) 2972 { 2973 PetscFunctionBegin; 2974 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2975 PetscValidType(mat, 1); 2976 PetscValidPointer(info, 3); 2977 MatCheckPreallocated(mat, 1); 2978 PetscUseTypeMethod(mat, getinfo, flag, info); 2979 PetscFunctionReturn(PETSC_SUCCESS); 2980 } 2981 2982 /* 2983 This is used by external packages where it is not easy to get the info from the actual 2984 matrix factorization. 2985 */ 2986 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info) 2987 { 2988 PetscFunctionBegin; 2989 PetscCall(PetscMemzero(info, sizeof(MatInfo))); 2990 PetscFunctionReturn(PETSC_SUCCESS); 2991 } 2992 2993 /*@C 2994 MatLUFactor - Performs in-place LU factorization of matrix. 2995 2996 Collective 2997 2998 Input Parameters: 2999 + mat - the matrix 3000 . row - row permutation 3001 . col - column permutation 3002 - info - options for factorization, includes 3003 .vb 3004 fill - expected fill as ratio of original fill. 3005 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3006 Run with the option -info to determine an optimal value to use 3007 .ve 3008 Level: developer 3009 3010 Notes: 3011 Most users should employ the `KSP` interface for linear solvers 3012 instead of working directly with matrix algebra routines such as this. 3013 See, e.g., `KSPCreate()`. 3014 3015 This changes the state of the matrix to a factored matrix; it cannot be used 3016 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3017 3018 This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()` 3019 when not using `KSP`. 3020 3021 Developer Note: 3022 The Fortran interface is not autogenerated as the 3023 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3024 3025 .seealso: [](chapter_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, 3026 `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3027 @*/ 3028 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3029 { 3030 MatFactorInfo tinfo; 3031 3032 PetscFunctionBegin; 3033 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3034 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3035 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3036 if (info) PetscValidPointer(info, 4); 3037 PetscValidType(mat, 1); 3038 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3039 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3040 MatCheckPreallocated(mat, 1); 3041 if (!info) { 3042 PetscCall(MatFactorInfoInitialize(&tinfo)); 3043 info = &tinfo; 3044 } 3045 3046 PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0)); 3047 PetscUseTypeMethod(mat, lufactor, row, col, info); 3048 PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0)); 3049 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3050 PetscFunctionReturn(PETSC_SUCCESS); 3051 } 3052 3053 /*@C 3054 MatILUFactor - Performs in-place ILU factorization of matrix. 3055 3056 Collective 3057 3058 Input Parameters: 3059 + mat - the matrix 3060 . row - row permutation 3061 . col - column permutation 3062 - info - structure containing 3063 .vb 3064 levels - number of levels of fill. 3065 expected fill - as ratio of original fill. 3066 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 3067 missing diagonal entries) 3068 .ve 3069 3070 Level: developer 3071 3072 Notes: 3073 Most users should employ the `KSP` interface for linear solvers 3074 instead of working directly with matrix algebra routines such as this. 3075 See, e.g., `KSPCreate()`. 3076 3077 Probably really in-place only when level of fill is zero, otherwise allocates 3078 new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()` 3079 when not using `KSP`. 3080 3081 Developer Note: 3082 The Fortran interface is not autogenerated as the 3083 interface definition cannot be generated correctly [due to MatFactorInfo] 3084 3085 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 3086 @*/ 3087 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3088 { 3089 PetscFunctionBegin; 3090 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3091 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3092 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3093 PetscValidPointer(info, 4); 3094 PetscValidType(mat, 1); 3095 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 3096 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3097 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3098 MatCheckPreallocated(mat, 1); 3099 3100 PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0)); 3101 PetscUseTypeMethod(mat, ilufactor, row, col, info); 3102 PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0)); 3103 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3104 PetscFunctionReturn(PETSC_SUCCESS); 3105 } 3106 3107 /*@C 3108 MatLUFactorSymbolic - Performs symbolic LU factorization of matrix. 3109 Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`. 3110 3111 Collective 3112 3113 Input Parameters: 3114 + fact - the factor matrix obtained with `MatGetFactor()` 3115 . mat - the matrix 3116 . row - the row permutation 3117 . col - the column permutation 3118 - info - options for factorization, includes 3119 .vb 3120 fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use 3121 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3122 .ve 3123 3124 Level: developer 3125 3126 Notes: 3127 See [Matrix Factorization](sec_matfactor) for additional information about factorizations 3128 3129 Most users should employ the simplified `KSP` interface for linear solvers 3130 instead of working directly with matrix algebra routines such as this. 3131 See, e.g., `KSPCreate()`. 3132 3133 Developer Note: 3134 The Fortran interface is not autogenerated as the 3135 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3136 3137 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3138 @*/ 3139 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 3140 { 3141 MatFactorInfo tinfo; 3142 3143 PetscFunctionBegin; 3144 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3145 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 3146 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 3147 if (info) PetscValidPointer(info, 5); 3148 PetscValidType(mat, 2); 3149 PetscValidPointer(fact, 1); 3150 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3151 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3152 if (!(fact)->ops->lufactorsymbolic) { 3153 MatSolverType stype; 3154 PetscCall(MatFactorGetSolverType(fact, &stype)); 3155 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic LU using solver package %s", ((PetscObject)mat)->type_name, stype); 3156 } 3157 MatCheckPreallocated(mat, 2); 3158 if (!info) { 3159 PetscCall(MatFactorInfoInitialize(&tinfo)); 3160 info = &tinfo; 3161 } 3162 3163 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0)); 3164 PetscCall((fact->ops->lufactorsymbolic)(fact, mat, row, col, info)); 3165 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0)); 3166 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3167 PetscFunctionReturn(PETSC_SUCCESS); 3168 } 3169 3170 /*@C 3171 MatLUFactorNumeric - Performs numeric LU factorization of a matrix. 3172 Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`. 3173 3174 Collective 3175 3176 Input Parameters: 3177 + fact - the factor matrix obtained with `MatGetFactor()` 3178 . mat - the matrix 3179 - info - options for factorization 3180 3181 Level: developer 3182 3183 Notes: 3184 See `MatLUFactor()` for in-place factorization. See 3185 `MatCholeskyFactorNumeric()` for the symmetric, positive definite case. 3186 3187 Most users should employ the `KSP` interface for linear solvers 3188 instead of working directly with matrix algebra routines such as this. 3189 See, e.g., `KSPCreate()`. 3190 3191 Developer Note: 3192 The Fortran interface is not autogenerated as the 3193 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3194 3195 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()` 3196 @*/ 3197 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3198 { 3199 MatFactorInfo tinfo; 3200 3201 PetscFunctionBegin; 3202 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3203 PetscValidType(mat, 2); 3204 PetscValidPointer(fact, 1); 3205 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3206 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3207 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, 3208 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3209 3210 PetscCheck((fact)->ops->lufactornumeric, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s numeric LU", ((PetscObject)mat)->type_name); 3211 MatCheckPreallocated(mat, 2); 3212 if (!info) { 3213 PetscCall(MatFactorInfoInitialize(&tinfo)); 3214 info = &tinfo; 3215 } 3216 3217 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3218 else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0)); 3219 PetscCall((fact->ops->lufactornumeric)(fact, mat, info)); 3220 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3221 else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0)); 3222 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3223 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3224 PetscFunctionReturn(PETSC_SUCCESS); 3225 } 3226 3227 /*@C 3228 MatCholeskyFactor - Performs in-place Cholesky factorization of a 3229 symmetric matrix. 3230 3231 Collective 3232 3233 Input Parameters: 3234 + mat - the matrix 3235 . perm - row and column permutations 3236 - f - expected fill as ratio of original fill 3237 3238 Level: developer 3239 3240 Notes: 3241 See `MatLUFactor()` for the nonsymmetric case. See also `MatGetFactor()`, 3242 `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`. 3243 3244 Most users should employ the `KSP` interface for linear solvers 3245 instead of working directly with matrix algebra routines such as this. 3246 See, e.g., `KSPCreate()`. 3247 3248 Developer Note: 3249 The Fortran interface is not autogenerated as the 3250 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3251 3252 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()` 3253 `MatGetOrdering()` 3254 @*/ 3255 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info) 3256 { 3257 MatFactorInfo tinfo; 3258 3259 PetscFunctionBegin; 3260 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3261 PetscValidType(mat, 1); 3262 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2); 3263 if (info) PetscValidPointer(info, 3); 3264 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3265 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3266 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3267 MatCheckPreallocated(mat, 1); 3268 if (!info) { 3269 PetscCall(MatFactorInfoInitialize(&tinfo)); 3270 info = &tinfo; 3271 } 3272 3273 PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0)); 3274 PetscUseTypeMethod(mat, choleskyfactor, perm, info); 3275 PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0)); 3276 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3277 PetscFunctionReturn(PETSC_SUCCESS); 3278 } 3279 3280 /*@C 3281 MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization 3282 of a symmetric matrix. 3283 3284 Collective 3285 3286 Input Parameters: 3287 + fact - the factor matrix obtained with `MatGetFactor()` 3288 . mat - the matrix 3289 . perm - row and column permutations 3290 - info - options for factorization, includes 3291 .vb 3292 fill - expected fill as ratio of original fill. 3293 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3294 Run with the option -info to determine an optimal value to use 3295 .ve 3296 3297 Level: developer 3298 3299 Notes: 3300 See `MatLUFactorSymbolic()` for the nonsymmetric case. See also 3301 `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`. 3302 3303 Most users should employ the `KSP` interface for linear solvers 3304 instead of working directly with matrix algebra routines such as this. 3305 See, e.g., `KSPCreate()`. 3306 3307 Developer Note: 3308 The Fortran interface is not autogenerated as the 3309 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3310 3311 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()` 3312 `MatGetOrdering()` 3313 @*/ 3314 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 3315 { 3316 MatFactorInfo tinfo; 3317 3318 PetscFunctionBegin; 3319 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3320 PetscValidType(mat, 2); 3321 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 3322 if (info) PetscValidPointer(info, 4); 3323 PetscValidPointer(fact, 1); 3324 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3325 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3326 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3327 if (!(fact)->ops->choleskyfactorsymbolic) { 3328 MatSolverType stype; 3329 PetscCall(MatFactorGetSolverType(fact, &stype)); 3330 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s symbolic factor Cholesky using solver package %s", ((PetscObject)mat)->type_name, stype); 3331 } 3332 MatCheckPreallocated(mat, 2); 3333 if (!info) { 3334 PetscCall(MatFactorInfoInitialize(&tinfo)); 3335 info = &tinfo; 3336 } 3337 3338 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3339 PetscCall((fact->ops->choleskyfactorsymbolic)(fact, mat, perm, info)); 3340 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3341 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3342 PetscFunctionReturn(PETSC_SUCCESS); 3343 } 3344 3345 /*@C 3346 MatCholeskyFactorNumeric - Performs numeric Cholesky factorization 3347 of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and 3348 `MatCholeskyFactorSymbolic()`. 3349 3350 Collective 3351 3352 Input Parameters: 3353 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored 3354 . mat - the initial matrix that is to be factored 3355 - info - options for factorization 3356 3357 Level: developer 3358 3359 Note: 3360 Most users should employ the `KSP` interface for linear solvers 3361 instead of working directly with matrix algebra routines such as this. 3362 See, e.g., `KSPCreate()`. 3363 3364 Developer Note: 3365 The Fortran interface is not autogenerated as the 3366 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3367 3368 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()` 3369 @*/ 3370 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3371 { 3372 MatFactorInfo tinfo; 3373 3374 PetscFunctionBegin; 3375 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3376 PetscValidType(mat, 2); 3377 PetscValidPointer(fact, 1); 3378 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3379 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3380 PetscCheck((fact)->ops->choleskyfactornumeric, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s numeric factor Cholesky", ((PetscObject)mat)->type_name); 3381 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, 3382 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3383 MatCheckPreallocated(mat, 2); 3384 if (!info) { 3385 PetscCall(MatFactorInfoInitialize(&tinfo)); 3386 info = &tinfo; 3387 } 3388 3389 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3390 else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0)); 3391 PetscCall((fact->ops->choleskyfactornumeric)(fact, mat, info)); 3392 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3393 else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0)); 3394 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3395 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3396 PetscFunctionReturn(PETSC_SUCCESS); 3397 } 3398 3399 /*@ 3400 MatQRFactor - Performs in-place QR factorization of matrix. 3401 3402 Collective 3403 3404 Input Parameters: 3405 + mat - the matrix 3406 . col - column permutation 3407 - info - options for factorization, includes 3408 .vb 3409 fill - expected fill as ratio of original fill. 3410 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3411 Run with the option -info to determine an optimal value to use 3412 .ve 3413 3414 Level: developer 3415 3416 Notes: 3417 Most users should employ the `KSP` interface for linear solvers 3418 instead of working directly with matrix algebra routines such as this. 3419 See, e.g., `KSPCreate()`. 3420 3421 This changes the state of the matrix to a factored matrix; it cannot be used 3422 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3423 3424 Developer Note: 3425 The Fortran interface is not autogenerated as the 3426 interface definition cannot be generated correctly [due to MatFactorInfo] 3427 3428 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`, 3429 `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3430 @*/ 3431 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info) 3432 { 3433 PetscFunctionBegin; 3434 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3435 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2); 3436 if (info) PetscValidPointer(info, 3); 3437 PetscValidType(mat, 1); 3438 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3439 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3440 MatCheckPreallocated(mat, 1); 3441 PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0)); 3442 PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info)); 3443 PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0)); 3444 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3445 PetscFunctionReturn(PETSC_SUCCESS); 3446 } 3447 3448 /*@ 3449 MatQRFactorSymbolic - Performs symbolic QR factorization of matrix. 3450 Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`. 3451 3452 Collective 3453 3454 Input Parameters: 3455 + fact - the factor matrix obtained with `MatGetFactor()` 3456 . mat - the matrix 3457 . col - column permutation 3458 - info - options for factorization, includes 3459 .vb 3460 fill - expected fill as ratio of original fill. 3461 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3462 Run with the option -info to determine an optimal value to use 3463 .ve 3464 3465 Level: developer 3466 3467 Note: 3468 Most users should employ the `KSP` interface for linear solvers 3469 instead of working directly with matrix algebra routines such as this. 3470 See, e.g., `KSPCreate()`. 3471 3472 Developer Note: 3473 The Fortran interface is not autogenerated as the 3474 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3475 3476 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3477 @*/ 3478 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info) 3479 { 3480 MatFactorInfo tinfo; 3481 3482 PetscFunctionBegin; 3483 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3484 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3485 if (info) PetscValidPointer(info, 4); 3486 PetscValidType(mat, 2); 3487 PetscValidPointer(fact, 1); 3488 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3489 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3490 MatCheckPreallocated(mat, 2); 3491 if (!info) { 3492 PetscCall(MatFactorInfoInitialize(&tinfo)); 3493 info = &tinfo; 3494 } 3495 3496 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3497 PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info)); 3498 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3499 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3500 PetscFunctionReturn(PETSC_SUCCESS); 3501 } 3502 3503 /*@ 3504 MatQRFactorNumeric - Performs numeric QR factorization of a matrix. 3505 Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`. 3506 3507 Collective 3508 3509 Input Parameters: 3510 + fact - the factor matrix obtained with `MatGetFactor()` 3511 . mat - the matrix 3512 - info - options for factorization 3513 3514 Level: developer 3515 3516 Notes: 3517 See `MatQRFactor()` for in-place factorization. 3518 3519 Most users should employ the `KSP` interface for linear solvers 3520 instead of working directly with matrix algebra routines such as this. 3521 See, e.g., `KSPCreate()`. 3522 3523 Developer Note: 3524 The Fortran interface is not autogenerated as the 3525 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3526 3527 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()` 3528 @*/ 3529 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3530 { 3531 MatFactorInfo tinfo; 3532 3533 PetscFunctionBegin; 3534 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3535 PetscValidType(mat, 2); 3536 PetscValidPointer(fact, 1); 3537 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3538 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3539 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, 3540 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3541 3542 MatCheckPreallocated(mat, 2); 3543 if (!info) { 3544 PetscCall(MatFactorInfoInitialize(&tinfo)); 3545 info = &tinfo; 3546 } 3547 3548 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3549 else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0)); 3550 PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info)); 3551 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3552 else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0)); 3553 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3554 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3555 PetscFunctionReturn(PETSC_SUCCESS); 3556 } 3557 3558 /*@ 3559 MatSolve - Solves A x = b, given a factored matrix. 3560 3561 Neighbor-wise Collective 3562 3563 Input Parameters: 3564 + mat - the factored matrix 3565 - b - the right-hand-side vector 3566 3567 Output Parameter: 3568 . x - the result vector 3569 3570 Level: developer 3571 3572 Notes: 3573 The vectors `b` and `x` cannot be the same. I.e., one cannot 3574 call `MatSolve`(A,x,x). 3575 3576 Most users should employ the `KSP` interface for linear solvers 3577 instead of working directly with matrix algebra routines such as this. 3578 See, e.g., `KSPCreate()`. 3579 3580 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3581 @*/ 3582 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x) 3583 { 3584 PetscFunctionBegin; 3585 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3586 PetscValidType(mat, 1); 3587 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3588 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3589 PetscCheckSameComm(mat, 1, b, 2); 3590 PetscCheckSameComm(mat, 1, x, 3); 3591 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3592 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); 3593 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); 3594 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); 3595 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3596 MatCheckPreallocated(mat, 1); 3597 3598 PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0)); 3599 if (mat->factorerrortype) { 3600 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3601 PetscCall(VecSetInf(x)); 3602 } else PetscUseTypeMethod(mat, solve, b, x); 3603 PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0)); 3604 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3605 PetscFunctionReturn(PETSC_SUCCESS); 3606 } 3607 3608 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans) 3609 { 3610 Vec b, x; 3611 PetscInt N, i; 3612 PetscErrorCode (*f)(Mat, Vec, Vec); 3613 PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE; 3614 3615 PetscFunctionBegin; 3616 if (A->factorerrortype) { 3617 PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype)); 3618 PetscCall(MatSetInf(X)); 3619 PetscFunctionReturn(PETSC_SUCCESS); 3620 } 3621 f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose; 3622 PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 3623 PetscCall(MatBoundToCPU(A, &Abound)); 3624 if (!Abound) { 3625 PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3626 PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3627 } 3628 #if defined(PETSC_HAVE_CUDA) 3629 if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B)); 3630 if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X)); 3631 #elif (PETSC_HAVE_HIP) 3632 if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B)); 3633 if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X)); 3634 #endif 3635 PetscCall(MatGetSize(B, NULL, &N)); 3636 for (i = 0; i < N; i++) { 3637 PetscCall(MatDenseGetColumnVecRead(B, i, &b)); 3638 PetscCall(MatDenseGetColumnVecWrite(X, i, &x)); 3639 PetscCall((*f)(A, b, x)); 3640 PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x)); 3641 PetscCall(MatDenseRestoreColumnVecRead(B, i, &b)); 3642 } 3643 if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B)); 3644 if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X)); 3645 PetscFunctionReturn(PETSC_SUCCESS); 3646 } 3647 3648 /*@ 3649 MatMatSolve - Solves A X = B, given a factored matrix. 3650 3651 Neighbor-wise Collective 3652 3653 Input Parameters: 3654 + A - the factored matrix 3655 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS) 3656 3657 Output Parameter: 3658 . X - the result matrix (dense matrix) 3659 3660 Level: developer 3661 3662 Note: 3663 If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`; 3664 otherwise, `B` and `X` cannot be the same. 3665 3666 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3667 @*/ 3668 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X) 3669 { 3670 PetscFunctionBegin; 3671 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3672 PetscValidType(A, 1); 3673 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3674 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3675 PetscCheckSameComm(A, 1, B, 2); 3676 PetscCheckSameComm(A, 1, X, 3); 3677 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); 3678 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); 3679 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"); 3680 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3681 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3682 MatCheckPreallocated(A, 1); 3683 3684 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3685 if (!A->ops->matsolve) { 3686 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name)); 3687 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE)); 3688 } else PetscUseTypeMethod(A, matsolve, B, X); 3689 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3690 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3691 PetscFunctionReturn(PETSC_SUCCESS); 3692 } 3693 3694 /*@ 3695 MatMatSolveTranspose - Solves A^T X = B, given a factored matrix. 3696 3697 Neighbor-wise Collective 3698 3699 Input Parameters: 3700 + A - the factored matrix 3701 - B - the right-hand-side matrix (`MATDENSE` matrix) 3702 3703 Output Parameter: 3704 . X - the result matrix (dense matrix) 3705 3706 Level: developer 3707 3708 Note: 3709 The matrices `B` and `X` cannot be the same. I.e., one cannot 3710 call `MatMatSolveTranspose`(A,X,X). 3711 3712 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()` 3713 @*/ 3714 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X) 3715 { 3716 PetscFunctionBegin; 3717 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3718 PetscValidType(A, 1); 3719 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3720 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3721 PetscCheckSameComm(A, 1, B, 2); 3722 PetscCheckSameComm(A, 1, X, 3); 3723 PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3724 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); 3725 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); 3726 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); 3727 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"); 3728 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3729 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3730 MatCheckPreallocated(A, 1); 3731 3732 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3733 if (!A->ops->matsolvetranspose) { 3734 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name)); 3735 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE)); 3736 } else PetscUseTypeMethod(A, matsolvetranspose, B, X); 3737 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3738 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3739 PetscFunctionReturn(PETSC_SUCCESS); 3740 } 3741 3742 /*@ 3743 MatMatTransposeSolve - Solves A X = B^T, given a factored matrix. 3744 3745 Neighbor-wise Collective 3746 3747 Input Parameters: 3748 + A - the factored matrix 3749 - Bt - the transpose of right-hand-side matrix as a `MATDENSE` 3750 3751 Output Parameter: 3752 . X - the result matrix (dense matrix) 3753 3754 Level: developer 3755 3756 Note: 3757 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 3758 format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`. 3759 3760 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3761 @*/ 3762 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X) 3763 { 3764 PetscFunctionBegin; 3765 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3766 PetscValidType(A, 1); 3767 PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2); 3768 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3769 PetscCheckSameComm(A, 1, Bt, 2); 3770 PetscCheckSameComm(A, 1, X, 3); 3771 3772 PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3773 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); 3774 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); 3775 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"); 3776 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3777 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3778 MatCheckPreallocated(A, 1); 3779 3780 PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0)); 3781 PetscUseTypeMethod(A, mattransposesolve, Bt, X); 3782 PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0)); 3783 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3784 PetscFunctionReturn(PETSC_SUCCESS); 3785 } 3786 3787 /*@ 3788 MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or 3789 U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U, 3790 3791 Neighbor-wise Collective 3792 3793 Input Parameters: 3794 + mat - the factored matrix 3795 - b - the right-hand-side vector 3796 3797 Output Parameter: 3798 . x - the result vector 3799 3800 Level: developer 3801 3802 Notes: 3803 `MatSolve()` should be used for most applications, as it performs 3804 a forward solve followed by a backward solve. 3805 3806 The vectors `b` and `x` cannot be the same, i.e., one cannot 3807 call `MatForwardSolve`(A,x,x). 3808 3809 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3810 the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet. 3811 `MatForwardSolve()` solves U^T*D y = b, and 3812 `MatBackwardSolve()` solves U x = y. 3813 Thus they do not provide a symmetric preconditioner. 3814 3815 .seealso: [](chapter_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatBackwardSolve()` 3816 @*/ 3817 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x) 3818 { 3819 PetscFunctionBegin; 3820 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3821 PetscValidType(mat, 1); 3822 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3823 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3824 PetscCheckSameComm(mat, 1, b, 2); 3825 PetscCheckSameComm(mat, 1, x, 3); 3826 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3827 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); 3828 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); 3829 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); 3830 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3831 MatCheckPreallocated(mat, 1); 3832 3833 PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0)); 3834 PetscUseTypeMethod(mat, forwardsolve, b, x); 3835 PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0)); 3836 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3837 PetscFunctionReturn(PETSC_SUCCESS); 3838 } 3839 3840 /*@ 3841 MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU. 3842 D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U, 3843 3844 Neighbor-wise Collective 3845 3846 Input Parameters: 3847 + mat - the factored matrix 3848 - b - the right-hand-side vector 3849 3850 Output Parameter: 3851 . x - the result vector 3852 3853 Level: developer 3854 3855 Notes: 3856 `MatSolve()` should be used for most applications, as it performs 3857 a forward solve followed by a backward solve. 3858 3859 The vectors `b` and `x` cannot be the same. I.e., one cannot 3860 call `MatBackwardSolve`(A,x,x). 3861 3862 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3863 the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet. 3864 `MatForwardSolve()` solves U^T*D y = b, and 3865 `MatBackwardSolve()` solves U x = y. 3866 Thus they do not provide a symmetric preconditioner. 3867 3868 .seealso: [](chapter_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatForwardSolve()` 3869 @*/ 3870 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x) 3871 { 3872 PetscFunctionBegin; 3873 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3874 PetscValidType(mat, 1); 3875 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3876 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3877 PetscCheckSameComm(mat, 1, b, 2); 3878 PetscCheckSameComm(mat, 1, x, 3); 3879 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3880 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); 3881 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); 3882 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); 3883 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3884 MatCheckPreallocated(mat, 1); 3885 3886 PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0)); 3887 PetscUseTypeMethod(mat, backwardsolve, b, x); 3888 PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0)); 3889 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3890 PetscFunctionReturn(PETSC_SUCCESS); 3891 } 3892 3893 /*@ 3894 MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix. 3895 3896 Neighbor-wise Collective 3897 3898 Input Parameters: 3899 + mat - the factored matrix 3900 . b - the right-hand-side vector 3901 - y - the vector to be added to 3902 3903 Output Parameter: 3904 . x - the result vector 3905 3906 Level: developer 3907 3908 Note: 3909 The vectors `b` and `x` cannot be the same. I.e., one cannot 3910 call `MatSolveAdd`(A,x,y,x). 3911 3912 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3913 @*/ 3914 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x) 3915 { 3916 PetscScalar one = 1.0; 3917 Vec tmp; 3918 3919 PetscFunctionBegin; 3920 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3921 PetscValidType(mat, 1); 3922 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 3923 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3924 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 3925 PetscCheckSameComm(mat, 1, b, 2); 3926 PetscCheckSameComm(mat, 1, y, 3); 3927 PetscCheckSameComm(mat, 1, x, 4); 3928 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3929 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); 3930 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); 3931 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); 3932 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); 3933 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); 3934 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3935 MatCheckPreallocated(mat, 1); 3936 3937 PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y)); 3938 if (mat->factorerrortype) { 3939 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3940 PetscCall(VecSetInf(x)); 3941 } else if (mat->ops->solveadd) { 3942 PetscUseTypeMethod(mat, solveadd, b, y, x); 3943 } else { 3944 /* do the solve then the add manually */ 3945 if (x != y) { 3946 PetscCall(MatSolve(mat, b, x)); 3947 PetscCall(VecAXPY(x, one, y)); 3948 } else { 3949 PetscCall(VecDuplicate(x, &tmp)); 3950 PetscCall(VecCopy(x, tmp)); 3951 PetscCall(MatSolve(mat, b, x)); 3952 PetscCall(VecAXPY(x, one, tmp)); 3953 PetscCall(VecDestroy(&tmp)); 3954 } 3955 } 3956 PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y)); 3957 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3958 PetscFunctionReturn(PETSC_SUCCESS); 3959 } 3960 3961 /*@ 3962 MatSolveTranspose - Solves A' x = b, given a factored matrix. 3963 3964 Neighbor-wise Collective 3965 3966 Input Parameters: 3967 + mat - the factored matrix 3968 - b - the right-hand-side vector 3969 3970 Output Parameter: 3971 . x - the result vector 3972 3973 Level: developer 3974 3975 Notes: 3976 The vectors `b` and `x` cannot be the same. I.e., one cannot 3977 call `MatSolveTranspose`(A,x,x). 3978 3979 Most users should employ the `KSP` interface for linear solvers 3980 instead of working directly with matrix algebra routines such as this. 3981 See, e.g., `KSPCreate()`. 3982 3983 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()` 3984 @*/ 3985 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x) 3986 { 3987 PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose; 3988 3989 PetscFunctionBegin; 3990 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3991 PetscValidType(mat, 1); 3992 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3993 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3994 PetscCheckSameComm(mat, 1, b, 2); 3995 PetscCheckSameComm(mat, 1, x, 3); 3996 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3997 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); 3998 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); 3999 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4000 MatCheckPreallocated(mat, 1); 4001 PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0)); 4002 if (mat->factorerrortype) { 4003 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4004 PetscCall(VecSetInf(x)); 4005 } else { 4006 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name); 4007 PetscCall((*f)(mat, b, x)); 4008 } 4009 PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0)); 4010 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4011 PetscFunctionReturn(PETSC_SUCCESS); 4012 } 4013 4014 /*@ 4015 MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a 4016 factored matrix. 4017 4018 Neighbor-wise Collective 4019 4020 Input Parameters: 4021 + mat - the factored matrix 4022 . b - the right-hand-side vector 4023 - y - the vector to be added to 4024 4025 Output Parameter: 4026 . x - the result vector 4027 4028 Level: developer 4029 4030 Note: 4031 The vectors `b` and `x` cannot be the same. I.e., one cannot 4032 call `MatSolveTransposeAdd`(A,x,y,x). 4033 4034 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()` 4035 @*/ 4036 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x) 4037 { 4038 PetscScalar one = 1.0; 4039 Vec tmp; 4040 PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd; 4041 4042 PetscFunctionBegin; 4043 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4044 PetscValidType(mat, 1); 4045 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4046 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4047 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4048 PetscCheckSameComm(mat, 1, b, 2); 4049 PetscCheckSameComm(mat, 1, y, 3); 4050 PetscCheckSameComm(mat, 1, x, 4); 4051 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4052 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); 4053 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); 4054 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); 4055 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); 4056 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4057 MatCheckPreallocated(mat, 1); 4058 4059 PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y)); 4060 if (mat->factorerrortype) { 4061 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4062 PetscCall(VecSetInf(x)); 4063 } else if (f) { 4064 PetscCall((*f)(mat, b, y, x)); 4065 } else { 4066 /* do the solve then the add manually */ 4067 if (x != y) { 4068 PetscCall(MatSolveTranspose(mat, b, x)); 4069 PetscCall(VecAXPY(x, one, y)); 4070 } else { 4071 PetscCall(VecDuplicate(x, &tmp)); 4072 PetscCall(VecCopy(x, tmp)); 4073 PetscCall(MatSolveTranspose(mat, b, x)); 4074 PetscCall(VecAXPY(x, one, tmp)); 4075 PetscCall(VecDestroy(&tmp)); 4076 } 4077 } 4078 PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y)); 4079 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4080 PetscFunctionReturn(PETSC_SUCCESS); 4081 } 4082 4083 /*@ 4084 MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps. 4085 4086 Neighbor-wise Collective 4087 4088 Input Parameters: 4089 + mat - the matrix 4090 . b - the right hand side 4091 . omega - the relaxation factor 4092 . flag - flag indicating the type of SOR (see below) 4093 . shift - diagonal shift 4094 . its - the number of iterations 4095 - lits - the number of local iterations 4096 4097 Output Parameter: 4098 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess) 4099 4100 SOR Flags: 4101 + `SOR_FORWARD_SWEEP` - forward SOR 4102 . `SOR_BACKWARD_SWEEP` - backward SOR 4103 . `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR) 4104 . `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR 4105 . `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR 4106 . `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR 4107 . `SOR_EISENSTAT` - SOR with Eisenstat trick 4108 . `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies 4109 upper/lower triangular part of matrix to 4110 vector (with omega) 4111 - `SOR_ZERO_INITIAL_GUESS` - zero initial guess 4112 4113 Level: developer 4114 4115 Notes: 4116 `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and 4117 `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings 4118 on each processor. 4119 4120 Application programmers will not generally use `MatSOR()` directly, 4121 but instead will employ the `KSP`/`PC` interface. 4122 4123 For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing 4124 4125 Most users should employ the `KSP` interface for linear solvers 4126 instead of working directly with matrix algebra routines such as this. 4127 See, e.g., `KSPCreate()`. 4128 4129 Vectors `x` and `b` CANNOT be the same 4130 4131 The flags are implemented as bitwise inclusive or operations. 4132 For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`) 4133 to specify a zero initial guess for SSOR. 4134 4135 Developer Note: 4136 We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes 4137 4138 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()` 4139 @*/ 4140 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x) 4141 { 4142 PetscFunctionBegin; 4143 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4144 PetscValidType(mat, 1); 4145 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4146 PetscValidHeaderSpecific(x, VEC_CLASSID, 8); 4147 PetscCheckSameComm(mat, 1, b, 2); 4148 PetscCheckSameComm(mat, 1, x, 8); 4149 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4150 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4151 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); 4152 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); 4153 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); 4154 PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its); 4155 PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits); 4156 PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same"); 4157 4158 MatCheckPreallocated(mat, 1); 4159 PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0)); 4160 PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x); 4161 PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0)); 4162 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4163 PetscFunctionReturn(PETSC_SUCCESS); 4164 } 4165 4166 /* 4167 Default matrix copy routine. 4168 */ 4169 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str) 4170 { 4171 PetscInt i, rstart = 0, rend = 0, nz; 4172 const PetscInt *cwork; 4173 const PetscScalar *vwork; 4174 4175 PetscFunctionBegin; 4176 if (B->assembled) PetscCall(MatZeroEntries(B)); 4177 if (str == SAME_NONZERO_PATTERN) { 4178 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 4179 for (i = rstart; i < rend; i++) { 4180 PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork)); 4181 PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES)); 4182 PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork)); 4183 } 4184 } else { 4185 PetscCall(MatAYPX(B, 0.0, A, str)); 4186 } 4187 PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 4188 PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 4189 PetscFunctionReturn(PETSC_SUCCESS); 4190 } 4191 4192 /*@ 4193 MatCopy - Copies a matrix to another matrix. 4194 4195 Collective 4196 4197 Input Parameters: 4198 + A - the matrix 4199 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN` 4200 4201 Output Parameter: 4202 . B - where the copy is put 4203 4204 Level: intermediate 4205 4206 Notes: 4207 If you use `SAME_NONZERO_PATTERN` then the two matrices must have the same nonzero pattern or the routine will crash. 4208 4209 `MatCopy()` copies the matrix entries of a matrix to another existing 4210 matrix (after first zeroing the second matrix). A related routine is 4211 `MatConvert()`, which first creates a new matrix and then copies the data. 4212 4213 .seealso: [](chapter_matrices), `Mat`, `MatConvert()`, `MatDuplicate()` 4214 @*/ 4215 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str) 4216 { 4217 PetscInt i; 4218 4219 PetscFunctionBegin; 4220 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 4221 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 4222 PetscValidType(A, 1); 4223 PetscValidType(B, 2); 4224 PetscCheckSameComm(A, 1, B, 2); 4225 MatCheckPreallocated(B, 2); 4226 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4227 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4228 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, 4229 A->cmap->N, B->cmap->N); 4230 MatCheckPreallocated(A, 1); 4231 if (A == B) PetscFunctionReturn(PETSC_SUCCESS); 4232 4233 PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0)); 4234 if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str); 4235 else PetscCall(MatCopy_Basic(A, B, str)); 4236 4237 B->stencil.dim = A->stencil.dim; 4238 B->stencil.noc = A->stencil.noc; 4239 for (i = 0; i <= A->stencil.dim; i++) { 4240 B->stencil.dims[i] = A->stencil.dims[i]; 4241 B->stencil.starts[i] = A->stencil.starts[i]; 4242 } 4243 4244 PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0)); 4245 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4246 PetscFunctionReturn(PETSC_SUCCESS); 4247 } 4248 4249 /*@C 4250 MatConvert - Converts a matrix to another matrix, either of the same 4251 or different type. 4252 4253 Collective 4254 4255 Input Parameters: 4256 + mat - the matrix 4257 . newtype - new matrix type. Use `MATSAME` to create a new matrix of the 4258 same type as the original matrix. 4259 - reuse - denotes if the destination matrix is to be created or reused. 4260 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 4261 `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). 4262 4263 Output Parameter: 4264 . M - pointer to place new matrix 4265 4266 Level: intermediate 4267 4268 Notes: 4269 `MatConvert()` first creates a new matrix and then copies the data from 4270 the first matrix. A related routine is `MatCopy()`, which copies the matrix 4271 entries of one matrix to another already existing matrix context. 4272 4273 Cannot be used to convert a sequential matrix to parallel or parallel to sequential, 4274 the MPI communicator of the generated matrix is always the same as the communicator 4275 of the input matrix. 4276 4277 .seealso: [](chapter_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 4278 @*/ 4279 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M) 4280 { 4281 PetscBool sametype, issame, flg; 4282 PetscBool3 issymmetric, ishermitian; 4283 char convname[256], mtype[256]; 4284 Mat B; 4285 4286 PetscFunctionBegin; 4287 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4288 PetscValidType(mat, 1); 4289 PetscValidPointer(M, 4); 4290 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4291 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4292 MatCheckPreallocated(mat, 1); 4293 4294 PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg)); 4295 if (flg) newtype = mtype; 4296 4297 PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype)); 4298 PetscCall(PetscStrcmp(newtype, "same", &issame)); 4299 PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix"); 4300 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"); 4301 4302 if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) { 4303 PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4304 PetscFunctionReturn(PETSC_SUCCESS); 4305 } 4306 4307 /* Cache Mat options because some converters use MatHeaderReplace */ 4308 issymmetric = mat->symmetric; 4309 ishermitian = mat->hermitian; 4310 4311 if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) { 4312 PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4313 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4314 } else { 4315 PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL; 4316 const char *prefix[3] = {"seq", "mpi", ""}; 4317 PetscInt i; 4318 /* 4319 Order of precedence: 4320 0) See if newtype is a superclass of the current matrix. 4321 1) See if a specialized converter is known to the current matrix. 4322 2) See if a specialized converter is known to the desired matrix class. 4323 3) See if a good general converter is registered for the desired class 4324 (as of 6/27/03 only MATMPIADJ falls into this category). 4325 4) See if a good general converter is known for the current matrix. 4326 5) Use a really basic converter. 4327 */ 4328 4329 /* 0) See if newtype is a superclass of the current matrix. 4330 i.e mat is mpiaij and newtype is aij */ 4331 for (i = 0; i < 2; i++) { 4332 PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname))); 4333 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4334 PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg)); 4335 PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg)); 4336 if (flg) { 4337 if (reuse == MAT_INPLACE_MATRIX) { 4338 PetscCall(PetscInfo(mat, "Early return\n")); 4339 PetscFunctionReturn(PETSC_SUCCESS); 4340 } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) { 4341 PetscCall(PetscInfo(mat, "Calling MatDuplicate\n")); 4342 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4343 PetscFunctionReturn(PETSC_SUCCESS); 4344 } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) { 4345 PetscCall(PetscInfo(mat, "Calling MatCopy\n")); 4346 PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN)); 4347 PetscFunctionReturn(PETSC_SUCCESS); 4348 } 4349 } 4350 } 4351 /* 1) See if a specialized converter is known to the current matrix and the desired class */ 4352 for (i = 0; i < 3; i++) { 4353 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4354 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4355 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4356 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4357 PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname))); 4358 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4359 PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv)); 4360 PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv)); 4361 if (conv) goto foundconv; 4362 } 4363 4364 /* 2) See if a specialized converter is known to the desired matrix class. */ 4365 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B)); 4366 PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 4367 PetscCall(MatSetType(B, newtype)); 4368 for (i = 0; i < 3; i++) { 4369 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4370 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4371 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4372 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4373 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4374 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4375 PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv)); 4376 PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv)); 4377 if (conv) { 4378 PetscCall(MatDestroy(&B)); 4379 goto foundconv; 4380 } 4381 } 4382 4383 /* 3) See if a good general converter is registered for the desired class */ 4384 conv = B->ops->convertfrom; 4385 PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv)); 4386 PetscCall(MatDestroy(&B)); 4387 if (conv) goto foundconv; 4388 4389 /* 4) See if a good general converter is known for the current matrix */ 4390 if (mat->ops->convert) conv = mat->ops->convert; 4391 PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv)); 4392 if (conv) goto foundconv; 4393 4394 /* 5) Use a really basic converter. */ 4395 PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n")); 4396 conv = MatConvert_Basic; 4397 4398 foundconv: 4399 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4400 PetscCall((*conv)(mat, newtype, reuse, M)); 4401 if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) { 4402 /* the block sizes must be same if the mappings are copied over */ 4403 (*M)->rmap->bs = mat->rmap->bs; 4404 (*M)->cmap->bs = mat->cmap->bs; 4405 PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping)); 4406 PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping)); 4407 (*M)->rmap->mapping = mat->rmap->mapping; 4408 (*M)->cmap->mapping = mat->cmap->mapping; 4409 } 4410 (*M)->stencil.dim = mat->stencil.dim; 4411 (*M)->stencil.noc = mat->stencil.noc; 4412 for (i = 0; i <= mat->stencil.dim; i++) { 4413 (*M)->stencil.dims[i] = mat->stencil.dims[i]; 4414 (*M)->stencil.starts[i] = mat->stencil.starts[i]; 4415 } 4416 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4417 } 4418 PetscCall(PetscObjectStateIncrease((PetscObject)*M)); 4419 4420 /* Copy Mat options */ 4421 if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE)); 4422 else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE)); 4423 if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE)); 4424 else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE)); 4425 PetscFunctionReturn(PETSC_SUCCESS); 4426 } 4427 4428 /*@C 4429 MatFactorGetSolverType - Returns name of the package providing the factorization routines 4430 4431 Not Collective 4432 4433 Input Parameter: 4434 . mat - the matrix, must be a factored matrix 4435 4436 Output Parameter: 4437 . type - the string name of the package (do not free this string) 4438 4439 Level: intermediate 4440 4441 Fortran Note: 4442 Pass in an empty string and the package name will be copied into it. Make sure the string is long enough. 4443 4444 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()` 4445 @*/ 4446 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type) 4447 { 4448 PetscErrorCode (*conv)(Mat, MatSolverType *); 4449 4450 PetscFunctionBegin; 4451 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4452 PetscValidType(mat, 1); 4453 PetscValidPointer(type, 2); 4454 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 4455 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv)); 4456 if (conv) PetscCall((*conv)(mat, type)); 4457 else *type = MATSOLVERPETSC; 4458 PetscFunctionReturn(PETSC_SUCCESS); 4459 } 4460 4461 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType; 4462 struct _MatSolverTypeForSpecifcType { 4463 MatType mtype; 4464 /* no entry for MAT_FACTOR_NONE */ 4465 PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *); 4466 MatSolverTypeForSpecifcType next; 4467 }; 4468 4469 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder; 4470 struct _MatSolverTypeHolder { 4471 char *name; 4472 MatSolverTypeForSpecifcType handlers; 4473 MatSolverTypeHolder next; 4474 }; 4475 4476 static MatSolverTypeHolder MatSolverTypeHolders = NULL; 4477 4478 /*@C 4479 MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type 4480 4481 Input Parameters: 4482 + package - name of the package, for example petsc or superlu 4483 . mtype - the matrix type that works with this package 4484 . ftype - the type of factorization supported by the package 4485 - createfactor - routine that will create the factored matrix ready to be used 4486 4487 Level: developer 4488 4489 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()` 4490 @*/ 4491 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *)) 4492 { 4493 MatSolverTypeHolder next = MatSolverTypeHolders, prev = NULL; 4494 PetscBool flg; 4495 MatSolverTypeForSpecifcType inext, iprev = NULL; 4496 4497 PetscFunctionBegin; 4498 PetscCall(MatInitializePackage()); 4499 if (!next) { 4500 PetscCall(PetscNew(&MatSolverTypeHolders)); 4501 PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name)); 4502 PetscCall(PetscNew(&MatSolverTypeHolders->handlers)); 4503 PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype)); 4504 MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor; 4505 PetscFunctionReturn(PETSC_SUCCESS); 4506 } 4507 while (next) { 4508 PetscCall(PetscStrcasecmp(package, next->name, &flg)); 4509 if (flg) { 4510 PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers"); 4511 inext = next->handlers; 4512 while (inext) { 4513 PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg)); 4514 if (flg) { 4515 inext->createfactor[(int)ftype - 1] = createfactor; 4516 PetscFunctionReturn(PETSC_SUCCESS); 4517 } 4518 iprev = inext; 4519 inext = inext->next; 4520 } 4521 PetscCall(PetscNew(&iprev->next)); 4522 PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype)); 4523 iprev->next->createfactor[(int)ftype - 1] = createfactor; 4524 PetscFunctionReturn(PETSC_SUCCESS); 4525 } 4526 prev = next; 4527 next = next->next; 4528 } 4529 PetscCall(PetscNew(&prev->next)); 4530 PetscCall(PetscStrallocpy(package, &prev->next->name)); 4531 PetscCall(PetscNew(&prev->next->handlers)); 4532 PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype)); 4533 prev->next->handlers->createfactor[(int)ftype - 1] = createfactor; 4534 PetscFunctionReturn(PETSC_SUCCESS); 4535 } 4536 4537 /*@C 4538 MatSolverTypeGet - Gets the function that creates the factor matrix if it exist 4539 4540 Input Parameters: 4541 + type - name of the package, for example petsc or superlu 4542 . ftype - the type of factorization supported by the type 4543 - mtype - the matrix type that works with this type 4544 4545 Output Parameters: 4546 + foundtype - `PETSC_TRUE` if the type was registered 4547 . foundmtype - `PETSC_TRUE` if the type supports the requested mtype 4548 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found 4549 4550 Level: developer 4551 4552 .seealso: [](chapter_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()` 4553 @*/ 4554 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *)) 4555 { 4556 MatSolverTypeHolder next = MatSolverTypeHolders; 4557 PetscBool flg; 4558 MatSolverTypeForSpecifcType inext; 4559 4560 PetscFunctionBegin; 4561 if (foundtype) *foundtype = PETSC_FALSE; 4562 if (foundmtype) *foundmtype = PETSC_FALSE; 4563 if (createfactor) *createfactor = NULL; 4564 4565 if (type) { 4566 while (next) { 4567 PetscCall(PetscStrcasecmp(type, next->name, &flg)); 4568 if (flg) { 4569 if (foundtype) *foundtype = PETSC_TRUE; 4570 inext = next->handlers; 4571 while (inext) { 4572 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4573 if (flg) { 4574 if (foundmtype) *foundmtype = PETSC_TRUE; 4575 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4576 PetscFunctionReturn(PETSC_SUCCESS); 4577 } 4578 inext = inext->next; 4579 } 4580 } 4581 next = next->next; 4582 } 4583 } else { 4584 while (next) { 4585 inext = next->handlers; 4586 while (inext) { 4587 PetscCall(PetscStrcmp(mtype, inext->mtype, &flg)); 4588 if (flg && inext->createfactor[(int)ftype - 1]) { 4589 if (foundtype) *foundtype = PETSC_TRUE; 4590 if (foundmtype) *foundmtype = PETSC_TRUE; 4591 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4592 PetscFunctionReturn(PETSC_SUCCESS); 4593 } 4594 inext = inext->next; 4595 } 4596 next = next->next; 4597 } 4598 /* try with base classes inext->mtype */ 4599 next = MatSolverTypeHolders; 4600 while (next) { 4601 inext = next->handlers; 4602 while (inext) { 4603 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4604 if (flg && inext->createfactor[(int)ftype - 1]) { 4605 if (foundtype) *foundtype = PETSC_TRUE; 4606 if (foundmtype) *foundmtype = PETSC_TRUE; 4607 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4608 PetscFunctionReturn(PETSC_SUCCESS); 4609 } 4610 inext = inext->next; 4611 } 4612 next = next->next; 4613 } 4614 } 4615 PetscFunctionReturn(PETSC_SUCCESS); 4616 } 4617 4618 PetscErrorCode MatSolverTypeDestroy(void) 4619 { 4620 MatSolverTypeHolder next = MatSolverTypeHolders, prev; 4621 MatSolverTypeForSpecifcType inext, iprev; 4622 4623 PetscFunctionBegin; 4624 while (next) { 4625 PetscCall(PetscFree(next->name)); 4626 inext = next->handlers; 4627 while (inext) { 4628 PetscCall(PetscFree(inext->mtype)); 4629 iprev = inext; 4630 inext = inext->next; 4631 PetscCall(PetscFree(iprev)); 4632 } 4633 prev = next; 4634 next = next->next; 4635 PetscCall(PetscFree(prev)); 4636 } 4637 MatSolverTypeHolders = NULL; 4638 PetscFunctionReturn(PETSC_SUCCESS); 4639 } 4640 4641 /*@C 4642 MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4643 4644 Logically Collective 4645 4646 Input Parameter: 4647 . mat - the matrix 4648 4649 Output Parameter: 4650 . flg - `PETSC_TRUE` if uses the ordering 4651 4652 Level: developer 4653 4654 Note: 4655 Most internal PETSc factorizations use the ordering passed to the factorization routine but external 4656 packages do not, thus we want to skip generating the ordering when it is not needed or used. 4657 4658 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4659 @*/ 4660 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg) 4661 { 4662 PetscFunctionBegin; 4663 *flg = mat->canuseordering; 4664 PetscFunctionReturn(PETSC_SUCCESS); 4665 } 4666 4667 /*@C 4668 MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object 4669 4670 Logically Collective 4671 4672 Input Parameters: 4673 + mat - the matrix obtained with `MatGetFactor()` 4674 - ftype - the factorization type to be used 4675 4676 Output Parameter: 4677 . otype - the preferred ordering type 4678 4679 Level: developer 4680 4681 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4682 @*/ 4683 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype) 4684 { 4685 PetscFunctionBegin; 4686 *otype = mat->preferredordering[ftype]; 4687 PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering"); 4688 PetscFunctionReturn(PETSC_SUCCESS); 4689 } 4690 4691 /*@C 4692 MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic() 4693 4694 Collective 4695 4696 Input Parameters: 4697 + mat - the matrix 4698 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4699 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4700 4701 Output Parameter: 4702 . f - the factor matrix used with MatXXFactorSymbolic() calls 4703 4704 Options Database Key: 4705 . -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory. 4706 One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices. 4707 4708 Level: intermediate 4709 4710 Notes: 4711 Users usually access the factorization solvers via `KSP` 4712 4713 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4714 such as pastix, superlu, mumps etc. 4715 4716 PETSc must have been ./configure to use the external solver, using the option --download-package 4717 4718 Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption 4719 where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set 4720 call `MatSetOptionsPrefixFactor()` on the originating matrix or `MatSetOptionsPrefix()` on the resulting factor matrix. 4721 4722 Developer Note: 4723 This should actually be called `MatCreateFactor()` since it creates a new factor object 4724 4725 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, 4726 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4727 @*/ 4728 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f) 4729 { 4730 PetscBool foundtype, foundmtype; 4731 PetscErrorCode (*conv)(Mat, MatFactorType, Mat *); 4732 4733 PetscFunctionBegin; 4734 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4735 PetscValidType(mat, 1); 4736 4737 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4738 MatCheckPreallocated(mat, 1); 4739 4740 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv)); 4741 if (!foundtype) { 4742 if (type) { 4743 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], 4744 ((PetscObject)mat)->type_name, type); 4745 } else { 4746 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); 4747 } 4748 } 4749 PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name); 4750 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); 4751 4752 PetscCall((*conv)(mat, ftype, f)); 4753 if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix)); 4754 PetscFunctionReturn(PETSC_SUCCESS); 4755 } 4756 4757 /*@C 4758 MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type 4759 4760 Not Collective 4761 4762 Input Parameters: 4763 + mat - the matrix 4764 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4765 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4766 4767 Output Parameter: 4768 . flg - PETSC_TRUE if the factorization is available 4769 4770 Level: intermediate 4771 4772 Notes: 4773 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4774 such as pastix, superlu, mumps etc. 4775 4776 PETSc must have been ./configure to use the external solver, using the option --download-package 4777 4778 Developer Note: 4779 This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object 4780 4781 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactor()`, `MatSolverTypeRegister()`, 4782 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4783 @*/ 4784 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg) 4785 { 4786 PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *); 4787 4788 PetscFunctionBegin; 4789 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4790 PetscValidType(mat, 1); 4791 PetscValidBoolPointer(flg, 4); 4792 4793 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4794 MatCheckPreallocated(mat, 1); 4795 4796 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv)); 4797 *flg = gconv ? PETSC_TRUE : PETSC_FALSE; 4798 PetscFunctionReturn(PETSC_SUCCESS); 4799 } 4800 4801 /*@ 4802 MatDuplicate - Duplicates a matrix including the non-zero structure. 4803 4804 Collective 4805 4806 Input Parameters: 4807 + mat - the matrix 4808 - op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`. 4809 See the manual page for `MatDuplicateOption()` for an explanation of these options. 4810 4811 Output Parameter: 4812 . M - pointer to place new matrix 4813 4814 Level: intermediate 4815 4816 Notes: 4817 You cannot change the nonzero pattern for the parent or child matrix if you use `MAT_SHARE_NONZERO_PATTERN`. 4818 4819 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. 4820 4821 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 4822 is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated. 4823 User should not use `MatDuplicate()` to create new matrix M if M is intended to be reused as the product of matrix operation. 4824 4825 .seealso: [](chapter_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption` 4826 @*/ 4827 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M) 4828 { 4829 Mat B; 4830 VecType vtype; 4831 PetscInt i; 4832 PetscObject dm; 4833 void (*viewf)(void); 4834 4835 PetscFunctionBegin; 4836 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4837 PetscValidType(mat, 1); 4838 PetscValidPointer(M, 3); 4839 PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix"); 4840 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4841 MatCheckPreallocated(mat, 1); 4842 4843 *M = NULL; 4844 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4845 PetscUseTypeMethod(mat, duplicate, op, M); 4846 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4847 B = *M; 4848 4849 PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf)); 4850 if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf)); 4851 PetscCall(MatGetVecType(mat, &vtype)); 4852 PetscCall(MatSetVecType(B, vtype)); 4853 4854 B->stencil.dim = mat->stencil.dim; 4855 B->stencil.noc = mat->stencil.noc; 4856 for (i = 0; i <= mat->stencil.dim; i++) { 4857 B->stencil.dims[i] = mat->stencil.dims[i]; 4858 B->stencil.starts[i] = mat->stencil.starts[i]; 4859 } 4860 4861 B->nooffproczerorows = mat->nooffproczerorows; 4862 B->nooffprocentries = mat->nooffprocentries; 4863 4864 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm)); 4865 if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm)); 4866 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4867 PetscFunctionReturn(PETSC_SUCCESS); 4868 } 4869 4870 /*@ 4871 MatGetDiagonal - Gets the diagonal of a matrix as a `Vec` 4872 4873 Logically Collective 4874 4875 Input Parameter: 4876 . mat - the matrix 4877 4878 Output Parameter: 4879 . v - the diagonal of the matrix 4880 4881 Level: intermediate 4882 4883 Note: 4884 Currently only correct in parallel for square matrices. 4885 4886 .seealso: [](chapter_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()` 4887 @*/ 4888 PetscErrorCode MatGetDiagonal(Mat mat, Vec v) 4889 { 4890 PetscFunctionBegin; 4891 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4892 PetscValidType(mat, 1); 4893 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4894 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4895 MatCheckPreallocated(mat, 1); 4896 4897 PetscUseTypeMethod(mat, getdiagonal, v); 4898 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4899 PetscFunctionReturn(PETSC_SUCCESS); 4900 } 4901 4902 /*@C 4903 MatGetRowMin - Gets the minimum value (of the real part) of each 4904 row of the matrix 4905 4906 Logically Collective 4907 4908 Input Parameter: 4909 . mat - the matrix 4910 4911 Output Parameters: 4912 + v - the vector for storing the maximums 4913 - idx - the indices of the column found for each row (optional) 4914 4915 Level: intermediate 4916 4917 Note: 4918 The result of this call are the same as if one converted the matrix to dense format 4919 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 4920 4921 This code is only implemented for a couple of matrix formats. 4922 4923 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, 4924 `MatGetRowMax()` 4925 @*/ 4926 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[]) 4927 { 4928 PetscFunctionBegin; 4929 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4930 PetscValidType(mat, 1); 4931 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4932 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4933 4934 if (!mat->cmap->N) { 4935 PetscCall(VecSet(v, PETSC_MAX_REAL)); 4936 if (idx) { 4937 PetscInt i, m = mat->rmap->n; 4938 for (i = 0; i < m; i++) idx[i] = -1; 4939 } 4940 } else { 4941 MatCheckPreallocated(mat, 1); 4942 } 4943 PetscUseTypeMethod(mat, getrowmin, v, idx); 4944 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4945 PetscFunctionReturn(PETSC_SUCCESS); 4946 } 4947 4948 /*@C 4949 MatGetRowMinAbs - Gets the minimum value (in absolute value) of each 4950 row of the matrix 4951 4952 Logically Collective 4953 4954 Input Parameter: 4955 . mat - the matrix 4956 4957 Output Parameters: 4958 + v - the vector for storing the minimums 4959 - idx - the indices of the column found for each row (or `NULL` if not needed) 4960 4961 Level: intermediate 4962 4963 Notes: 4964 if a row is completely empty or has only 0.0 values then the idx[] value for that 4965 row is 0 (the first column). 4966 4967 This code is only implemented for a couple of matrix formats. 4968 4969 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()` 4970 @*/ 4971 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[]) 4972 { 4973 PetscFunctionBegin; 4974 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4975 PetscValidType(mat, 1); 4976 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4977 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4978 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4979 4980 if (!mat->cmap->N) { 4981 PetscCall(VecSet(v, 0.0)); 4982 if (idx) { 4983 PetscInt i, m = mat->rmap->n; 4984 for (i = 0; i < m; i++) idx[i] = -1; 4985 } 4986 } else { 4987 MatCheckPreallocated(mat, 1); 4988 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 4989 PetscUseTypeMethod(mat, getrowminabs, v, idx); 4990 } 4991 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4992 PetscFunctionReturn(PETSC_SUCCESS); 4993 } 4994 4995 /*@C 4996 MatGetRowMax - Gets the maximum value (of the real part) of each 4997 row of the matrix 4998 4999 Logically Collective 5000 5001 Input Parameter: 5002 . mat - the matrix 5003 5004 Output Parameters: 5005 + v - the vector for storing the maximums 5006 - idx - the indices of the column found for each row (optional) 5007 5008 Level: intermediate 5009 5010 Notes: 5011 The result of this call are the same as if one converted the matrix to dense format 5012 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5013 5014 This code is only implemented for a couple of matrix formats. 5015 5016 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5017 @*/ 5018 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[]) 5019 { 5020 PetscFunctionBegin; 5021 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5022 PetscValidType(mat, 1); 5023 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5024 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5025 5026 if (!mat->cmap->N) { 5027 PetscCall(VecSet(v, PETSC_MIN_REAL)); 5028 if (idx) { 5029 PetscInt i, m = mat->rmap->n; 5030 for (i = 0; i < m; i++) idx[i] = -1; 5031 } 5032 } else { 5033 MatCheckPreallocated(mat, 1); 5034 PetscUseTypeMethod(mat, getrowmax, v, idx); 5035 } 5036 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5037 PetscFunctionReturn(PETSC_SUCCESS); 5038 } 5039 5040 /*@C 5041 MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each 5042 row of the matrix 5043 5044 Logically Collective 5045 5046 Input Parameter: 5047 . mat - the matrix 5048 5049 Output Parameters: 5050 + v - the vector for storing the maximums 5051 - idx - the indices of the column found for each row (or `NULL` if not needed) 5052 5053 Level: intermediate 5054 5055 Notes: 5056 if a row is completely empty or has only 0.0 values then the idx[] value for that 5057 row is 0 (the first column). 5058 5059 This code is only implemented for a couple of matrix formats. 5060 5061 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5062 @*/ 5063 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[]) 5064 { 5065 PetscFunctionBegin; 5066 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5067 PetscValidType(mat, 1); 5068 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5069 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5070 5071 if (!mat->cmap->N) { 5072 PetscCall(VecSet(v, 0.0)); 5073 if (idx) { 5074 PetscInt i, m = mat->rmap->n; 5075 for (i = 0; i < m; i++) idx[i] = -1; 5076 } 5077 } else { 5078 MatCheckPreallocated(mat, 1); 5079 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5080 PetscUseTypeMethod(mat, getrowmaxabs, v, idx); 5081 } 5082 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5083 PetscFunctionReturn(PETSC_SUCCESS); 5084 } 5085 5086 /*@ 5087 MatGetRowSum - Gets the sum of each row of the matrix 5088 5089 Logically or Neighborhood Collective 5090 5091 Input Parameter: 5092 . mat - the matrix 5093 5094 Output Parameter: 5095 . v - the vector for storing the sum of rows 5096 5097 Level: intermediate 5098 5099 Notes: 5100 This code is slow since it is not currently specialized for different formats 5101 5102 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()` 5103 @*/ 5104 PetscErrorCode MatGetRowSum(Mat mat, Vec v) 5105 { 5106 Vec ones; 5107 5108 PetscFunctionBegin; 5109 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5110 PetscValidType(mat, 1); 5111 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5112 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5113 MatCheckPreallocated(mat, 1); 5114 PetscCall(MatCreateVecs(mat, &ones, NULL)); 5115 PetscCall(VecSet(ones, 1.)); 5116 PetscCall(MatMult(mat, ones, v)); 5117 PetscCall(VecDestroy(&ones)); 5118 PetscFunctionReturn(PETSC_SUCCESS); 5119 } 5120 5121 /*@ 5122 MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) 5123 when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B) 5124 5125 Collective 5126 5127 Input Parameter: 5128 . mat - the matrix to provide the transpose 5129 5130 Output Parameter: 5131 . 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 5132 5133 Level: advanced 5134 5135 Note: 5136 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 5137 routine allows bypassing that call. 5138 5139 .seealso: [](chapter_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5140 @*/ 5141 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B) 5142 { 5143 PetscContainer rB = NULL; 5144 MatParentState *rb = NULL; 5145 5146 PetscFunctionBegin; 5147 PetscCall(PetscNew(&rb)); 5148 rb->id = ((PetscObject)mat)->id; 5149 rb->state = 0; 5150 PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate)); 5151 PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB)); 5152 PetscCall(PetscContainerSetPointer(rB, rb)); 5153 PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault)); 5154 PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB)); 5155 PetscCall(PetscObjectDereference((PetscObject)rB)); 5156 PetscFunctionReturn(PETSC_SUCCESS); 5157 } 5158 5159 /*@ 5160 MatTranspose - Computes an in-place or out-of-place transpose of a matrix. 5161 5162 Collective 5163 5164 Input Parameters: 5165 + mat - the matrix to transpose 5166 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5167 5168 Output Parameter: 5169 . B - the transpose 5170 5171 Level: intermediate 5172 5173 Notes: 5174 If you use `MAT_INPLACE_MATRIX` then you must pass in &mat for B 5175 5176 `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 5177 transpose, call `MatTransposeSetPrecursor`(mat,B) before calling this routine. 5178 5179 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. 5180 5181 Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed. 5182 5183 If mat is unchanged from the last call this function returns immediately without recomputing the result 5184 5185 If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()` 5186 5187 .seealso: [](chapter_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`, 5188 `MatTransposeSymbolic()`, `MatCreateTranspose()` 5189 @*/ 5190 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B) 5191 { 5192 PetscContainer rB = NULL; 5193 MatParentState *rb = NULL; 5194 5195 PetscFunctionBegin; 5196 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5197 PetscValidType(mat, 1); 5198 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5199 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5200 PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first"); 5201 PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX"); 5202 MatCheckPreallocated(mat, 1); 5203 if (reuse == MAT_REUSE_MATRIX) { 5204 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5205 PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor()."); 5206 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5207 PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5208 if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS); 5209 } 5210 5211 PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0)); 5212 if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) { 5213 PetscUseTypeMethod(mat, transpose, reuse, B); 5214 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5215 } 5216 PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0)); 5217 5218 if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B)); 5219 if (reuse != MAT_INPLACE_MATRIX) { 5220 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5221 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5222 rb->state = ((PetscObject)mat)->state; 5223 rb->nonzerostate = mat->nonzerostate; 5224 } 5225 PetscFunctionReturn(PETSC_SUCCESS); 5226 } 5227 5228 /*@ 5229 MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix. 5230 5231 Collective 5232 5233 Input Parameter: 5234 . A - the matrix to transpose 5235 5236 Output Parameter: 5237 . 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 5238 numerical portion. 5239 5240 Level: intermediate 5241 5242 Note: 5243 This is not supported for many matrix types, use `MatTranspose()` in those cases 5244 5245 .seealso: [](chapter_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5246 @*/ 5247 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B) 5248 { 5249 PetscFunctionBegin; 5250 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5251 PetscValidType(A, 1); 5252 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5253 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5254 PetscCheck(A->ops->transposesymbolic, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 5255 PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0)); 5256 PetscCall((*A->ops->transposesymbolic)(A, B)); 5257 PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0)); 5258 5259 PetscCall(MatTransposeSetPrecursor(A, *B)); 5260 PetscFunctionReturn(PETSC_SUCCESS); 5261 } 5262 5263 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B) 5264 { 5265 PetscContainer rB; 5266 MatParentState *rb; 5267 5268 PetscFunctionBegin; 5269 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5270 PetscValidType(A, 1); 5271 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5272 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5273 PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB)); 5274 PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()"); 5275 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5276 PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5277 PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure"); 5278 PetscFunctionReturn(PETSC_SUCCESS); 5279 } 5280 5281 /*@ 5282 MatIsTranspose - Test whether a matrix is another one's transpose, 5283 or its own, in which case it tests symmetry. 5284 5285 Collective 5286 5287 Input Parameters: 5288 + A - the matrix to test 5289 . B - the matrix to test against, this can equal the first parameter 5290 - tol - tolerance, differences between entries smaller than this are counted as zero 5291 5292 Output Parameter: 5293 . flg - the result 5294 5295 Level: intermediate 5296 5297 Notes: 5298 Only available for `MATAIJ` matrices. 5299 5300 The sequential algorithm has a running time of the order of the number of nonzeros; the parallel 5301 test involves parallel copies of the block-offdiagonal parts of the matrix. 5302 5303 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()` 5304 @*/ 5305 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5306 { 5307 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5308 5309 PetscFunctionBegin; 5310 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5311 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5312 PetscValidBoolPointer(flg, 4); 5313 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f)); 5314 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g)); 5315 *flg = PETSC_FALSE; 5316 if (f && g) { 5317 PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test"); 5318 PetscCall((*f)(A, B, tol, flg)); 5319 } else { 5320 MatType mattype; 5321 5322 PetscCall(MatGetType(f ? B : A, &mattype)); 5323 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype); 5324 } 5325 PetscFunctionReturn(PETSC_SUCCESS); 5326 } 5327 5328 /*@ 5329 MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate. 5330 5331 Collective 5332 5333 Input Parameters: 5334 + mat - the matrix to transpose and complex conjugate 5335 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5336 5337 Output Parameter: 5338 . B - the Hermitian transpose 5339 5340 Level: intermediate 5341 5342 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse` 5343 @*/ 5344 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B) 5345 { 5346 PetscFunctionBegin; 5347 PetscCall(MatTranspose(mat, reuse, B)); 5348 #if defined(PETSC_USE_COMPLEX) 5349 PetscCall(MatConjugate(*B)); 5350 #endif 5351 PetscFunctionReturn(PETSC_SUCCESS); 5352 } 5353 5354 /*@ 5355 MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose, 5356 5357 Collective 5358 5359 Input Parameters: 5360 + A - the matrix to test 5361 . B - the matrix to test against, this can equal the first parameter 5362 - tol - tolerance, differences between entries smaller than this are counted as zero 5363 5364 Output Parameter: 5365 . flg - the result 5366 5367 Level: intermediate 5368 5369 Notes: 5370 Only available for `MATAIJ` matrices. 5371 5372 The sequential algorithm 5373 has a running time of the order of the number of nonzeros; the parallel 5374 test involves parallel copies of the block-offdiagonal parts of the matrix. 5375 5376 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()` 5377 @*/ 5378 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5379 { 5380 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5381 5382 PetscFunctionBegin; 5383 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5384 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5385 PetscValidBoolPointer(flg, 4); 5386 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f)); 5387 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g)); 5388 if (f && g) { 5389 PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test"); 5390 PetscCall((*f)(A, B, tol, flg)); 5391 } 5392 PetscFunctionReturn(PETSC_SUCCESS); 5393 } 5394 5395 /*@ 5396 MatPermute - Creates a new matrix with rows and columns permuted from the 5397 original. 5398 5399 Collective 5400 5401 Input Parameters: 5402 + mat - the matrix to permute 5403 . row - row permutation, each processor supplies only the permutation for its rows 5404 - col - column permutation, each processor supplies only the permutation for its columns 5405 5406 Output Parameter: 5407 . B - the permuted matrix 5408 5409 Level: advanced 5410 5411 Note: 5412 The index sets map from row/col of permuted matrix to row/col of original matrix. 5413 The index sets should be on the same communicator as mat and have the same local sizes. 5414 5415 Developer Note: 5416 If you want to implement `MatPermute()` for a matrix type, and your approach doesn't 5417 exploit the fact that row and col are permutations, consider implementing the 5418 more general `MatCreateSubMatrix()` instead. 5419 5420 .seealso: [](chapter_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()` 5421 @*/ 5422 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B) 5423 { 5424 PetscFunctionBegin; 5425 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5426 PetscValidType(mat, 1); 5427 PetscValidHeaderSpecific(row, IS_CLASSID, 2); 5428 PetscValidHeaderSpecific(col, IS_CLASSID, 3); 5429 PetscValidPointer(B, 4); 5430 PetscCheckSameComm(mat, 1, row, 2); 5431 if (row != col) PetscCheckSameComm(row, 2, col, 3); 5432 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5433 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5434 PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name); 5435 MatCheckPreallocated(mat, 1); 5436 5437 if (mat->ops->permute) { 5438 PetscUseTypeMethod(mat, permute, row, col, B); 5439 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5440 } else { 5441 PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B)); 5442 } 5443 PetscFunctionReturn(PETSC_SUCCESS); 5444 } 5445 5446 /*@ 5447 MatEqual - Compares two matrices. 5448 5449 Collective 5450 5451 Input Parameters: 5452 + A - the first matrix 5453 - B - the second matrix 5454 5455 Output Parameter: 5456 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise. 5457 5458 Level: intermediate 5459 5460 .seealso: [](chapter_matrices), `Mat` 5461 @*/ 5462 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg) 5463 { 5464 PetscFunctionBegin; 5465 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5466 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5467 PetscValidType(A, 1); 5468 PetscValidType(B, 2); 5469 PetscValidBoolPointer(flg, 3); 5470 PetscCheckSameComm(A, 1, B, 2); 5471 MatCheckPreallocated(A, 1); 5472 MatCheckPreallocated(B, 2); 5473 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5474 PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5475 PetscCheck(A->rmap->N == B->rmap->N && A->cmap->N == B->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat B: global dim %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->N, B->rmap->N, A->cmap->N, 5476 B->cmap->N); 5477 if (A->ops->equal && A->ops->equal == B->ops->equal) { 5478 PetscUseTypeMethod(A, equal, B, flg); 5479 } else { 5480 PetscCall(MatMultEqual(A, B, 10, flg)); 5481 } 5482 PetscFunctionReturn(PETSC_SUCCESS); 5483 } 5484 5485 /*@ 5486 MatDiagonalScale - Scales a matrix on the left and right by diagonal 5487 matrices that are stored as vectors. Either of the two scaling 5488 matrices can be `NULL`. 5489 5490 Collective 5491 5492 Input Parameters: 5493 + mat - the matrix to be scaled 5494 . l - the left scaling vector (or `NULL`) 5495 - r - the right scaling vector (or `NULL`) 5496 5497 Level: intermediate 5498 5499 Note: 5500 `MatDiagonalScale()` computes A = LAR, where 5501 L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector) 5502 The L scales the rows of the matrix, the R scales the columns of the matrix. 5503 5504 .seealso: [](chapter_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()` 5505 @*/ 5506 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r) 5507 { 5508 PetscFunctionBegin; 5509 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5510 PetscValidType(mat, 1); 5511 if (l) { 5512 PetscValidHeaderSpecific(l, VEC_CLASSID, 2); 5513 PetscCheckSameComm(mat, 1, l, 2); 5514 } 5515 if (r) { 5516 PetscValidHeaderSpecific(r, VEC_CLASSID, 3); 5517 PetscCheckSameComm(mat, 1, r, 3); 5518 } 5519 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5520 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5521 MatCheckPreallocated(mat, 1); 5522 if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS); 5523 5524 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5525 PetscUseTypeMethod(mat, diagonalscale, l, r); 5526 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5527 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5528 if (l != r) mat->symmetric = PETSC_BOOL3_FALSE; 5529 PetscFunctionReturn(PETSC_SUCCESS); 5530 } 5531 5532 /*@ 5533 MatScale - Scales all elements of a matrix by a given number. 5534 5535 Logically Collective 5536 5537 Input Parameters: 5538 + mat - the matrix to be scaled 5539 - a - the scaling value 5540 5541 Level: intermediate 5542 5543 .seealso: [](chapter_matrices), `Mat`, `MatDiagonalScale()` 5544 @*/ 5545 PetscErrorCode MatScale(Mat mat, PetscScalar a) 5546 { 5547 PetscFunctionBegin; 5548 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5549 PetscValidType(mat, 1); 5550 PetscCheck(a == (PetscScalar)1.0 || mat->ops->scale, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 5551 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5552 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5553 PetscValidLogicalCollectiveScalar(mat, a, 2); 5554 MatCheckPreallocated(mat, 1); 5555 5556 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5557 if (a != (PetscScalar)1.0) { 5558 PetscUseTypeMethod(mat, scale, a); 5559 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5560 } 5561 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5562 PetscFunctionReturn(PETSC_SUCCESS); 5563 } 5564 5565 /*@ 5566 MatNorm - Calculates various norms of a matrix. 5567 5568 Collective 5569 5570 Input Parameters: 5571 + mat - the matrix 5572 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY` 5573 5574 Output Parameter: 5575 . nrm - the resulting norm 5576 5577 Level: intermediate 5578 5579 .seealso: [](chapter_matrices), `Mat` 5580 @*/ 5581 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm) 5582 { 5583 PetscFunctionBegin; 5584 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5585 PetscValidType(mat, 1); 5586 PetscValidRealPointer(nrm, 3); 5587 5588 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5589 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5590 MatCheckPreallocated(mat, 1); 5591 5592 PetscUseTypeMethod(mat, norm, type, nrm); 5593 PetscFunctionReturn(PETSC_SUCCESS); 5594 } 5595 5596 /* 5597 This variable is used to prevent counting of MatAssemblyBegin() that 5598 are called from within a MatAssemblyEnd(). 5599 */ 5600 static PetscInt MatAssemblyEnd_InUse = 0; 5601 /*@ 5602 MatAssemblyBegin - Begins assembling the matrix. This routine should 5603 be called after completing all calls to `MatSetValues()`. 5604 5605 Collective 5606 5607 Input Parameters: 5608 + mat - the matrix 5609 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5610 5611 Level: beginner 5612 5613 Notes: 5614 `MatSetValues()` generally caches the values that belong to other MPI ranks. The matrix is ready to 5615 use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called. 5616 5617 Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES` 5618 in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before 5619 using the matrix. 5620 5621 ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the 5622 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 5623 a global collective operation requiring all processes that share the matrix. 5624 5625 Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed 5626 out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros 5627 before `MAT_FINAL_ASSEMBLY` so the space is not compressed out. 5628 5629 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()` 5630 @*/ 5631 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type) 5632 { 5633 PetscFunctionBegin; 5634 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5635 PetscValidType(mat, 1); 5636 MatCheckPreallocated(mat, 1); 5637 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?"); 5638 if (mat->assembled) { 5639 mat->was_assembled = PETSC_TRUE; 5640 mat->assembled = PETSC_FALSE; 5641 } 5642 5643 if (!MatAssemblyEnd_InUse) { 5644 PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0)); 5645 PetscTryTypeMethod(mat, assemblybegin, type); 5646 PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0)); 5647 } else PetscTryTypeMethod(mat, assemblybegin, type); 5648 PetscFunctionReturn(PETSC_SUCCESS); 5649 } 5650 5651 /*@ 5652 MatAssembled - Indicates if a matrix has been assembled and is ready for 5653 use; for example, in matrix-vector product. 5654 5655 Not Collective 5656 5657 Input Parameter: 5658 . mat - the matrix 5659 5660 Output Parameter: 5661 . assembled - `PETSC_TRUE` or `PETSC_FALSE` 5662 5663 Level: advanced 5664 5665 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()` 5666 @*/ 5667 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled) 5668 { 5669 PetscFunctionBegin; 5670 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5671 PetscValidBoolPointer(assembled, 2); 5672 *assembled = mat->assembled; 5673 PetscFunctionReturn(PETSC_SUCCESS); 5674 } 5675 5676 /*@ 5677 MatAssemblyEnd - Completes assembling the matrix. This routine should 5678 be called after `MatAssemblyBegin()`. 5679 5680 Collective 5681 5682 Input Parameters: 5683 + mat - the matrix 5684 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5685 5686 Options Database Keys: 5687 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatEndAssembly()` 5688 . -mat_view ::ascii_info_detail - Prints more detailed info 5689 . -mat_view - Prints matrix in ASCII format 5690 . -mat_view ::ascii_matlab - Prints matrix in Matlab format 5691 . -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 5692 . -display <name> - Sets display name (default is host) 5693 . -draw_pause <sec> - Sets number of seconds to pause after display 5694 . -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See [Using MATLAB with PETSc](ch_matlab)) 5695 . -viewer_socket_machine <machine> - Machine to use for socket 5696 . -viewer_socket_port <port> - Port number to use for socket 5697 - -mat_view binary:filename[:append] - Save matrix to file in binary format 5698 5699 Level: beginner 5700 5701 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()` 5702 @*/ 5703 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type) 5704 { 5705 static PetscInt inassm = 0; 5706 PetscBool flg = PETSC_FALSE; 5707 5708 PetscFunctionBegin; 5709 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5710 PetscValidType(mat, 1); 5711 5712 inassm++; 5713 MatAssemblyEnd_InUse++; 5714 if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */ 5715 PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0)); 5716 PetscTryTypeMethod(mat, assemblyend, type); 5717 PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0)); 5718 } else PetscTryTypeMethod(mat, assemblyend, type); 5719 5720 /* Flush assembly is not a true assembly */ 5721 if (type != MAT_FLUSH_ASSEMBLY) { 5722 if (mat->num_ass) { 5723 if (!mat->symmetry_eternal) { 5724 mat->symmetric = PETSC_BOOL3_UNKNOWN; 5725 mat->hermitian = PETSC_BOOL3_UNKNOWN; 5726 } 5727 if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN; 5728 if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN; 5729 } 5730 mat->num_ass++; 5731 mat->assembled = PETSC_TRUE; 5732 mat->ass_nonzerostate = mat->nonzerostate; 5733 } 5734 5735 mat->insertmode = NOT_SET_VALUES; 5736 MatAssemblyEnd_InUse--; 5737 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5738 if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) { 5739 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 5740 5741 if (mat->checksymmetryonassembly) { 5742 PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg)); 5743 if (flg) { 5744 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5745 } else { 5746 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5747 } 5748 } 5749 if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL)); 5750 } 5751 inassm--; 5752 PetscFunctionReturn(PETSC_SUCCESS); 5753 } 5754 5755 /*@ 5756 MatSetOption - Sets a parameter option for a matrix. Some options 5757 may be specific to certain storage formats. Some options 5758 determine how values will be inserted (or added). Sorted, 5759 row-oriented input will generally assemble the fastest. The default 5760 is row-oriented. 5761 5762 Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption` 5763 5764 Input Parameters: 5765 + mat - the matrix 5766 . option - the option, one of those listed below (and possibly others), 5767 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5768 5769 Options Describing Matrix Structure: 5770 + `MAT_SPD` - symmetric positive definite 5771 . `MAT_SYMMETRIC` - symmetric in terms of both structure and value 5772 . `MAT_HERMITIAN` - transpose is the complex conjugation 5773 . `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure 5774 . `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix 5775 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix 5776 - `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix 5777 5778 These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they 5779 do not need to be computed (usually at a high cost) 5780 5781 Options For Use with `MatSetValues()`: 5782 Insert a logically dense subblock, which can be 5783 . `MAT_ROW_ORIENTED` - row-oriented (default) 5784 5785 These options reflect the data you pass in with `MatSetValues()`; it has 5786 nothing to do with how the data is stored internally in the matrix 5787 data structure. 5788 5789 When (re)assembling a matrix, we can restrict the input for 5790 efficiency/debugging purposes. These options include 5791 + `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow) 5792 . `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated 5793 . `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries 5794 . `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry 5795 . `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly 5796 . `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if 5797 any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves 5798 performance for very large process counts. 5799 - `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset 5800 of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly 5801 functions, instead sending only neighbor messages. 5802 5803 Level: intermediate 5804 5805 Notes: 5806 Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg! 5807 5808 Some options are relevant only for particular matrix types and 5809 are thus ignored by others. Other options are not supported by 5810 certain matrix types and will generate an error message if set. 5811 5812 If using Fortran to compute a matrix, one may need to 5813 use the column-oriented option (or convert to the row-oriented 5814 format). 5815 5816 `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion 5817 that would generate a new entry in the nonzero structure is instead 5818 ignored. Thus, if memory has not already been allocated for this particular 5819 data, then the insertion is ignored. For dense matrices, in which 5820 the entire array is allocated, no entries are ever ignored. 5821 Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction 5822 5823 `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion 5824 that would generate a new entry in the nonzero structure instead produces 5825 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 5826 5827 `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion 5828 that would generate a new entry that has not been preallocated will 5829 instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats 5830 only.) This is a useful flag when debugging matrix memory preallocation. 5831 If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 5832 5833 `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for 5834 other processors should be dropped, rather than stashed. 5835 This is useful if you know that the "owning" processor is also 5836 always generating the correct matrix entries, so that PETSc need 5837 not transfer duplicate entries generated on another processor. 5838 5839 `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the 5840 searches during matrix assembly. When this flag is set, the hash table 5841 is created during the first matrix assembly. This hash table is 5842 used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()` 5843 to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag 5844 should be used with `MAT_USE_HASH_TABLE` flag. This option is currently 5845 supported by `MATMPIBAIJ` format only. 5846 5847 `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries 5848 are kept in the nonzero structure 5849 5850 `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating 5851 a zero location in the matrix 5852 5853 `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types 5854 5855 `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the 5856 zero row routines and thus improves performance for very large process counts. 5857 5858 `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular 5859 part of the matrix (since they should match the upper triangular part). 5860 5861 `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a 5862 single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common 5863 with finite difference schemes with non-periodic boundary conditions. 5864 5865 Developer Note: 5866 `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other 5867 places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRIC` or `MAT_SPD` would need to be changed back 5868 to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had 5869 not changed. 5870 5871 .seealso: [](chapter_matrices), `MatOption`, `Mat`, `MatGetOption()` 5872 @*/ 5873 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg) 5874 { 5875 PetscFunctionBegin; 5876 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5877 if (op > 0) { 5878 PetscValidLogicalCollectiveEnum(mat, op, 2); 5879 PetscValidLogicalCollectiveBool(mat, flg, 3); 5880 } 5881 5882 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); 5883 5884 switch (op) { 5885 case MAT_FORCE_DIAGONAL_ENTRIES: 5886 mat->force_diagonals = flg; 5887 PetscFunctionReturn(PETSC_SUCCESS); 5888 case MAT_NO_OFF_PROC_ENTRIES: 5889 mat->nooffprocentries = flg; 5890 PetscFunctionReturn(PETSC_SUCCESS); 5891 case MAT_SUBSET_OFF_PROC_ENTRIES: 5892 mat->assembly_subset = flg; 5893 if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */ 5894 #if !defined(PETSC_HAVE_MPIUNI) 5895 PetscCall(MatStashScatterDestroy_BTS(&mat->stash)); 5896 #endif 5897 mat->stash.first_assembly_done = PETSC_FALSE; 5898 } 5899 PetscFunctionReturn(PETSC_SUCCESS); 5900 case MAT_NO_OFF_PROC_ZERO_ROWS: 5901 mat->nooffproczerorows = flg; 5902 PetscFunctionReturn(PETSC_SUCCESS); 5903 case MAT_SPD: 5904 if (flg) { 5905 mat->spd = PETSC_BOOL3_TRUE; 5906 mat->symmetric = PETSC_BOOL3_TRUE; 5907 mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5908 } else { 5909 mat->spd = PETSC_BOOL3_FALSE; 5910 } 5911 break; 5912 case MAT_SYMMETRIC: 5913 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5914 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5915 #if !defined(PETSC_USE_COMPLEX) 5916 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5917 #endif 5918 break; 5919 case MAT_HERMITIAN: 5920 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5921 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5922 #if !defined(PETSC_USE_COMPLEX) 5923 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5924 #endif 5925 break; 5926 case MAT_STRUCTURALLY_SYMMETRIC: 5927 mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5928 break; 5929 case MAT_SYMMETRY_ETERNAL: 5930 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"); 5931 mat->symmetry_eternal = flg; 5932 if (flg) mat->structural_symmetry_eternal = PETSC_TRUE; 5933 break; 5934 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 5935 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"); 5936 mat->structural_symmetry_eternal = flg; 5937 break; 5938 case MAT_SPD_ETERNAL: 5939 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"); 5940 mat->spd_eternal = flg; 5941 if (flg) { 5942 mat->structural_symmetry_eternal = PETSC_TRUE; 5943 mat->symmetry_eternal = PETSC_TRUE; 5944 } 5945 break; 5946 case MAT_STRUCTURE_ONLY: 5947 mat->structure_only = flg; 5948 break; 5949 case MAT_SORTED_FULL: 5950 mat->sortedfull = flg; 5951 break; 5952 default: 5953 break; 5954 } 5955 PetscTryTypeMethod(mat, setoption, op, flg); 5956 PetscFunctionReturn(PETSC_SUCCESS); 5957 } 5958 5959 /*@ 5960 MatGetOption - Gets a parameter option that has been set for a matrix. 5961 5962 Logically Collective 5963 5964 Input Parameters: 5965 + mat - the matrix 5966 - option - the option, this only responds to certain options, check the code for which ones 5967 5968 Output Parameter: 5969 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5970 5971 Level: intermediate 5972 5973 Notes: 5974 Can only be called after `MatSetSizes()` and `MatSetType()` have been set. 5975 5976 Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or 5977 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 5978 5979 .seealso: [](chapter_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, 5980 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 5981 @*/ 5982 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg) 5983 { 5984 PetscFunctionBegin; 5985 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5986 PetscValidType(mat, 1); 5987 5988 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); 5989 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()"); 5990 5991 switch (op) { 5992 case MAT_NO_OFF_PROC_ENTRIES: 5993 *flg = mat->nooffprocentries; 5994 break; 5995 case MAT_NO_OFF_PROC_ZERO_ROWS: 5996 *flg = mat->nooffproczerorows; 5997 break; 5998 case MAT_SYMMETRIC: 5999 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()"); 6000 break; 6001 case MAT_HERMITIAN: 6002 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()"); 6003 break; 6004 case MAT_STRUCTURALLY_SYMMETRIC: 6005 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()"); 6006 break; 6007 case MAT_SPD: 6008 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()"); 6009 break; 6010 case MAT_SYMMETRY_ETERNAL: 6011 *flg = mat->symmetry_eternal; 6012 break; 6013 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6014 *flg = mat->symmetry_eternal; 6015 break; 6016 default: 6017 break; 6018 } 6019 PetscFunctionReturn(PETSC_SUCCESS); 6020 } 6021 6022 /*@ 6023 MatZeroEntries - Zeros all entries of a matrix. For sparse matrices 6024 this routine retains the old nonzero structure. 6025 6026 Logically Collective 6027 6028 Input Parameter: 6029 . mat - the matrix 6030 6031 Level: intermediate 6032 6033 Note: 6034 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. 6035 See the Performance chapter of the users manual for information on preallocating matrices. 6036 6037 .seealso: [](chapter_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()` 6038 @*/ 6039 PetscErrorCode MatZeroEntries(Mat mat) 6040 { 6041 PetscFunctionBegin; 6042 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6043 PetscValidType(mat, 1); 6044 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6045 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"); 6046 MatCheckPreallocated(mat, 1); 6047 6048 PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0)); 6049 PetscUseTypeMethod(mat, zeroentries); 6050 PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0)); 6051 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6052 PetscFunctionReturn(PETSC_SUCCESS); 6053 } 6054 6055 /*@ 6056 MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal) 6057 of a set of rows and columns of a matrix. 6058 6059 Collective 6060 6061 Input Parameters: 6062 + mat - the matrix 6063 . numRows - the number of rows/columns to zero 6064 . rows - the global row indices 6065 . diag - value put in the diagonal of the eliminated rows 6066 . x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call 6067 - b - optional vector of the right hand side, that will be adjusted by provided solution entries 6068 6069 Level: intermediate 6070 6071 Notes: 6072 This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6073 6074 For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`. 6075 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 6076 6077 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6078 Krylov method to take advantage of the known solution on the zeroed rows. 6079 6080 For the parallel case, all processes that share the matrix (i.e., 6081 those in the communicator used for matrix creation) MUST call this 6082 routine, regardless of whether any rows being zeroed are owned by 6083 them. 6084 6085 Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix. 6086 6087 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6088 list only rows local to itself). 6089 6090 The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine. 6091 6092 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6093 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6094 @*/ 6095 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6096 { 6097 PetscFunctionBegin; 6098 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6099 PetscValidType(mat, 1); 6100 if (numRows) PetscValidIntPointer(rows, 3); 6101 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6102 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6103 MatCheckPreallocated(mat, 1); 6104 6105 PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b); 6106 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6107 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6108 PetscFunctionReturn(PETSC_SUCCESS); 6109 } 6110 6111 /*@ 6112 MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal) 6113 of a set of rows and columns of a matrix. 6114 6115 Collective 6116 6117 Input Parameters: 6118 + mat - the matrix 6119 . is - the rows to zero 6120 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6121 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6122 - b - optional vector of right hand side, that will be adjusted by provided solution 6123 6124 Level: intermediate 6125 6126 Note: 6127 See `MatZeroRowsColumns()` for details on how this routine operates. 6128 6129 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6130 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()` 6131 @*/ 6132 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6133 { 6134 PetscInt numRows; 6135 const PetscInt *rows; 6136 6137 PetscFunctionBegin; 6138 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6139 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6140 PetscValidType(mat, 1); 6141 PetscValidType(is, 2); 6142 PetscCall(ISGetLocalSize(is, &numRows)); 6143 PetscCall(ISGetIndices(is, &rows)); 6144 PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b)); 6145 PetscCall(ISRestoreIndices(is, &rows)); 6146 PetscFunctionReturn(PETSC_SUCCESS); 6147 } 6148 6149 /*@ 6150 MatZeroRows - Zeros all entries (except possibly the main diagonal) 6151 of a set of rows of a matrix. 6152 6153 Collective 6154 6155 Input Parameters: 6156 + mat - the matrix 6157 . numRows - the number of rows to zero 6158 . rows - the global row indices 6159 . diag - value put in the diagonal of the zeroed rows 6160 . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call 6161 - b - optional vector of right hand side, that will be adjusted by provided solution entries 6162 6163 Level: intermediate 6164 6165 Notes: 6166 This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6167 6168 For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`. 6169 6170 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6171 Krylov method to take advantage of the known solution on the zeroed rows. 6172 6173 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) 6174 from the matrix. 6175 6176 Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix 6177 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 6178 formats this does not alter the nonzero structure. 6179 6180 If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure 6181 of the matrix is not changed the values are 6182 merely zeroed. 6183 6184 The user can set a value in the diagonal entry (or for the `MATAIJ` format 6185 formats can optionally remove the main diagonal entry from the 6186 nonzero structure as well, by passing 0.0 as the final argument). 6187 6188 For the parallel case, all processes that share the matrix (i.e., 6189 those in the communicator used for matrix creation) MUST call this 6190 routine, regardless of whether any rows being zeroed are owned by 6191 them. 6192 6193 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6194 list only rows local to itself). 6195 6196 You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it 6197 owns that are to be zeroed. This saves a global synchronization in the implementation. 6198 6199 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6200 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE` 6201 @*/ 6202 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6203 { 6204 PetscFunctionBegin; 6205 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6206 PetscValidType(mat, 1); 6207 if (numRows) PetscValidIntPointer(rows, 3); 6208 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6209 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6210 MatCheckPreallocated(mat, 1); 6211 6212 PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b); 6213 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6214 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6215 PetscFunctionReturn(PETSC_SUCCESS); 6216 } 6217 6218 /*@ 6219 MatZeroRowsIS - Zeros all entries (except possibly the main diagonal) 6220 of a set of rows of a matrix. 6221 6222 Collective 6223 6224 Input Parameters: 6225 + mat - the matrix 6226 . is - index set of rows to remove (if `NULL` then no row is removed) 6227 . diag - value put in all diagonals of eliminated rows 6228 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6229 - b - optional vector of right hand side, that will be adjusted by provided solution 6230 6231 Level: intermediate 6232 6233 Note: 6234 See `MatZeroRows()` for details on how this routine operates. 6235 6236 .seealso: [](chapter_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6237 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6238 @*/ 6239 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6240 { 6241 PetscInt numRows = 0; 6242 const PetscInt *rows = NULL; 6243 6244 PetscFunctionBegin; 6245 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6246 PetscValidType(mat, 1); 6247 if (is) { 6248 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6249 PetscCall(ISGetLocalSize(is, &numRows)); 6250 PetscCall(ISGetIndices(is, &rows)); 6251 } 6252 PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b)); 6253 if (is) PetscCall(ISRestoreIndices(is, &rows)); 6254 PetscFunctionReturn(PETSC_SUCCESS); 6255 } 6256 6257 /*@ 6258 MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal) 6259 of a set of rows of a matrix. These rows must be local to the process. 6260 6261 Collective 6262 6263 Input Parameters: 6264 + mat - the matrix 6265 . numRows - the number of rows to remove 6266 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6267 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6268 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6269 - b - optional vector of right hand side, that will be adjusted by provided solution 6270 6271 Level: intermediate 6272 6273 Notes: 6274 See `MatZeroRows()` for details on how this routine operates. 6275 6276 The grid coordinates are across the entire grid, not just the local portion 6277 6278 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6279 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6280 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6281 `DM_BOUNDARY_PERIODIC` boundary type. 6282 6283 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 6284 a single value per point) you can skip filling those indices. 6285 6286 Fortran Note: 6287 `idxm` and `idxn` should be declared as 6288 $ MatStencil idxm(4,m) 6289 and the values inserted using 6290 .vb 6291 idxm(MatStencil_i,1) = i 6292 idxm(MatStencil_j,1) = j 6293 idxm(MatStencil_k,1) = k 6294 idxm(MatStencil_c,1) = c 6295 etc 6296 .ve 6297 6298 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6299 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6300 @*/ 6301 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6302 { 6303 PetscInt dim = mat->stencil.dim; 6304 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6305 PetscInt *dims = mat->stencil.dims + 1; 6306 PetscInt *starts = mat->stencil.starts; 6307 PetscInt *dxm = (PetscInt *)rows; 6308 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6309 6310 PetscFunctionBegin; 6311 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6312 PetscValidType(mat, 1); 6313 if (numRows) PetscValidPointer(rows, 3); 6314 6315 PetscCall(PetscMalloc1(numRows, &jdxm)); 6316 for (i = 0; i < numRows; ++i) { 6317 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6318 for (j = 0; j < 3 - sdim; ++j) dxm++; 6319 /* Local index in X dir */ 6320 tmp = *dxm++ - starts[0]; 6321 /* Loop over remaining dimensions */ 6322 for (j = 0; j < dim - 1; ++j) { 6323 /* If nonlocal, set index to be negative */ 6324 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6325 /* Update local index */ 6326 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6327 } 6328 /* Skip component slot if necessary */ 6329 if (mat->stencil.noc) dxm++; 6330 /* Local row number */ 6331 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6332 } 6333 PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b)); 6334 PetscCall(PetscFree(jdxm)); 6335 PetscFunctionReturn(PETSC_SUCCESS); 6336 } 6337 6338 /*@ 6339 MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal) 6340 of a set of rows and columns of a matrix. 6341 6342 Collective 6343 6344 Input Parameters: 6345 + mat - the matrix 6346 . numRows - the number of rows/columns to remove 6347 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6348 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6349 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6350 - b - optional vector of right hand side, that will be adjusted by provided solution 6351 6352 Level: intermediate 6353 6354 Notes: 6355 See `MatZeroRowsColumns()` for details on how this routine operates. 6356 6357 The grid coordinates are across the entire grid, not just the local portion 6358 6359 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6360 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6361 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6362 `DM_BOUNDARY_PERIODIC` boundary type. 6363 6364 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 6365 a single value per point) you can skip filling those indices. 6366 6367 Fortran Note: 6368 `idxm` and `idxn` should be declared as 6369 $ MatStencil idxm(4,m) 6370 and the values inserted using 6371 .vb 6372 idxm(MatStencil_i,1) = i 6373 idxm(MatStencil_j,1) = j 6374 idxm(MatStencil_k,1) = k 6375 idxm(MatStencil_c,1) = c 6376 etc 6377 .ve 6378 6379 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6380 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()` 6381 @*/ 6382 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6383 { 6384 PetscInt dim = mat->stencil.dim; 6385 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6386 PetscInt *dims = mat->stencil.dims + 1; 6387 PetscInt *starts = mat->stencil.starts; 6388 PetscInt *dxm = (PetscInt *)rows; 6389 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6390 6391 PetscFunctionBegin; 6392 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6393 PetscValidType(mat, 1); 6394 if (numRows) PetscValidPointer(rows, 3); 6395 6396 PetscCall(PetscMalloc1(numRows, &jdxm)); 6397 for (i = 0; i < numRows; ++i) { 6398 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6399 for (j = 0; j < 3 - sdim; ++j) dxm++; 6400 /* Local index in X dir */ 6401 tmp = *dxm++ - starts[0]; 6402 /* Loop over remaining dimensions */ 6403 for (j = 0; j < dim - 1; ++j) { 6404 /* If nonlocal, set index to be negative */ 6405 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6406 /* Update local index */ 6407 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6408 } 6409 /* Skip component slot if necessary */ 6410 if (mat->stencil.noc) dxm++; 6411 /* Local row number */ 6412 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6413 } 6414 PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b)); 6415 PetscCall(PetscFree(jdxm)); 6416 PetscFunctionReturn(PETSC_SUCCESS); 6417 } 6418 6419 /*@C 6420 MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal) 6421 of a set of rows of a matrix; using local numbering of rows. 6422 6423 Collective 6424 6425 Input Parameters: 6426 + mat - the matrix 6427 . numRows - the number of rows to remove 6428 . rows - the local row indices 6429 . diag - value put in all diagonals of eliminated rows 6430 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6431 - b - optional vector of right hand side, that will be adjusted by provided solution 6432 6433 Level: intermediate 6434 6435 Notes: 6436 Before calling `MatZeroRowsLocal()`, the user must first set the 6437 local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`. 6438 6439 See `MatZeroRows()` for details on how this routine operates. 6440 6441 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`, 6442 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6443 @*/ 6444 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6445 { 6446 PetscFunctionBegin; 6447 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6448 PetscValidType(mat, 1); 6449 if (numRows) PetscValidIntPointer(rows, 3); 6450 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6451 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6452 MatCheckPreallocated(mat, 1); 6453 6454 if (mat->ops->zerorowslocal) { 6455 PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b); 6456 } else { 6457 IS is, newis; 6458 const PetscInt *newRows; 6459 6460 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6461 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6462 PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis)); 6463 PetscCall(ISGetIndices(newis, &newRows)); 6464 PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b); 6465 PetscCall(ISRestoreIndices(newis, &newRows)); 6466 PetscCall(ISDestroy(&newis)); 6467 PetscCall(ISDestroy(&is)); 6468 } 6469 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6470 PetscFunctionReturn(PETSC_SUCCESS); 6471 } 6472 6473 /*@ 6474 MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal) 6475 of a set of rows of a matrix; using local numbering of rows. 6476 6477 Collective 6478 6479 Input Parameters: 6480 + mat - the matrix 6481 . is - index set of rows to remove 6482 . diag - value put in all diagonals of eliminated rows 6483 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6484 - b - optional vector of right hand side, that will be adjusted by provided solution 6485 6486 Level: intermediate 6487 6488 Notes: 6489 Before calling `MatZeroRowsLocalIS()`, the user must first set the 6490 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6491 6492 See `MatZeroRows()` for details on how this routine operates. 6493 6494 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6495 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6496 @*/ 6497 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6498 { 6499 PetscInt numRows; 6500 const PetscInt *rows; 6501 6502 PetscFunctionBegin; 6503 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6504 PetscValidType(mat, 1); 6505 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6506 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6507 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6508 MatCheckPreallocated(mat, 1); 6509 6510 PetscCall(ISGetLocalSize(is, &numRows)); 6511 PetscCall(ISGetIndices(is, &rows)); 6512 PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b)); 6513 PetscCall(ISRestoreIndices(is, &rows)); 6514 PetscFunctionReturn(PETSC_SUCCESS); 6515 } 6516 6517 /*@ 6518 MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal) 6519 of a set of rows and columns of a matrix; using local numbering of rows. 6520 6521 Collective 6522 6523 Input Parameters: 6524 + mat - the matrix 6525 . numRows - the number of rows to remove 6526 . rows - the global row indices 6527 . diag - value put in all diagonals of eliminated rows 6528 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6529 - b - optional vector of right hand side, that will be adjusted by provided solution 6530 6531 Level: intermediate 6532 6533 Notes: 6534 Before calling `MatZeroRowsColumnsLocal()`, the user must first set the 6535 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6536 6537 See `MatZeroRowsColumns()` for details on how this routine operates. 6538 6539 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6540 `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6541 @*/ 6542 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6543 { 6544 IS is, newis; 6545 const PetscInt *newRows; 6546 6547 PetscFunctionBegin; 6548 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6549 PetscValidType(mat, 1); 6550 if (numRows) PetscValidIntPointer(rows, 3); 6551 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6552 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6553 MatCheckPreallocated(mat, 1); 6554 6555 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6556 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6557 PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis)); 6558 PetscCall(ISGetIndices(newis, &newRows)); 6559 PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b); 6560 PetscCall(ISRestoreIndices(newis, &newRows)); 6561 PetscCall(ISDestroy(&newis)); 6562 PetscCall(ISDestroy(&is)); 6563 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6564 PetscFunctionReturn(PETSC_SUCCESS); 6565 } 6566 6567 /*@ 6568 MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal) 6569 of a set of rows and columns of a matrix; using local numbering of rows. 6570 6571 Collective 6572 6573 Input Parameters: 6574 + mat - the matrix 6575 . is - index set of rows to remove 6576 . diag - value put in all diagonals of eliminated rows 6577 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6578 - b - optional vector of right hand side, that will be adjusted by provided solution 6579 6580 Level: intermediate 6581 6582 Notes: 6583 Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the 6584 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6585 6586 See `MatZeroRowsColumns()` for details on how this routine operates. 6587 6588 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6589 `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6590 @*/ 6591 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6592 { 6593 PetscInt numRows; 6594 const PetscInt *rows; 6595 6596 PetscFunctionBegin; 6597 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6598 PetscValidType(mat, 1); 6599 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6600 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6601 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6602 MatCheckPreallocated(mat, 1); 6603 6604 PetscCall(ISGetLocalSize(is, &numRows)); 6605 PetscCall(ISGetIndices(is, &rows)); 6606 PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b)); 6607 PetscCall(ISRestoreIndices(is, &rows)); 6608 PetscFunctionReturn(PETSC_SUCCESS); 6609 } 6610 6611 /*@C 6612 MatGetSize - Returns the numbers of rows and columns in a matrix. 6613 6614 Not Collective 6615 6616 Input Parameter: 6617 . mat - the matrix 6618 6619 Output Parameters: 6620 + m - the number of global rows 6621 - n - the number of global columns 6622 6623 Level: beginner 6624 6625 Note: 6626 Both output parameters can be `NULL` on input. 6627 6628 .seealso: [](chapter_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()` 6629 @*/ 6630 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n) 6631 { 6632 PetscFunctionBegin; 6633 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6634 if (m) *m = mat->rmap->N; 6635 if (n) *n = mat->cmap->N; 6636 PetscFunctionReturn(PETSC_SUCCESS); 6637 } 6638 6639 /*@C 6640 MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns 6641 of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`. 6642 6643 Not Collective 6644 6645 Input Parameter: 6646 . mat - the matrix 6647 6648 Output Parameters: 6649 + m - the number of local rows, use `NULL` to not obtain this value 6650 - n - the number of local columns, use `NULL` to not obtain this value 6651 6652 Level: beginner 6653 6654 .seealso: [](chapter_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()` 6655 @*/ 6656 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n) 6657 { 6658 PetscFunctionBegin; 6659 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6660 if (m) PetscValidIntPointer(m, 2); 6661 if (n) PetscValidIntPointer(n, 3); 6662 if (m) *m = mat->rmap->n; 6663 if (n) *n = mat->cmap->n; 6664 PetscFunctionReturn(PETSC_SUCCESS); 6665 } 6666 6667 /*@C 6668 MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by 6669 this processor. (The columns of the "diagonal block" for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts. 6670 6671 Not Collective, unless matrix has not been allocated, then collective 6672 6673 Input Parameter: 6674 . mat - the matrix 6675 6676 Output Parameters: 6677 + m - the global index of the first local column, use `NULL` to not obtain this value 6678 - n - one more than the global index of the last local column, use `NULL` to not obtain this value 6679 6680 Level: developer 6681 6682 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout` 6683 @*/ 6684 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n) 6685 { 6686 PetscFunctionBegin; 6687 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6688 PetscValidType(mat, 1); 6689 if (m) PetscValidIntPointer(m, 2); 6690 if (n) PetscValidIntPointer(n, 3); 6691 MatCheckPreallocated(mat, 1); 6692 if (m) *m = mat->cmap->rstart; 6693 if (n) *n = mat->cmap->rend; 6694 PetscFunctionReturn(PETSC_SUCCESS); 6695 } 6696 6697 /*@C 6698 MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6699 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 6700 vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts 6701 6702 Not Collective 6703 6704 Input Parameter: 6705 . mat - the matrix 6706 6707 Output Parameters: 6708 + m - the global index of the first local row, use `NULL` to not obtain this value 6709 - n - one more than the global index of the last local row, use `NULL` to not obtain this value 6710 6711 Level: beginner 6712 6713 Note: 6714 This function requires that the matrix be preallocated. If you have not preallocated, consider using 6715 `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N) 6716 and then `MPI_Scan()` to calculate prefix sums of the local sizes. 6717 6718 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, 6719 `PetscLayout` 6720 @*/ 6721 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n) 6722 { 6723 PetscFunctionBegin; 6724 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6725 PetscValidType(mat, 1); 6726 if (m) PetscValidIntPointer(m, 2); 6727 if (n) PetscValidIntPointer(n, 3); 6728 MatCheckPreallocated(mat, 1); 6729 if (m) *m = mat->rmap->rstart; 6730 if (n) *n = mat->rmap->rend; 6731 PetscFunctionReturn(PETSC_SUCCESS); 6732 } 6733 6734 /*@C 6735 MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6736 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 6737 vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts 6738 6739 Not Collective, unless matrix has not been allocated 6740 6741 Input Parameter: 6742 . mat - the matrix 6743 6744 Output Parameter: 6745 . ranges - start of each processors portion plus one more than the total length at the end 6746 6747 Level: beginner 6748 6749 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout` 6750 @*/ 6751 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges) 6752 { 6753 PetscFunctionBegin; 6754 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6755 PetscValidType(mat, 1); 6756 MatCheckPreallocated(mat, 1); 6757 PetscCall(PetscLayoutGetRanges(mat->rmap, ranges)); 6758 PetscFunctionReturn(PETSC_SUCCESS); 6759 } 6760 6761 /*@C 6762 MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by 6763 each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts. 6764 6765 Not Collective, unless matrix has not been allocated 6766 6767 Input Parameter: 6768 . mat - the matrix 6769 6770 Output Parameter: 6771 . ranges - start of each processors portion plus one more then the total length at the end 6772 6773 Level: beginner 6774 6775 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()` 6776 @*/ 6777 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges) 6778 { 6779 PetscFunctionBegin; 6780 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6781 PetscValidType(mat, 1); 6782 MatCheckPreallocated(mat, 1); 6783 PetscCall(PetscLayoutGetRanges(mat->cmap, ranges)); 6784 PetscFunctionReturn(PETSC_SUCCESS); 6785 } 6786 6787 /*@C 6788 MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this 6789 corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership 6790 is more complicated. See :any:`<sec_matlayout>` for details on matrix layouts. 6791 6792 Not Collective 6793 6794 Input Parameter: 6795 . A - matrix 6796 6797 Output Parameters: 6798 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value 6799 - cols - columns in which this process owns elements, use `NULL` to not obtain this value 6800 6801 Level: intermediate 6802 6803 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK`` 6804 @*/ 6805 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols) 6806 { 6807 PetscErrorCode (*f)(Mat, IS *, IS *); 6808 6809 PetscFunctionBegin; 6810 MatCheckPreallocated(A, 1); 6811 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f)); 6812 if (f) { 6813 PetscCall((*f)(A, rows, cols)); 6814 } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */ 6815 if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows)); 6816 if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols)); 6817 } 6818 PetscFunctionReturn(PETSC_SUCCESS); 6819 } 6820 6821 /*@C 6822 MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()` 6823 Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()` 6824 to complete the factorization. 6825 6826 Collective 6827 6828 Input Parameters: 6829 + fact - the factorized matrix obtained with `MatGetFactor()` 6830 . mat - the matrix 6831 . row - row permutation 6832 . col - column permutation 6833 - info - structure containing 6834 .vb 6835 levels - number of levels of fill. 6836 expected fill - as ratio of original fill. 6837 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 6838 missing diagonal entries) 6839 .ve 6840 6841 Level: developer 6842 6843 Notes: 6844 See [Matrix Factorization](sec_matfactor) for additional information. 6845 6846 Most users should employ the `KSP` interface for linear solvers 6847 instead of working directly with matrix algebra routines such as this. 6848 See, e.g., `KSPCreate()`. 6849 6850 Uses the definition of level of fill as in Y. Saad, 2003 6851 6852 Developer Note: 6853 The Fortran interface is not autogenerated as the 6854 interface definition cannot be generated correctly [due to `MatFactorInfo`] 6855 6856 References: 6857 . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003 6858 6859 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 6860 `MatGetOrdering()`, `MatFactorInfo` 6861 @*/ 6862 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 6863 { 6864 PetscFunctionBegin; 6865 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 6866 PetscValidType(mat, 2); 6867 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 6868 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 6869 PetscValidPointer(info, 5); 6870 PetscValidPointer(fact, 1); 6871 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels); 6872 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 6873 if (!fact->ops->ilufactorsymbolic) { 6874 MatSolverType stype; 6875 PetscCall(MatFactorGetSolverType(fact, &stype)); 6876 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ILU using solver type %s", ((PetscObject)mat)->type_name, stype); 6877 } 6878 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6879 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6880 MatCheckPreallocated(mat, 2); 6881 6882 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0)); 6883 PetscCall((fact->ops->ilufactorsymbolic)(fact, mat, row, col, info)); 6884 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0)); 6885 PetscFunctionReturn(PETSC_SUCCESS); 6886 } 6887 6888 /*@C 6889 MatICCFactorSymbolic - Performs symbolic incomplete 6890 Cholesky factorization for a symmetric matrix. Use 6891 `MatCholeskyFactorNumeric()` to complete the factorization. 6892 6893 Collective 6894 6895 Input Parameters: 6896 + fact - the factorized matrix obtained with `MatGetFactor()` 6897 . mat - the matrix to be factored 6898 . perm - row and column permutation 6899 - info - structure containing 6900 .vb 6901 levels - number of levels of fill. 6902 expected fill - as ratio of original fill. 6903 .ve 6904 6905 Level: developer 6906 6907 Notes: 6908 Most users should employ the `KSP` interface for linear solvers 6909 instead of working directly with matrix algebra routines such as this. 6910 See, e.g., `KSPCreate()`. 6911 6912 This uses the definition of level of fill as in Y. Saad, 2003 6913 6914 Developer Note: 6915 The Fortran interface is not autogenerated as the 6916 interface definition cannot be generated correctly [due to `MatFactorInfo`] 6917 6918 References: 6919 . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003 6920 6921 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 6922 @*/ 6923 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 6924 { 6925 PetscFunctionBegin; 6926 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 6927 PetscValidType(mat, 2); 6928 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 6929 PetscValidPointer(info, 4); 6930 PetscValidPointer(fact, 1); 6931 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6932 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels); 6933 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 6934 if (!(fact)->ops->iccfactorsymbolic) { 6935 MatSolverType stype; 6936 PetscCall(MatFactorGetSolverType(fact, &stype)); 6937 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ICC using solver type %s", ((PetscObject)mat)->type_name, stype); 6938 } 6939 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6940 MatCheckPreallocated(mat, 2); 6941 6942 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 6943 PetscCall((fact->ops->iccfactorsymbolic)(fact, mat, perm, info)); 6944 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 6945 PetscFunctionReturn(PETSC_SUCCESS); 6946 } 6947 6948 /*@C 6949 MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat 6950 points to an array of valid matrices, they may be reused to store the new 6951 submatrices. 6952 6953 Collective 6954 6955 Input Parameters: 6956 + mat - the matrix 6957 . n - the number of submatrixes to be extracted (on this processor, may be zero) 6958 . irow - index set of rows to extract 6959 . icol - index set of columns to extract 6960 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 6961 6962 Output Parameter: 6963 . submat - the array of submatrices 6964 6965 Level: advanced 6966 6967 Notes: 6968 `MatCreateSubMatrices()` can extract ONLY sequential submatrices 6969 (from both sequential and parallel matrices). Use `MatCreateSubMatrix()` 6970 to extract a parallel submatrix. 6971 6972 Some matrix types place restrictions on the row and column 6973 indices, such as that they be sorted or that they be equal to each other. 6974 6975 The index sets may not have duplicate entries. 6976 6977 When extracting submatrices from a parallel matrix, each processor can 6978 form a different submatrix by setting the rows and columns of its 6979 individual index sets according to the local submatrix desired. 6980 6981 When finished using the submatrices, the user should destroy 6982 them with `MatDestroySubMatrices()`. 6983 6984 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 6985 original matrix has not changed from that last call to `MatCreateSubMatrices()`. 6986 6987 This routine creates the matrices in submat; you should NOT create them before 6988 calling it. It also allocates the array of matrix pointers submat. 6989 6990 For `MATBAIJ` matrices the index sets must respect the block structure, that is if they 6991 request one row/column in a block, they must request all rows/columns that are in 6992 that block. For example, if the block size is 2 you cannot request just row 0 and 6993 column 0. 6994 6995 Fortran Note: 6996 The Fortran interface is slightly different from that given below; it 6997 requires one to pass in as `submat` a `Mat` (integer) array of size at least n+1. 6998 6999 .seealso: [](chapter_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7000 @*/ 7001 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7002 { 7003 PetscInt i; 7004 PetscBool eq; 7005 7006 PetscFunctionBegin; 7007 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7008 PetscValidType(mat, 1); 7009 if (n) { 7010 PetscValidPointer(irow, 3); 7011 for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3); 7012 PetscValidPointer(icol, 4); 7013 for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4); 7014 } 7015 PetscValidPointer(submat, 6); 7016 if (n && scall == MAT_REUSE_MATRIX) { 7017 PetscValidPointer(*submat, 6); 7018 for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6); 7019 } 7020 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7021 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7022 MatCheckPreallocated(mat, 1); 7023 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7024 PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat); 7025 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7026 for (i = 0; i < n; i++) { 7027 (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */ 7028 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7029 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7030 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 7031 if (mat->boundtocpu && mat->bindingpropagates) { 7032 PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE)); 7033 PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE)); 7034 } 7035 #endif 7036 } 7037 PetscFunctionReturn(PETSC_SUCCESS); 7038 } 7039 7040 /*@C 7041 MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms). 7042 7043 Collective 7044 7045 Input Parameters: 7046 + mat - the matrix 7047 . n - the number of submatrixes to be extracted 7048 . irow - index set of rows to extract 7049 . icol - index set of columns to extract 7050 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7051 7052 Output Parameter: 7053 . submat - the array of submatrices 7054 7055 Level: advanced 7056 7057 Note: 7058 This is used by `PCGASM` 7059 7060 .seealso: [](chapter_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7061 @*/ 7062 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7063 { 7064 PetscInt i; 7065 PetscBool eq; 7066 7067 PetscFunctionBegin; 7068 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7069 PetscValidType(mat, 1); 7070 if (n) { 7071 PetscValidPointer(irow, 3); 7072 PetscValidHeaderSpecific(*irow, IS_CLASSID, 3); 7073 PetscValidPointer(icol, 4); 7074 PetscValidHeaderSpecific(*icol, IS_CLASSID, 4); 7075 } 7076 PetscValidPointer(submat, 6); 7077 if (n && scall == MAT_REUSE_MATRIX) { 7078 PetscValidPointer(*submat, 6); 7079 PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6); 7080 } 7081 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7082 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7083 MatCheckPreallocated(mat, 1); 7084 7085 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7086 PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat); 7087 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7088 for (i = 0; i < n; i++) { 7089 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7090 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7091 } 7092 PetscFunctionReturn(PETSC_SUCCESS); 7093 } 7094 7095 /*@C 7096 MatDestroyMatrices - Destroys an array of matrices. 7097 7098 Collective 7099 7100 Input Parameters: 7101 + n - the number of local matrices 7102 - mat - the matrices (this is a pointer to the array of matrices) 7103 7104 Level: advanced 7105 7106 Note: 7107 Frees not only the matrices, but also the array that contains the matrices 7108 7109 Fortran Note: 7110 This does not free the array. 7111 7112 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()` 7113 @*/ 7114 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[]) 7115 { 7116 PetscInt i; 7117 7118 PetscFunctionBegin; 7119 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7120 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7121 PetscValidPointer(mat, 2); 7122 7123 for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i])); 7124 7125 /* memory is allocated even if n = 0 */ 7126 PetscCall(PetscFree(*mat)); 7127 PetscFunctionReturn(PETSC_SUCCESS); 7128 } 7129 7130 /*@C 7131 MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`. 7132 7133 Collective 7134 7135 Input Parameters: 7136 + n - the number of local matrices 7137 - mat - the matrices (this is a pointer to the array of matrices, just to match the calling 7138 sequence of `MatCreateSubMatrices()`) 7139 7140 Level: advanced 7141 7142 Note: 7143 Frees not only the matrices, but also the array that contains the matrices 7144 7145 Fortran Note: 7146 This does not free the array. 7147 7148 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7149 @*/ 7150 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[]) 7151 { 7152 Mat mat0; 7153 7154 PetscFunctionBegin; 7155 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7156 /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */ 7157 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7158 PetscValidPointer(mat, 2); 7159 7160 mat0 = (*mat)[0]; 7161 if (mat0 && mat0->ops->destroysubmatrices) { 7162 PetscCall((mat0->ops->destroysubmatrices)(n, mat)); 7163 } else { 7164 PetscCall(MatDestroyMatrices(n, mat)); 7165 } 7166 PetscFunctionReturn(PETSC_SUCCESS); 7167 } 7168 7169 /*@C 7170 MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process 7171 7172 Collective 7173 7174 Input Parameter: 7175 . mat - the matrix 7176 7177 Output Parameter: 7178 . matstruct - the sequential matrix with the nonzero structure of mat 7179 7180 Level: developer 7181 7182 .seealso: [](chapter_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7183 @*/ 7184 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct) 7185 { 7186 PetscFunctionBegin; 7187 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7188 PetscValidPointer(matstruct, 2); 7189 7190 PetscValidType(mat, 1); 7191 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7192 MatCheckPreallocated(mat, 1); 7193 7194 PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7195 PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct); 7196 PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7197 PetscFunctionReturn(PETSC_SUCCESS); 7198 } 7199 7200 /*@C 7201 MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`. 7202 7203 Collective 7204 7205 Input Parameter: 7206 . mat - the matrix (this is a pointer to the array of matrices, just to match the calling 7207 sequence of `MatGetSequentialNonzeroStructure()`) 7208 7209 Level: advanced 7210 7211 Note: 7212 Frees not only the matrices, but also the array that contains the matrices 7213 7214 .seealso: [](chapter_matrices), `Mat`, `MatGetSeqNonzeroStructure()` 7215 @*/ 7216 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat) 7217 { 7218 PetscFunctionBegin; 7219 PetscValidPointer(mat, 1); 7220 PetscCall(MatDestroy(mat)); 7221 PetscFunctionReturn(PETSC_SUCCESS); 7222 } 7223 7224 /*@ 7225 MatIncreaseOverlap - Given a set of submatrices indicated by index sets, 7226 replaces the index sets by larger ones that represent submatrices with 7227 additional overlap. 7228 7229 Collective 7230 7231 Input Parameters: 7232 + mat - the matrix 7233 . n - the number of index sets 7234 . is - the array of index sets (these index sets will changed during the call) 7235 - ov - the additional overlap requested 7236 7237 Options Database Key: 7238 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7239 7240 Level: developer 7241 7242 Note: 7243 The computed overlap preserves the matrix block sizes when the blocks are square. 7244 That is: if a matrix nonzero for a given block would increase the overlap all columns associated with 7245 that block are included in the overlap regardless of whether each specific column would increase the overlap. 7246 7247 .seealso: [](chapter_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()` 7248 @*/ 7249 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov) 7250 { 7251 PetscInt i, bs, cbs; 7252 7253 PetscFunctionBegin; 7254 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7255 PetscValidType(mat, 1); 7256 PetscValidLogicalCollectiveInt(mat, n, 2); 7257 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7258 if (n) { 7259 PetscValidPointer(is, 3); 7260 for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3); 7261 } 7262 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7263 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7264 MatCheckPreallocated(mat, 1); 7265 7266 if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS); 7267 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7268 PetscUseTypeMethod(mat, increaseoverlap, n, is, ov); 7269 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7270 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 7271 if (bs == cbs) { 7272 for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs)); 7273 } 7274 PetscFunctionReturn(PETSC_SUCCESS); 7275 } 7276 7277 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt); 7278 7279 /*@ 7280 MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across 7281 a sub communicator, replaces the index sets by larger ones that represent submatrices with 7282 additional overlap. 7283 7284 Collective 7285 7286 Input Parameters: 7287 + mat - the matrix 7288 . n - the number of index sets 7289 . is - the array of index sets (these index sets will changed during the call) 7290 - ov - the additional overlap requested 7291 7292 ` Options Database Key: 7293 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7294 7295 Level: developer 7296 7297 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()` 7298 @*/ 7299 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov) 7300 { 7301 PetscInt i; 7302 7303 PetscFunctionBegin; 7304 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7305 PetscValidType(mat, 1); 7306 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7307 if (n) { 7308 PetscValidPointer(is, 3); 7309 PetscValidHeaderSpecific(*is, IS_CLASSID, 3); 7310 } 7311 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7312 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7313 MatCheckPreallocated(mat, 1); 7314 if (!ov) PetscFunctionReturn(PETSC_SUCCESS); 7315 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7316 for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov)); 7317 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7318 PetscFunctionReturn(PETSC_SUCCESS); 7319 } 7320 7321 /*@ 7322 MatGetBlockSize - Returns the matrix block size. 7323 7324 Not Collective 7325 7326 Input Parameter: 7327 . mat - the matrix 7328 7329 Output Parameter: 7330 . bs - block size 7331 7332 Level: intermediate 7333 7334 Notes: 7335 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7336 7337 If the block size has not been set yet this routine returns 1. 7338 7339 .seealso: [](chapter_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()` 7340 @*/ 7341 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs) 7342 { 7343 PetscFunctionBegin; 7344 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7345 PetscValidIntPointer(bs, 2); 7346 *bs = PetscAbs(mat->rmap->bs); 7347 PetscFunctionReturn(PETSC_SUCCESS); 7348 } 7349 7350 /*@ 7351 MatGetBlockSizes - Returns the matrix block row and column sizes. 7352 7353 Not Collective 7354 7355 Input Parameter: 7356 . mat - the matrix 7357 7358 Output Parameters: 7359 + rbs - row block size 7360 - cbs - column block size 7361 7362 Level: intermediate 7363 7364 Notes: 7365 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7366 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7367 7368 If a block size has not been set yet this routine returns 1. 7369 7370 .seealso: [](chapter_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()` 7371 @*/ 7372 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs) 7373 { 7374 PetscFunctionBegin; 7375 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7376 if (rbs) PetscValidIntPointer(rbs, 2); 7377 if (cbs) PetscValidIntPointer(cbs, 3); 7378 if (rbs) *rbs = PetscAbs(mat->rmap->bs); 7379 if (cbs) *cbs = PetscAbs(mat->cmap->bs); 7380 PetscFunctionReturn(PETSC_SUCCESS); 7381 } 7382 7383 /*@ 7384 MatSetBlockSize - Sets the matrix block size. 7385 7386 Logically Collective 7387 7388 Input Parameters: 7389 + mat - the matrix 7390 - bs - block size 7391 7392 Level: intermediate 7393 7394 Notes: 7395 Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix. 7396 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7397 7398 For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size 7399 is compatible with the matrix local sizes. 7400 7401 .seealso: [](chapter_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()` 7402 @*/ 7403 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs) 7404 { 7405 PetscFunctionBegin; 7406 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7407 PetscValidLogicalCollectiveInt(mat, bs, 2); 7408 PetscCall(MatSetBlockSizes(mat, bs, bs)); 7409 PetscFunctionReturn(PETSC_SUCCESS); 7410 } 7411 7412 typedef struct { 7413 PetscInt n; 7414 IS *is; 7415 Mat *mat; 7416 PetscObjectState nonzerostate; 7417 Mat C; 7418 } EnvelopeData; 7419 7420 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata) 7421 { 7422 for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i])); 7423 PetscCall(PetscFree(edata->is)); 7424 PetscCall(PetscFree(edata)); 7425 return PETSC_SUCCESS; 7426 } 7427 7428 /* 7429 MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores 7430 the sizes of these blocks in the matrix. An individual block may lie over several processes. 7431 7432 Collective 7433 7434 Input Parameter: 7435 . mat - the matrix 7436 7437 Notes: 7438 There can be zeros within the blocks 7439 7440 The blocks can overlap between processes, including laying on more than two processes 7441 7442 .seealso: [](chapter_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()` 7443 */ 7444 static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat) 7445 { 7446 PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend; 7447 PetscInt *diag, *odiag, sc; 7448 VecScatter scatter; 7449 PetscScalar *seqv; 7450 const PetscScalar *parv; 7451 const PetscInt *ia, *ja; 7452 PetscBool set, flag, done; 7453 Mat AA = mat, A; 7454 MPI_Comm comm; 7455 PetscMPIInt rank, size, tag; 7456 MPI_Status status; 7457 PetscContainer container; 7458 EnvelopeData *edata; 7459 Vec seq, par; 7460 IS isglobal; 7461 7462 PetscFunctionBegin; 7463 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7464 PetscCall(MatIsSymmetricKnown(mat, &set, &flag)); 7465 if (!set || !flag) { 7466 /* TOO: only needs nonzero structure of transpose */ 7467 PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA)); 7468 PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN)); 7469 } 7470 PetscCall(MatAIJGetLocalMat(AA, &A)); 7471 PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7472 PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix"); 7473 7474 PetscCall(MatGetLocalSize(mat, &n, NULL)); 7475 PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag)); 7476 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 7477 PetscCallMPI(MPI_Comm_size(comm, &size)); 7478 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7479 7480 PetscCall(PetscMalloc2(n, &sizes, n, &starts)); 7481 7482 if (rank > 0) { 7483 PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7484 PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7485 } 7486 PetscCall(MatGetOwnershipRange(mat, &rstart, NULL)); 7487 for (i = 0; i < n; i++) { 7488 env = PetscMax(env, ja[ia[i + 1] - 1]); 7489 II = rstart + i; 7490 if (env == II) { 7491 starts[lblocks] = tbs; 7492 sizes[lblocks++] = 1 + II - tbs; 7493 tbs = 1 + II; 7494 } 7495 } 7496 if (rank < size - 1) { 7497 PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm)); 7498 PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm)); 7499 } 7500 7501 PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7502 if (!set || !flag) PetscCall(MatDestroy(&AA)); 7503 PetscCall(MatDestroy(&A)); 7504 7505 PetscCall(PetscNew(&edata)); 7506 PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate)); 7507 edata->n = lblocks; 7508 /* create IS needed for extracting blocks from the original matrix */ 7509 PetscCall(PetscMalloc1(lblocks, &edata->is)); 7510 for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i])); 7511 7512 /* Create the resulting inverse matrix structure with preallocation information */ 7513 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C)); 7514 PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 7515 PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat)); 7516 PetscCall(MatSetType(edata->C, MATAIJ)); 7517 7518 /* Communicate the start and end of each row, from each block to the correct rank */ 7519 /* TODO: Use PetscSF instead of VecScatter */ 7520 for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i]; 7521 PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq)); 7522 PetscCall(VecGetArrayWrite(seq, &seqv)); 7523 for (PetscInt i = 0; i < lblocks; i++) { 7524 for (PetscInt j = 0; j < sizes[i]; j++) { 7525 seqv[cnt] = starts[i]; 7526 seqv[cnt + 1] = starts[i] + sizes[i]; 7527 cnt += 2; 7528 } 7529 } 7530 PetscCall(VecRestoreArrayWrite(seq, &seqv)); 7531 PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 7532 sc -= cnt; 7533 PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par)); 7534 PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal)); 7535 PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter)); 7536 PetscCall(ISDestroy(&isglobal)); 7537 PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7538 PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7539 PetscCall(VecScatterDestroy(&scatter)); 7540 PetscCall(VecDestroy(&seq)); 7541 PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend)); 7542 PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag)); 7543 PetscCall(VecGetArrayRead(par, &parv)); 7544 cnt = 0; 7545 PetscCall(MatGetSize(mat, NULL, &n)); 7546 for (PetscInt i = 0; i < mat->rmap->n; i++) { 7547 PetscInt start, end, d = 0, od = 0; 7548 7549 start = (PetscInt)PetscRealPart(parv[cnt]); 7550 end = (PetscInt)PetscRealPart(parv[cnt + 1]); 7551 cnt += 2; 7552 7553 if (start < cstart) { 7554 od += cstart - start + n - cend; 7555 d += cend - cstart; 7556 } else if (start < cend) { 7557 od += n - cend; 7558 d += cend - start; 7559 } else od += n - start; 7560 if (end <= cstart) { 7561 od -= cstart - end + n - cend; 7562 d -= cend - cstart; 7563 } else if (end < cend) { 7564 od -= n - cend; 7565 d -= cend - end; 7566 } else od -= n - end; 7567 7568 odiag[i] = od; 7569 diag[i] = d; 7570 } 7571 PetscCall(VecRestoreArrayRead(par, &parv)); 7572 PetscCall(VecDestroy(&par)); 7573 PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL)); 7574 PetscCall(PetscFree2(diag, odiag)); 7575 PetscCall(PetscFree2(sizes, starts)); 7576 7577 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container)); 7578 PetscCall(PetscContainerSetPointer(container, edata)); 7579 PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy)); 7580 PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container)); 7581 PetscCall(PetscObjectDereference((PetscObject)container)); 7582 PetscFunctionReturn(PETSC_SUCCESS); 7583 } 7584 7585 /*@ 7586 MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A 7587 7588 Collective 7589 7590 Input Parameters: 7591 + A - the matrix 7592 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine 7593 7594 Output Parameter: 7595 . C - matrix with inverted block diagonal of `A` 7596 7597 Level: advanced 7598 7599 Note: 7600 For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal. 7601 7602 .seealso: [](chapter_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()` 7603 @*/ 7604 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C) 7605 { 7606 PetscContainer container; 7607 EnvelopeData *edata; 7608 PetscObjectState nonzerostate; 7609 7610 PetscFunctionBegin; 7611 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7612 if (!container) { 7613 PetscCall(MatComputeVariableBlockEnvelope(A)); 7614 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7615 } 7616 PetscCall(PetscContainerGetPointer(container, (void **)&edata)); 7617 PetscCall(MatGetNonzeroState(A, &nonzerostate)); 7618 PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure"); 7619 PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output"); 7620 7621 PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat)); 7622 *C = edata->C; 7623 7624 for (PetscInt i = 0; i < edata->n; i++) { 7625 Mat D; 7626 PetscScalar *dvalues; 7627 7628 PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D)); 7629 PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE)); 7630 PetscCall(MatSeqDenseInvert(D)); 7631 PetscCall(MatDenseGetArray(D, &dvalues)); 7632 PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES)); 7633 PetscCall(MatDestroy(&D)); 7634 } 7635 PetscCall(MatDestroySubMatrices(edata->n, &edata->mat)); 7636 PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY)); 7637 PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY)); 7638 PetscFunctionReturn(PETSC_SUCCESS); 7639 } 7640 7641 /*@ 7642 MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size 7643 7644 Logically Collective 7645 7646 Input Parameters: 7647 + mat - the matrix 7648 . nblocks - the number of blocks on this process, each block can only exist on a single process 7649 - bsizes - the block sizes 7650 7651 Level: intermediate 7652 7653 Notes: 7654 Currently used by `PCVPBJACOBI` for `MATAIJ` matrices 7655 7656 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. 7657 7658 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, 7659 `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI` 7660 @*/ 7661 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes) 7662 { 7663 PetscInt i, ncnt = 0, nlocal; 7664 7665 PetscFunctionBegin; 7666 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7667 PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero"); 7668 PetscCall(MatGetLocalSize(mat, &nlocal, NULL)); 7669 for (i = 0; i < nblocks; i++) ncnt += bsizes[i]; 7670 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); 7671 PetscCall(PetscFree(mat->bsizes)); 7672 mat->nblocks = nblocks; 7673 PetscCall(PetscMalloc1(nblocks, &mat->bsizes)); 7674 PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks)); 7675 PetscFunctionReturn(PETSC_SUCCESS); 7676 } 7677 7678 /*@C 7679 MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size 7680 7681 Logically Collective; No Fortran Support 7682 7683 Input Parameter: 7684 . mat - the matrix 7685 7686 Output Parameters: 7687 + nblocks - the number of blocks on this process 7688 - bsizes - the block sizes 7689 7690 Level: intermediate 7691 7692 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()` 7693 @*/ 7694 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes) 7695 { 7696 PetscFunctionBegin; 7697 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7698 *nblocks = mat->nblocks; 7699 *bsizes = mat->bsizes; 7700 PetscFunctionReturn(PETSC_SUCCESS); 7701 } 7702 7703 /*@ 7704 MatSetBlockSizes - Sets the matrix block row and column sizes. 7705 7706 Logically Collective 7707 7708 Input Parameters: 7709 + mat - the matrix 7710 . rbs - row block size 7711 - cbs - column block size 7712 7713 Level: intermediate 7714 7715 Notes: 7716 Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix. 7717 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7718 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7719 7720 For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes 7721 are compatible with the matrix local sizes. 7722 7723 The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`. 7724 7725 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()` 7726 @*/ 7727 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs) 7728 { 7729 PetscFunctionBegin; 7730 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7731 PetscValidLogicalCollectiveInt(mat, rbs, 2); 7732 PetscValidLogicalCollectiveInt(mat, cbs, 3); 7733 PetscTryTypeMethod(mat, setblocksizes, rbs, cbs); 7734 if (mat->rmap->refcnt) { 7735 ISLocalToGlobalMapping l2g = NULL; 7736 PetscLayout nmap = NULL; 7737 7738 PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap)); 7739 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g)); 7740 PetscCall(PetscLayoutDestroy(&mat->rmap)); 7741 mat->rmap = nmap; 7742 mat->rmap->mapping = l2g; 7743 } 7744 if (mat->cmap->refcnt) { 7745 ISLocalToGlobalMapping l2g = NULL; 7746 PetscLayout nmap = NULL; 7747 7748 PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap)); 7749 if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g)); 7750 PetscCall(PetscLayoutDestroy(&mat->cmap)); 7751 mat->cmap = nmap; 7752 mat->cmap->mapping = l2g; 7753 } 7754 PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs)); 7755 PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs)); 7756 PetscFunctionReturn(PETSC_SUCCESS); 7757 } 7758 7759 /*@ 7760 MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices 7761 7762 Logically Collective 7763 7764 Input Parameters: 7765 + mat - the matrix 7766 . fromRow - matrix from which to copy row block size 7767 - fromCol - matrix from which to copy column block size (can be same as fromRow) 7768 7769 Level: developer 7770 7771 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()` 7772 @*/ 7773 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol) 7774 { 7775 PetscFunctionBegin; 7776 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7777 PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2); 7778 PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3); 7779 if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs)); 7780 if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs)); 7781 PetscFunctionReturn(PETSC_SUCCESS); 7782 } 7783 7784 /*@ 7785 MatResidual - Default routine to calculate the residual r = b - Ax 7786 7787 Collective 7788 7789 Input Parameters: 7790 + mat - the matrix 7791 . b - the right-hand-side 7792 - x - the approximate solution 7793 7794 Output Parameter: 7795 . r - location to store the residual 7796 7797 Level: developer 7798 7799 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()` 7800 @*/ 7801 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r) 7802 { 7803 PetscFunctionBegin; 7804 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7805 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 7806 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 7807 PetscValidHeaderSpecific(r, VEC_CLASSID, 4); 7808 PetscValidType(mat, 1); 7809 MatCheckPreallocated(mat, 1); 7810 PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0)); 7811 if (!mat->ops->residual) { 7812 PetscCall(MatMult(mat, x, r)); 7813 PetscCall(VecAYPX(r, -1.0, b)); 7814 } else { 7815 PetscUseTypeMethod(mat, residual, b, x, r); 7816 } 7817 PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0)); 7818 PetscFunctionReturn(PETSC_SUCCESS); 7819 } 7820 7821 /*MC 7822 MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix 7823 7824 Synopsis: 7825 MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 7826 7827 Not Collective 7828 7829 Input Parameters: 7830 + A - the matrix 7831 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7832 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7833 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7834 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7835 always used. 7836 7837 Output Parameters: 7838 + n - number of local rows in the (possibly compressed) matrix 7839 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 7840 . ja - the column indices 7841 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7842 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7843 7844 Level: developer 7845 7846 Note: 7847 Use `MatRestoreRowIJF90()` when you no longer need access to the data 7848 7849 .seealso: [](chapter_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()` 7850 M*/ 7851 7852 /*MC 7853 MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()` 7854 7855 Synopsis: 7856 MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 7857 7858 Not Collective 7859 7860 Input Parameters: 7861 + A - the matrix 7862 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7863 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7864 inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7865 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7866 always used. 7867 . n - number of local rows in the (possibly compressed) matrix 7868 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 7869 . ja - the column indices 7870 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7871 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7872 7873 Level: developer 7874 7875 .seealso: [](chapter_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()` 7876 M*/ 7877 7878 /*@C 7879 MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix 7880 7881 Collective 7882 7883 Input Parameters: 7884 + mat - the matrix 7885 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7886 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7887 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7888 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7889 always used. 7890 7891 Output Parameters: 7892 + n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed 7893 . 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 7894 . ja - the column indices, use `NULL` if not needed 7895 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7896 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7897 7898 Level: developer 7899 7900 Notes: 7901 You CANNOT change any of the ia[] or ja[] values. 7902 7903 Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values. 7904 7905 Fortran Notes: 7906 Use 7907 .vb 7908 PetscInt, pointer :: ia(:),ja(:) 7909 call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr) 7910 ! Access the ith and jth entries via ia(i) and ja(j) 7911 .ve 7912 `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()` 7913 7914 .seealso: [](chapter_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()` 7915 @*/ 7916 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7917 { 7918 PetscFunctionBegin; 7919 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7920 PetscValidType(mat, 1); 7921 if (n) PetscValidIntPointer(n, 5); 7922 if (ia) PetscValidPointer(ia, 6); 7923 if (ja) PetscValidPointer(ja, 7); 7924 if (done) PetscValidBoolPointer(done, 8); 7925 MatCheckPreallocated(mat, 1); 7926 if (!mat->ops->getrowij && done) *done = PETSC_FALSE; 7927 else { 7928 if (done) *done = PETSC_TRUE; 7929 PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0)); 7930 PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done); 7931 PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0)); 7932 } 7933 PetscFunctionReturn(PETSC_SUCCESS); 7934 } 7935 7936 /*@C 7937 MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices. 7938 7939 Collective 7940 7941 Input Parameters: 7942 + mat - the matrix 7943 . shift - 1 or zero indicating we want the indices starting at 0 or 1 7944 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be 7945 symmetrized 7946 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7947 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7948 always used. 7949 . n - number of columns in the (possibly compressed) matrix 7950 . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix 7951 - ja - the row indices 7952 7953 Output Parameter: 7954 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned 7955 7956 Level: developer 7957 7958 .seealso: [](chapter_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 7959 @*/ 7960 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7961 { 7962 PetscFunctionBegin; 7963 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7964 PetscValidType(mat, 1); 7965 PetscValidIntPointer(n, 5); 7966 if (ia) PetscValidPointer(ia, 6); 7967 if (ja) PetscValidPointer(ja, 7); 7968 PetscValidBoolPointer(done, 8); 7969 MatCheckPreallocated(mat, 1); 7970 if (!mat->ops->getcolumnij) *done = PETSC_FALSE; 7971 else { 7972 *done = PETSC_TRUE; 7973 PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 7974 } 7975 PetscFunctionReturn(PETSC_SUCCESS); 7976 } 7977 7978 /*@C 7979 MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`. 7980 7981 Collective 7982 7983 Input Parameters: 7984 + mat - the matrix 7985 . shift - 1 or zero indicating we want the indices starting at 0 or 1 7986 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7987 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7988 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7989 always used. 7990 . n - size of (possibly compressed) matrix 7991 . ia - the row pointers 7992 - ja - the column indices 7993 7994 Output Parameter: 7995 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 7996 7997 Level: developer 7998 7999 Note: 8000 This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental 8001 us of the array after it has been restored. If you pass `NULL`, it will 8002 not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid. 8003 8004 Fortran Note: 8005 `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()` 8006 8007 .seealso: [](chapter_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()` 8008 @*/ 8009 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8010 { 8011 PetscFunctionBegin; 8012 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8013 PetscValidType(mat, 1); 8014 if (ia) PetscValidPointer(ia, 6); 8015 if (ja) PetscValidPointer(ja, 7); 8016 if (done) PetscValidBoolPointer(done, 8); 8017 MatCheckPreallocated(mat, 1); 8018 8019 if (!mat->ops->restorerowij && done) *done = PETSC_FALSE; 8020 else { 8021 if (done) *done = PETSC_TRUE; 8022 PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8023 if (n) *n = 0; 8024 if (ia) *ia = NULL; 8025 if (ja) *ja = NULL; 8026 } 8027 PetscFunctionReturn(PETSC_SUCCESS); 8028 } 8029 8030 /*@C 8031 MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`. 8032 8033 Collective 8034 8035 Input Parameters: 8036 + mat - the matrix 8037 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8038 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8039 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8040 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8041 always used. 8042 8043 Output Parameters: 8044 + n - size of (possibly compressed) matrix 8045 . ia - the column pointers 8046 . ja - the row indices 8047 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8048 8049 Level: developer 8050 8051 .seealso: [](chapter_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()` 8052 @*/ 8053 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8054 { 8055 PetscFunctionBegin; 8056 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8057 PetscValidType(mat, 1); 8058 if (ia) PetscValidPointer(ia, 6); 8059 if (ja) PetscValidPointer(ja, 7); 8060 PetscValidBoolPointer(done, 8); 8061 MatCheckPreallocated(mat, 1); 8062 8063 if (!mat->ops->restorecolumnij) *done = PETSC_FALSE; 8064 else { 8065 *done = PETSC_TRUE; 8066 PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8067 if (n) *n = 0; 8068 if (ia) *ia = NULL; 8069 if (ja) *ja = NULL; 8070 } 8071 PetscFunctionReturn(PETSC_SUCCESS); 8072 } 8073 8074 /*@C 8075 MatColoringPatch -Used inside matrix coloring routines that use `MatGetRowIJ()` and/or `MatGetColumnIJ()`. 8076 8077 Collective 8078 8079 Input Parameters: 8080 + mat - the matrix 8081 . ncolors - maximum color value 8082 . n - number of entries in colorarray 8083 - colorarray - array indicating color for each column 8084 8085 Output Parameter: 8086 . iscoloring - coloring generated using colorarray information 8087 8088 Level: developer 8089 8090 .seealso: [](chapter_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()` 8091 @*/ 8092 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring) 8093 { 8094 PetscFunctionBegin; 8095 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8096 PetscValidType(mat, 1); 8097 PetscValidIntPointer(colorarray, 4); 8098 PetscValidPointer(iscoloring, 5); 8099 MatCheckPreallocated(mat, 1); 8100 8101 if (!mat->ops->coloringpatch) { 8102 PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring)); 8103 } else { 8104 PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring); 8105 } 8106 PetscFunctionReturn(PETSC_SUCCESS); 8107 } 8108 8109 /*@ 8110 MatSetUnfactored - Resets a factored matrix to be treated as unfactored. 8111 8112 Logically Collective 8113 8114 Input Parameter: 8115 . mat - the factored matrix to be reset 8116 8117 Level: developer 8118 8119 Notes: 8120 This routine should be used only with factored matrices formed by in-place 8121 factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE` 8122 format). This option can save memory, for example, when solving nonlinear 8123 systems with a matrix-free Newton-Krylov method and a matrix-based, in-place 8124 ILU(0) preconditioner. 8125 8126 One can specify in-place ILU(0) factorization by calling 8127 .vb 8128 PCType(pc,PCILU); 8129 PCFactorSeUseInPlace(pc); 8130 .ve 8131 or by using the options -pc_type ilu -pc_factor_in_place 8132 8133 In-place factorization ILU(0) can also be used as a local 8134 solver for the blocks within the block Jacobi or additive Schwarz 8135 methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc 8136 for details on setting local solver options. 8137 8138 Most users should employ the `KSP` interface for linear solvers 8139 instead of working directly with matrix algebra routines such as this. 8140 See, e.g., `KSPCreate()`. 8141 8142 .seealso: [](chapter_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()` 8143 @*/ 8144 PetscErrorCode MatSetUnfactored(Mat mat) 8145 { 8146 PetscFunctionBegin; 8147 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8148 PetscValidType(mat, 1); 8149 MatCheckPreallocated(mat, 1); 8150 mat->factortype = MAT_FACTOR_NONE; 8151 if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS); 8152 PetscUseTypeMethod(mat, setunfactored); 8153 PetscFunctionReturn(PETSC_SUCCESS); 8154 } 8155 8156 /*MC 8157 MatDenseGetArrayF90 - Accesses a matrix array from Fortran 8158 8159 Synopsis: 8160 MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8161 8162 Not Collective 8163 8164 Input Parameter: 8165 . x - matrix 8166 8167 Output Parameters: 8168 + xx_v - the Fortran pointer to the array 8169 - ierr - error code 8170 8171 Example of Usage: 8172 .vb 8173 PetscScalar, pointer xx_v(:,:) 8174 .... 8175 call MatDenseGetArrayF90(x,xx_v,ierr) 8176 a = xx_v(3) 8177 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8178 .ve 8179 8180 Level: advanced 8181 8182 .seealso: [](chapter_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()` 8183 M*/ 8184 8185 /*MC 8186 MatDenseRestoreArrayF90 - Restores a matrix array that has been 8187 accessed with `MatDenseGetArrayF90()`. 8188 8189 Synopsis: 8190 MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8191 8192 Not Collective 8193 8194 Input Parameters: 8195 + x - matrix 8196 - xx_v - the Fortran90 pointer to the array 8197 8198 Output Parameter: 8199 . ierr - error code 8200 8201 Example of Usage: 8202 .vb 8203 PetscScalar, pointer xx_v(:,:) 8204 .... 8205 call MatDenseGetArrayF90(x,xx_v,ierr) 8206 a = xx_v(3) 8207 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8208 .ve 8209 8210 Level: advanced 8211 8212 .seealso: [](chapter_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()` 8213 M*/ 8214 8215 /*MC 8216 MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran. 8217 8218 Synopsis: 8219 MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8220 8221 Not Collective 8222 8223 Input Parameter: 8224 . x - matrix 8225 8226 Output Parameters: 8227 + xx_v - the Fortran pointer to the array 8228 - ierr - error code 8229 8230 Example of Usage: 8231 .vb 8232 PetscScalar, pointer xx_v(:) 8233 .... 8234 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8235 a = xx_v(3) 8236 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8237 .ve 8238 8239 Level: advanced 8240 8241 .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()` 8242 M*/ 8243 8244 /*MC 8245 MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been 8246 accessed with `MatSeqAIJGetArrayF90()`. 8247 8248 Synopsis: 8249 MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8250 8251 Not Collective 8252 8253 Input Parameters: 8254 + x - matrix 8255 - xx_v - the Fortran90 pointer to the array 8256 8257 Output Parameter: 8258 . ierr - error code 8259 8260 Example of Usage: 8261 .vb 8262 PetscScalar, pointer xx_v(:) 8263 .... 8264 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8265 a = xx_v(3) 8266 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8267 .ve 8268 8269 Level: advanced 8270 8271 .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()` 8272 M*/ 8273 8274 /*@ 8275 MatCreateSubMatrix - Gets a single submatrix on the same number of processors 8276 as the original matrix. 8277 8278 Collective 8279 8280 Input Parameters: 8281 + mat - the original matrix 8282 . isrow - parallel `IS` containing the rows this processor should obtain 8283 . 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. 8284 - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 8285 8286 Output Parameter: 8287 . newmat - the new submatrix, of the same type as the original matrix 8288 8289 Level: advanced 8290 8291 Notes: 8292 The submatrix will be able to be multiplied with vectors using the same layout as `iscol`. 8293 8294 Some matrix types place restrictions on the row and column indices, such 8295 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; 8296 for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row. 8297 8298 The index sets may not have duplicate entries. 8299 8300 The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`, 8301 the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls 8302 to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX` 8303 will reuse the matrix generated the first time. You should call `MatDestroy()` on `newmat` when 8304 you are finished using it. 8305 8306 The communicator of the newly obtained matrix is ALWAYS the same as the communicator of 8307 the input matrix. 8308 8309 If `iscol` is `NULL` then all columns are obtained (not supported in Fortran). 8310 8311 Example usage: 8312 Consider the following 8x8 matrix with 34 non-zero values, that is 8313 assembled across 3 processors. Let's assume that proc0 owns 3 rows, 8314 proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 8315 as follows 8316 .vb 8317 1 2 0 | 0 3 0 | 0 4 8318 Proc0 0 5 6 | 7 0 0 | 8 0 8319 9 0 10 | 11 0 0 | 12 0 8320 ------------------------------------- 8321 13 0 14 | 15 16 17 | 0 0 8322 Proc1 0 18 0 | 19 20 21 | 0 0 8323 0 0 0 | 22 23 0 | 24 0 8324 ------------------------------------- 8325 Proc2 25 26 27 | 0 0 28 | 29 0 8326 30 0 0 | 31 32 33 | 0 34 8327 .ve 8328 8329 Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6]. The resulting submatrix is 8330 8331 .vb 8332 2 0 | 0 3 0 | 0 8333 Proc0 5 6 | 7 0 0 | 8 8334 ------------------------------- 8335 Proc1 18 0 | 19 20 21 | 0 8336 ------------------------------- 8337 Proc2 26 27 | 0 0 28 | 29 8338 0 0 | 31 32 33 | 0 8339 .ve 8340 8341 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()` 8342 @*/ 8343 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat) 8344 { 8345 PetscMPIInt size; 8346 Mat *local; 8347 IS iscoltmp; 8348 PetscBool flg; 8349 8350 PetscFunctionBegin; 8351 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8352 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 8353 if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 8354 PetscValidPointer(newmat, 5); 8355 if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5); 8356 PetscValidType(mat, 1); 8357 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8358 PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX"); 8359 8360 MatCheckPreallocated(mat, 1); 8361 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8362 8363 if (!iscol || isrow == iscol) { 8364 PetscBool stride; 8365 PetscMPIInt grabentirematrix = 0, grab; 8366 PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride)); 8367 if (stride) { 8368 PetscInt first, step, n, rstart, rend; 8369 PetscCall(ISStrideGetInfo(isrow, &first, &step)); 8370 if (step == 1) { 8371 PetscCall(MatGetOwnershipRange(mat, &rstart, &rend)); 8372 if (rstart == first) { 8373 PetscCall(ISGetLocalSize(isrow, &n)); 8374 if (n == rend - rstart) grabentirematrix = 1; 8375 } 8376 } 8377 } 8378 PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat))); 8379 if (grab) { 8380 PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n")); 8381 if (cll == MAT_INITIAL_MATRIX) { 8382 *newmat = mat; 8383 PetscCall(PetscObjectReference((PetscObject)mat)); 8384 } 8385 PetscFunctionReturn(PETSC_SUCCESS); 8386 } 8387 } 8388 8389 if (!iscol) { 8390 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp)); 8391 } else { 8392 iscoltmp = iscol; 8393 } 8394 8395 /* if original matrix is on just one processor then use submatrix generated */ 8396 if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) { 8397 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat)); 8398 goto setproperties; 8399 } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) { 8400 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local)); 8401 *newmat = *local; 8402 PetscCall(PetscFree(local)); 8403 goto setproperties; 8404 } else if (!mat->ops->createsubmatrix) { 8405 /* Create a new matrix type that implements the operation using the full matrix */ 8406 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8407 switch (cll) { 8408 case MAT_INITIAL_MATRIX: 8409 PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat)); 8410 break; 8411 case MAT_REUSE_MATRIX: 8412 PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp)); 8413 break; 8414 default: 8415 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX"); 8416 } 8417 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8418 goto setproperties; 8419 } 8420 8421 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8422 PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat); 8423 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8424 8425 setproperties: 8426 PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg)); 8427 if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat)); 8428 if (!iscol) PetscCall(ISDestroy(&iscoltmp)); 8429 if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat)); 8430 PetscFunctionReturn(PETSC_SUCCESS); 8431 } 8432 8433 /*@ 8434 MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix 8435 8436 Not Collective 8437 8438 Input Parameters: 8439 + A - the matrix we wish to propagate options from 8440 - B - the matrix we wish to propagate options to 8441 8442 Level: beginner 8443 8444 Note: 8445 Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL` 8446 8447 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, MatIsStructurallySymmetricKnown()` 8448 @*/ 8449 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B) 8450 { 8451 PetscFunctionBegin; 8452 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8453 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 8454 B->symmetry_eternal = A->symmetry_eternal; 8455 B->structural_symmetry_eternal = A->structural_symmetry_eternal; 8456 B->symmetric = A->symmetric; 8457 B->structurally_symmetric = A->structurally_symmetric; 8458 B->spd = A->spd; 8459 B->hermitian = A->hermitian; 8460 PetscFunctionReturn(PETSC_SUCCESS); 8461 } 8462 8463 /*@ 8464 MatStashSetInitialSize - sets the sizes of the matrix stash, that is 8465 used during the assembly process to store values that belong to 8466 other processors. 8467 8468 Not Collective 8469 8470 Input Parameters: 8471 + mat - the matrix 8472 . size - the initial size of the stash. 8473 - bsize - the initial size of the block-stash(if used). 8474 8475 Options Database Keys: 8476 + -matstash_initial_size <size> or <size0,size1,...sizep-1> 8477 - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1> 8478 8479 Level: intermediate 8480 8481 Notes: 8482 The block-stash is used for values set with `MatSetValuesBlocked()` while 8483 the stash is used for values set with `MatSetValues()` 8484 8485 Run with the option -info and look for output of the form 8486 MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs. 8487 to determine the appropriate value, MM, to use for size and 8488 MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs. 8489 to determine the value, BMM to use for bsize 8490 8491 .seealso: [](chapter_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()` 8492 @*/ 8493 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize) 8494 { 8495 PetscFunctionBegin; 8496 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8497 PetscValidType(mat, 1); 8498 PetscCall(MatStashSetInitialSize_Private(&mat->stash, size)); 8499 PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize)); 8500 PetscFunctionReturn(PETSC_SUCCESS); 8501 } 8502 8503 /*@ 8504 MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of 8505 the matrix 8506 8507 Neighbor-wise Collective 8508 8509 Input Parameters: 8510 + mat - the matrix 8511 . x - the vector to be multiplied by the interpolation operator 8512 - y - the vector to be added to the result 8513 8514 Output Parameter: 8515 . w - the resulting vector 8516 8517 Level: intermediate 8518 8519 Notes: 8520 `w` may be the same vector as `y`. 8521 8522 This allows one to use either the restriction or interpolation (its transpose) 8523 matrix to do the interpolation 8524 8525 .seealso: [](chapter_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8526 @*/ 8527 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w) 8528 { 8529 PetscInt M, N, Ny; 8530 8531 PetscFunctionBegin; 8532 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8533 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8534 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8535 PetscValidHeaderSpecific(w, VEC_CLASSID, 4); 8536 PetscCall(MatGetSize(A, &M, &N)); 8537 PetscCall(VecGetSize(y, &Ny)); 8538 if (M == Ny) { 8539 PetscCall(MatMultAdd(A, x, y, w)); 8540 } else { 8541 PetscCall(MatMultTransposeAdd(A, x, y, w)); 8542 } 8543 PetscFunctionReturn(PETSC_SUCCESS); 8544 } 8545 8546 /*@ 8547 MatInterpolate - y = A*x or A'*x depending on the shape of 8548 the matrix 8549 8550 Neighbor-wise Collective 8551 8552 Input Parameters: 8553 + mat - the matrix 8554 - x - the vector to be interpolated 8555 8556 Output Parameter: 8557 . y - the resulting vector 8558 8559 Level: intermediate 8560 8561 Note: 8562 This allows one to use either the restriction or interpolation (its transpose) 8563 matrix to do the interpolation 8564 8565 .seealso: [](chapter_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8566 @*/ 8567 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y) 8568 { 8569 PetscInt M, N, Ny; 8570 8571 PetscFunctionBegin; 8572 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8573 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8574 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8575 PetscCall(MatGetSize(A, &M, &N)); 8576 PetscCall(VecGetSize(y, &Ny)); 8577 if (M == Ny) { 8578 PetscCall(MatMult(A, x, y)); 8579 } else { 8580 PetscCall(MatMultTranspose(A, x, y)); 8581 } 8582 PetscFunctionReturn(PETSC_SUCCESS); 8583 } 8584 8585 /*@ 8586 MatRestrict - y = A*x or A'*x 8587 8588 Neighbor-wise Collective 8589 8590 Input Parameters: 8591 + mat - the matrix 8592 - x - the vector to be restricted 8593 8594 Output Parameter: 8595 . y - the resulting vector 8596 8597 Level: intermediate 8598 8599 Note: 8600 This allows one to use either the restriction or interpolation (its transpose) 8601 matrix to do the restriction 8602 8603 .seealso: [](chapter_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG` 8604 @*/ 8605 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y) 8606 { 8607 PetscInt M, N, Ny; 8608 8609 PetscFunctionBegin; 8610 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8611 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8612 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8613 PetscCall(MatGetSize(A, &M, &N)); 8614 PetscCall(VecGetSize(y, &Ny)); 8615 if (M == Ny) { 8616 PetscCall(MatMult(A, x, y)); 8617 } else { 8618 PetscCall(MatMultTranspose(A, x, y)); 8619 } 8620 PetscFunctionReturn(PETSC_SUCCESS); 8621 } 8622 8623 /*@ 8624 MatMatInterpolateAdd - Y = W + A*X or W + A'*X 8625 8626 Neighbor-wise Collective 8627 8628 Input Parameters: 8629 + mat - the matrix 8630 . x - the input dense matrix to be multiplied 8631 - w - the input dense matrix to be added to the result 8632 8633 Output Parameter: 8634 . y - the output dense matrix 8635 8636 Level: intermediate 8637 8638 Note: 8639 This allows one to use either the restriction or interpolation (its transpose) 8640 matrix to do the interpolation. y matrix can be reused if already created with the proper sizes, 8641 otherwise it will be recreated. y must be initialized to `NULL` if not supplied. 8642 8643 .seealso: [](chapter_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG` 8644 @*/ 8645 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y) 8646 { 8647 PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0; 8648 PetscBool trans = PETSC_TRUE; 8649 MatReuse reuse = MAT_INITIAL_MATRIX; 8650 8651 PetscFunctionBegin; 8652 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8653 PetscValidHeaderSpecific(x, MAT_CLASSID, 2); 8654 PetscValidType(x, 2); 8655 if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3); 8656 if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4); 8657 PetscCall(MatGetSize(A, &M, &N)); 8658 PetscCall(MatGetSize(x, &Mx, &Nx)); 8659 if (N == Mx) trans = PETSC_FALSE; 8660 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); 8661 Mo = trans ? N : M; 8662 if (*y) { 8663 PetscCall(MatGetSize(*y, &My, &Ny)); 8664 if (Mo == My && Nx == Ny) { 8665 reuse = MAT_REUSE_MATRIX; 8666 } else { 8667 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); 8668 PetscCall(MatDestroy(y)); 8669 } 8670 } 8671 8672 if (w && *y == w) { /* this is to minimize changes in PCMG */ 8673 PetscBool flg; 8674 8675 PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w)); 8676 if (w) { 8677 PetscInt My, Ny, Mw, Nw; 8678 8679 PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg)); 8680 PetscCall(MatGetSize(*y, &My, &Ny)); 8681 PetscCall(MatGetSize(w, &Mw, &Nw)); 8682 if (!flg || My != Mw || Ny != Nw) w = NULL; 8683 } 8684 if (!w) { 8685 PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w)); 8686 PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w)); 8687 PetscCall(PetscObjectDereference((PetscObject)w)); 8688 } else { 8689 PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN)); 8690 } 8691 } 8692 if (!trans) { 8693 PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8694 } else { 8695 PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8696 } 8697 if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN)); 8698 PetscFunctionReturn(PETSC_SUCCESS); 8699 } 8700 8701 /*@ 8702 MatMatInterpolate - Y = A*X or A'*X 8703 8704 Neighbor-wise Collective 8705 8706 Input Parameters: 8707 + mat - the matrix 8708 - x - the input dense matrix 8709 8710 Output Parameter: 8711 . y - the output dense matrix 8712 8713 Level: intermediate 8714 8715 Note: 8716 This allows one to use either the restriction or interpolation (its transpose) 8717 matrix to do the interpolation. y matrix can be reused if already created with the proper sizes, 8718 otherwise it will be recreated. y must be initialized to `NULL` if not supplied. 8719 8720 .seealso: [](chapter_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG` 8721 @*/ 8722 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y) 8723 { 8724 PetscFunctionBegin; 8725 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8726 PetscFunctionReturn(PETSC_SUCCESS); 8727 } 8728 8729 /*@ 8730 MatMatRestrict - Y = A*X or A'*X 8731 8732 Neighbor-wise Collective 8733 8734 Input Parameters: 8735 + mat - the matrix 8736 - x - the input dense matrix 8737 8738 Output Parameter: 8739 . y - the output dense matrix 8740 8741 Level: intermediate 8742 8743 Note: 8744 This allows one to use either the restriction or interpolation (its transpose) 8745 matrix to do the restriction. y matrix can be reused if already created with the proper sizes, 8746 otherwise it will be recreated. y must be initialized to `NULL` if not supplied. 8747 8748 .seealso: [](chapter_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG` 8749 @*/ 8750 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y) 8751 { 8752 PetscFunctionBegin; 8753 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8754 PetscFunctionReturn(PETSC_SUCCESS); 8755 } 8756 8757 /*@ 8758 MatGetNullSpace - retrieves the null space of a matrix. 8759 8760 Logically Collective 8761 8762 Input Parameters: 8763 + mat - the matrix 8764 - nullsp - the null space object 8765 8766 Level: developer 8767 8768 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace` 8769 @*/ 8770 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp) 8771 { 8772 PetscFunctionBegin; 8773 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8774 PetscValidPointer(nullsp, 2); 8775 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp; 8776 PetscFunctionReturn(PETSC_SUCCESS); 8777 } 8778 8779 /*@ 8780 MatSetNullSpace - attaches a null space to a matrix. 8781 8782 Logically Collective 8783 8784 Input Parameters: 8785 + mat - the matrix 8786 - nullsp - the null space object 8787 8788 Level: advanced 8789 8790 Notes: 8791 This null space is used by the `KSP` linear solvers to solve singular systems. 8792 8793 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` 8794 8795 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 8796 to zero but the linear system will still be solved in a least squares sense. 8797 8798 The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that 8799 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). 8800 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 8801 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 8802 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). 8803 This \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix. 8804 8805 If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called 8806 `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this 8807 routine also automatically calls `MatSetTransposeNullSpace()`. 8808 8809 The user should call `MatNullSpaceDestroy()`. 8810 8811 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, 8812 `KSPSetPCSide()` 8813 @*/ 8814 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp) 8815 { 8816 PetscFunctionBegin; 8817 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8818 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8819 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8820 PetscCall(MatNullSpaceDestroy(&mat->nullsp)); 8821 mat->nullsp = nullsp; 8822 if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp)); 8823 PetscFunctionReturn(PETSC_SUCCESS); 8824 } 8825 8826 /*@ 8827 MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix. 8828 8829 Logically Collective 8830 8831 Input Parameters: 8832 + mat - the matrix 8833 - nullsp - the null space object 8834 8835 Level: developer 8836 8837 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()` 8838 @*/ 8839 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp) 8840 { 8841 PetscFunctionBegin; 8842 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8843 PetscValidType(mat, 1); 8844 PetscValidPointer(nullsp, 2); 8845 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp; 8846 PetscFunctionReturn(PETSC_SUCCESS); 8847 } 8848 8849 /*@ 8850 MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix 8851 8852 Logically Collective 8853 8854 Input Parameters: 8855 + mat - the matrix 8856 - nullsp - the null space object 8857 8858 Level: advanced 8859 8860 Notes: 8861 This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning. 8862 8863 See `MatSetNullSpace()` 8864 8865 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()` 8866 @*/ 8867 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp) 8868 { 8869 PetscFunctionBegin; 8870 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8871 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8872 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8873 PetscCall(MatNullSpaceDestroy(&mat->transnullsp)); 8874 mat->transnullsp = nullsp; 8875 PetscFunctionReturn(PETSC_SUCCESS); 8876 } 8877 8878 /*@ 8879 MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions 8880 This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix. 8881 8882 Logically Collective 8883 8884 Input Parameters: 8885 + mat - the matrix 8886 - nullsp - the null space object 8887 8888 Level: advanced 8889 8890 Notes: 8891 Overwrites any previous near null space that may have been attached 8892 8893 You can remove the null space by calling this routine with an nullsp of `NULL` 8894 8895 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()` 8896 @*/ 8897 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp) 8898 { 8899 PetscFunctionBegin; 8900 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8901 PetscValidType(mat, 1); 8902 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8903 MatCheckPreallocated(mat, 1); 8904 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8905 PetscCall(MatNullSpaceDestroy(&mat->nearnullsp)); 8906 mat->nearnullsp = nullsp; 8907 PetscFunctionReturn(PETSC_SUCCESS); 8908 } 8909 8910 /*@ 8911 MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()` 8912 8913 Not Collective 8914 8915 Input Parameter: 8916 . mat - the matrix 8917 8918 Output Parameter: 8919 . nullsp - the null space object, `NULL` if not set 8920 8921 Level: advanced 8922 8923 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()` 8924 @*/ 8925 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp) 8926 { 8927 PetscFunctionBegin; 8928 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8929 PetscValidType(mat, 1); 8930 PetscValidPointer(nullsp, 2); 8931 MatCheckPreallocated(mat, 1); 8932 *nullsp = mat->nearnullsp; 8933 PetscFunctionReturn(PETSC_SUCCESS); 8934 } 8935 8936 /*@C 8937 MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix. 8938 8939 Collective 8940 8941 Input Parameters: 8942 + mat - the matrix 8943 . row - row/column permutation 8944 - info - information on desired factorization process 8945 8946 Level: developer 8947 8948 Notes: 8949 Probably really in-place only when level of fill is zero, otherwise allocates 8950 new space to store factored matrix and deletes previous memory. 8951 8952 Most users should employ the `KSP` interface for linear solvers 8953 instead of working directly with matrix algebra routines such as this. 8954 See, e.g., `KSPCreate()`. 8955 8956 Developer Note: 8957 The Fortran interface is not autogenerated as the 8958 interface definition cannot be generated correctly [due to `MatFactorInfo`] 8959 8960 .seealso: [](chapter_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 8961 @*/ 8962 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info) 8963 { 8964 PetscFunctionBegin; 8965 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8966 PetscValidType(mat, 1); 8967 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 8968 PetscValidPointer(info, 3); 8969 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 8970 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 8971 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8972 MatCheckPreallocated(mat, 1); 8973 PetscUseTypeMethod(mat, iccfactor, row, info); 8974 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 8975 PetscFunctionReturn(PETSC_SUCCESS); 8976 } 8977 8978 /*@ 8979 MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the 8980 ghosted ones. 8981 8982 Not Collective 8983 8984 Input Parameters: 8985 + mat - the matrix 8986 - diag - the diagonal values, including ghost ones 8987 8988 Level: developer 8989 8990 Notes: 8991 Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices 8992 8993 This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()` 8994 8995 .seealso: [](chapter_matrices), `Mat`, `MatDiagonalScale()` 8996 @*/ 8997 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag) 8998 { 8999 PetscMPIInt size; 9000 9001 PetscFunctionBegin; 9002 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9003 PetscValidHeaderSpecific(diag, VEC_CLASSID, 2); 9004 PetscValidType(mat, 1); 9005 9006 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled"); 9007 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 9008 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 9009 if (size == 1) { 9010 PetscInt n, m; 9011 PetscCall(VecGetSize(diag, &n)); 9012 PetscCall(MatGetSize(mat, NULL, &m)); 9013 PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions"); 9014 PetscCall(MatDiagonalScale(mat, NULL, diag)); 9015 } else { 9016 PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag)); 9017 } 9018 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 9019 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9020 PetscFunctionReturn(PETSC_SUCCESS); 9021 } 9022 9023 /*@ 9024 MatGetInertia - Gets the inertia from a factored matrix 9025 9026 Collective 9027 9028 Input Parameter: 9029 . mat - the matrix 9030 9031 Output Parameters: 9032 + nneg - number of negative eigenvalues 9033 . nzero - number of zero eigenvalues 9034 - npos - number of positive eigenvalues 9035 9036 Level: advanced 9037 9038 Note: 9039 Matrix must have been factored by `MatCholeskyFactor()` 9040 9041 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()` 9042 @*/ 9043 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos) 9044 { 9045 PetscFunctionBegin; 9046 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9047 PetscValidType(mat, 1); 9048 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9049 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled"); 9050 PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos); 9051 PetscFunctionReturn(PETSC_SUCCESS); 9052 } 9053 9054 /*@C 9055 MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors 9056 9057 Neighbor-wise Collective 9058 9059 Input Parameters: 9060 + mat - the factored matrix obtained with `MatGetFactor()` 9061 - b - the right-hand-side vectors 9062 9063 Output Parameter: 9064 . x - the result vectors 9065 9066 Level: developer 9067 9068 Note: 9069 The vectors `b` and `x` cannot be the same. I.e., one cannot 9070 call `MatSolves`(A,x,x). 9071 9072 .seealso: [](chapter_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()` 9073 @*/ 9074 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x) 9075 { 9076 PetscFunctionBegin; 9077 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9078 PetscValidType(mat, 1); 9079 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 9080 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9081 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 9082 9083 MatCheckPreallocated(mat, 1); 9084 PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0)); 9085 PetscUseTypeMethod(mat, solves, b, x); 9086 PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0)); 9087 PetscFunctionReturn(PETSC_SUCCESS); 9088 } 9089 9090 /*@ 9091 MatIsSymmetric - Test whether a matrix is symmetric 9092 9093 Collective 9094 9095 Input Parameters: 9096 + A - the matrix to test 9097 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose) 9098 9099 Output Parameter: 9100 . flg - the result 9101 9102 Level: intermediate 9103 9104 Notes: 9105 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9106 9107 If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()` 9108 9109 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9110 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9111 9112 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`, 9113 `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()` 9114 @*/ 9115 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg) 9116 { 9117 PetscFunctionBegin; 9118 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9119 PetscValidBoolPointer(flg, 3); 9120 9121 if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE; 9122 else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE; 9123 else { 9124 if (!A->ops->issymmetric) { 9125 MatType mattype; 9126 PetscCall(MatGetType(A, &mattype)); 9127 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for symmetric", mattype); 9128 } 9129 PetscUseTypeMethod(A, issymmetric, tol, flg); 9130 if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg)); 9131 } 9132 PetscFunctionReturn(PETSC_SUCCESS); 9133 } 9134 9135 /*@ 9136 MatIsHermitian - Test whether a matrix is Hermitian 9137 9138 Collective 9139 9140 Input Parameters: 9141 + A - the matrix to test 9142 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian) 9143 9144 Output Parameter: 9145 . flg - the result 9146 9147 Level: intermediate 9148 9149 Notes: 9150 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9151 9152 If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()` 9153 9154 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9155 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`) 9156 9157 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, 9158 `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()` 9159 @*/ 9160 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg) 9161 { 9162 PetscFunctionBegin; 9163 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9164 PetscValidBoolPointer(flg, 3); 9165 9166 if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE; 9167 else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE; 9168 else { 9169 if (!A->ops->ishermitian) { 9170 MatType mattype; 9171 PetscCall(MatGetType(A, &mattype)); 9172 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for hermitian", mattype); 9173 } 9174 PetscUseTypeMethod(A, ishermitian, tol, flg); 9175 if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg)); 9176 } 9177 PetscFunctionReturn(PETSC_SUCCESS); 9178 } 9179 9180 /*@ 9181 MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state 9182 9183 Not Collective 9184 9185 Input Parameter: 9186 . A - the matrix to check 9187 9188 Output Parameters: 9189 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid) 9190 - flg - the result (only valid if set is `PETSC_TRUE`) 9191 9192 Level: advanced 9193 9194 Notes: 9195 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()` 9196 if you want it explicitly checked 9197 9198 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9199 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9200 9201 .seealso: [](chapter_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9202 @*/ 9203 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9204 { 9205 PetscFunctionBegin; 9206 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9207 PetscValidBoolPointer(set, 2); 9208 PetscValidBoolPointer(flg, 3); 9209 if (A->symmetric != PETSC_BOOL3_UNKNOWN) { 9210 *set = PETSC_TRUE; 9211 *flg = PetscBool3ToBool(A->symmetric); 9212 } else { 9213 *set = PETSC_FALSE; 9214 } 9215 PetscFunctionReturn(PETSC_SUCCESS); 9216 } 9217 9218 /*@ 9219 MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state 9220 9221 Not Collective 9222 9223 Input Parameter: 9224 . A - the matrix to check 9225 9226 Output Parameters: 9227 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid) 9228 - flg - the result (only valid if set is `PETSC_TRUE`) 9229 9230 Level: advanced 9231 9232 Notes: 9233 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). 9234 9235 One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD 9236 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`) 9237 9238 .seealso: [](chapter_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9239 @*/ 9240 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg) 9241 { 9242 PetscFunctionBegin; 9243 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9244 PetscValidBoolPointer(set, 2); 9245 PetscValidBoolPointer(flg, 3); 9246 if (A->spd != PETSC_BOOL3_UNKNOWN) { 9247 *set = PETSC_TRUE; 9248 *flg = PetscBool3ToBool(A->spd); 9249 } else { 9250 *set = PETSC_FALSE; 9251 } 9252 PetscFunctionReturn(PETSC_SUCCESS); 9253 } 9254 9255 /*@ 9256 MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state 9257 9258 Not Collective 9259 9260 Input Parameter: 9261 . A - the matrix to check 9262 9263 Output Parameters: 9264 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid) 9265 - flg - the result (only valid if set is `PETSC_TRUE`) 9266 9267 Level: advanced 9268 9269 Notes: 9270 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()` 9271 if you want it explicitly checked 9272 9273 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9274 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9275 9276 .seealso: [](chapter_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()` 9277 @*/ 9278 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg) 9279 { 9280 PetscFunctionBegin; 9281 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9282 PetscValidBoolPointer(set, 2); 9283 PetscValidBoolPointer(flg, 3); 9284 if (A->hermitian != PETSC_BOOL3_UNKNOWN) { 9285 *set = PETSC_TRUE; 9286 *flg = PetscBool3ToBool(A->hermitian); 9287 } else { 9288 *set = PETSC_FALSE; 9289 } 9290 PetscFunctionReturn(PETSC_SUCCESS); 9291 } 9292 9293 /*@ 9294 MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric 9295 9296 Collective 9297 9298 Input Parameter: 9299 . A - the matrix to test 9300 9301 Output Parameter: 9302 . flg - the result 9303 9304 Level: intermediate 9305 9306 Notes: 9307 If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()` 9308 9309 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 9310 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9311 9312 .seealso: [](chapter_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()` 9313 @*/ 9314 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg) 9315 { 9316 PetscFunctionBegin; 9317 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9318 PetscValidBoolPointer(flg, 2); 9319 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9320 *flg = PetscBool3ToBool(A->structurally_symmetric); 9321 } else { 9322 PetscUseTypeMethod(A, isstructurallysymmetric, flg); 9323 PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg)); 9324 } 9325 PetscFunctionReturn(PETSC_SUCCESS); 9326 } 9327 9328 /*@ 9329 MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state 9330 9331 Not Collective 9332 9333 Input Parameter: 9334 . A - the matrix to check 9335 9336 Output Parameters: 9337 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid) 9338 - flg - the result (only valid if set is PETSC_TRUE) 9339 9340 Level: advanced 9341 9342 Notes: 9343 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 9344 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9345 9346 Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation) 9347 9348 .seealso: [](chapter_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9349 @*/ 9350 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9351 { 9352 PetscFunctionBegin; 9353 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9354 PetscValidBoolPointer(set, 2); 9355 PetscValidBoolPointer(flg, 3); 9356 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9357 *set = PETSC_TRUE; 9358 *flg = PetscBool3ToBool(A->structurally_symmetric); 9359 } else { 9360 *set = PETSC_FALSE; 9361 } 9362 PetscFunctionReturn(PETSC_SUCCESS); 9363 } 9364 9365 /*@ 9366 MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need 9367 to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process 9368 9369 Not Collective 9370 9371 Input Parameter: 9372 . mat - the matrix 9373 9374 Output Parameters: 9375 + nstash - the size of the stash 9376 . reallocs - the number of additional mallocs incurred. 9377 . bnstash - the size of the block stash 9378 - breallocs - the number of additional mallocs incurred.in the block stash 9379 9380 Level: advanced 9381 9382 .seealso: [](chapter_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()` 9383 @*/ 9384 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs) 9385 { 9386 PetscFunctionBegin; 9387 PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs)); 9388 PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs)); 9389 PetscFunctionReturn(PETSC_SUCCESS); 9390 } 9391 9392 /*@C 9393 MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same 9394 parallel layout, `PetscLayout` for rows and columns 9395 9396 Collective 9397 9398 Input Parameter: 9399 . mat - the matrix 9400 9401 Output Parameters: 9402 + right - (optional) vector that the matrix can be multiplied against 9403 - left - (optional) vector that the matrix vector product can be stored in 9404 9405 Level: advanced 9406 9407 Notes: 9408 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()`. 9409 9410 These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed 9411 9412 .seealso: [](chapter_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()` 9413 @*/ 9414 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left) 9415 { 9416 PetscFunctionBegin; 9417 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9418 PetscValidType(mat, 1); 9419 if (mat->ops->getvecs) { 9420 PetscUseTypeMethod(mat, getvecs, right, left); 9421 } else { 9422 PetscInt rbs, cbs; 9423 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 9424 if (right) { 9425 PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup"); 9426 PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), right)); 9427 PetscCall(VecSetSizes(*right, mat->cmap->n, PETSC_DETERMINE)); 9428 PetscCall(VecSetBlockSize(*right, cbs)); 9429 PetscCall(VecSetType(*right, mat->defaultvectype)); 9430 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9431 if (mat->boundtocpu && mat->bindingpropagates) { 9432 PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE)); 9433 PetscCall(VecBindToCPU(*right, PETSC_TRUE)); 9434 } 9435 #endif 9436 PetscCall(PetscLayoutReference(mat->cmap, &(*right)->map)); 9437 } 9438 if (left) { 9439 PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup"); 9440 PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), left)); 9441 PetscCall(VecSetSizes(*left, mat->rmap->n, PETSC_DETERMINE)); 9442 PetscCall(VecSetBlockSize(*left, rbs)); 9443 PetscCall(VecSetType(*left, mat->defaultvectype)); 9444 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9445 if (mat->boundtocpu && mat->bindingpropagates) { 9446 PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE)); 9447 PetscCall(VecBindToCPU(*left, PETSC_TRUE)); 9448 } 9449 #endif 9450 PetscCall(PetscLayoutReference(mat->rmap, &(*left)->map)); 9451 } 9452 } 9453 PetscFunctionReturn(PETSC_SUCCESS); 9454 } 9455 9456 /*@C 9457 MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure 9458 with default values. 9459 9460 Not Collective 9461 9462 Input Parameter: 9463 . info - the `MatFactorInfo` data structure 9464 9465 Level: developer 9466 9467 Notes: 9468 The solvers are generally used through the `KSP` and `PC` objects, for example 9469 `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC` 9470 9471 Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed 9472 9473 Developer Note: 9474 The Fortran interface is not autogenerated as the 9475 interface definition cannot be generated correctly [due to `MatFactorInfo`] 9476 9477 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo` 9478 @*/ 9479 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info) 9480 { 9481 PetscFunctionBegin; 9482 PetscCall(PetscMemzero(info, sizeof(MatFactorInfo))); 9483 PetscFunctionReturn(PETSC_SUCCESS); 9484 } 9485 9486 /*@ 9487 MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed 9488 9489 Collective 9490 9491 Input Parameters: 9492 + mat - the factored matrix 9493 - is - the index set defining the Schur indices (0-based) 9494 9495 Level: advanced 9496 9497 Notes: 9498 Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system. 9499 9500 You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call. 9501 9502 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9503 9504 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`, 9505 `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9506 @*/ 9507 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is) 9508 { 9509 PetscErrorCode (*f)(Mat, IS); 9510 9511 PetscFunctionBegin; 9512 PetscValidType(mat, 1); 9513 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9514 PetscValidType(is, 2); 9515 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 9516 PetscCheckSameComm(mat, 1, is, 2); 9517 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 9518 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f)); 9519 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO"); 9520 PetscCall(MatDestroy(&mat->schur)); 9521 PetscCall((*f)(mat, is)); 9522 PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created"); 9523 PetscFunctionReturn(PETSC_SUCCESS); 9524 } 9525 9526 /*@ 9527 MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step 9528 9529 Logically Collective 9530 9531 Input Parameters: 9532 + F - the factored matrix obtained by calling `MatGetFactor()` 9533 . S - location where to return the Schur complement, can be `NULL` 9534 - status - the status of the Schur complement matrix, can be `NULL` 9535 9536 Level: advanced 9537 9538 Notes: 9539 You must call `MatFactorSetSchurIS()` before calling this routine. 9540 9541 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9542 9543 The routine provides a copy of the Schur matrix stored within the solver data structures. 9544 The caller must destroy the object when it is no longer needed. 9545 If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse. 9546 9547 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) 9548 9549 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9550 9551 Developer Note: 9552 The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc 9553 matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix. 9554 9555 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9556 @*/ 9557 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9558 { 9559 PetscFunctionBegin; 9560 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9561 if (S) PetscValidPointer(S, 2); 9562 if (status) PetscValidPointer(status, 3); 9563 if (S) { 9564 PetscErrorCode (*f)(Mat, Mat *); 9565 9566 PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f)); 9567 if (f) { 9568 PetscCall((*f)(F, S)); 9569 } else { 9570 PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S)); 9571 } 9572 } 9573 if (status) *status = F->schur_status; 9574 PetscFunctionReturn(PETSC_SUCCESS); 9575 } 9576 9577 /*@ 9578 MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix 9579 9580 Logically Collective 9581 9582 Input Parameters: 9583 + F - the factored matrix obtained by calling `MatGetFactor()` 9584 . *S - location where to return the Schur complement, can be `NULL` 9585 - status - the status of the Schur complement matrix, can be `NULL` 9586 9587 Level: advanced 9588 9589 Notes: 9590 You must call `MatFactorSetSchurIS()` before calling this routine. 9591 9592 Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS` 9593 9594 The routine returns a the Schur Complement stored within the data structures of the solver. 9595 9596 If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement. 9597 9598 The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed. 9599 9600 Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix 9601 9602 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9603 9604 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9605 @*/ 9606 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9607 { 9608 PetscFunctionBegin; 9609 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9610 if (S) PetscValidPointer(S, 2); 9611 if (status) PetscValidPointer(status, 3); 9612 if (S) *S = F->schur; 9613 if (status) *status = F->schur_status; 9614 PetscFunctionReturn(PETSC_SUCCESS); 9615 } 9616 9617 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F) 9618 { 9619 Mat S = F->schur; 9620 9621 PetscFunctionBegin; 9622 switch (F->schur_status) { 9623 case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through 9624 case MAT_FACTOR_SCHUR_INVERTED: 9625 if (S) { 9626 S->ops->solve = NULL; 9627 S->ops->matsolve = NULL; 9628 S->ops->solvetranspose = NULL; 9629 S->ops->matsolvetranspose = NULL; 9630 S->ops->solveadd = NULL; 9631 S->ops->solvetransposeadd = NULL; 9632 S->factortype = MAT_FACTOR_NONE; 9633 PetscCall(PetscFree(S->solvertype)); 9634 } 9635 case MAT_FACTOR_SCHUR_FACTORED: // fall-through 9636 break; 9637 default: 9638 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9639 } 9640 PetscFunctionReturn(PETSC_SUCCESS); 9641 } 9642 9643 /*@ 9644 MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()` 9645 9646 Logically Collective 9647 9648 Input Parameters: 9649 + F - the factored matrix obtained by calling `MatGetFactor()` 9650 . *S - location where the Schur complement is stored 9651 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`) 9652 9653 Level: advanced 9654 9655 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9656 @*/ 9657 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status) 9658 { 9659 PetscFunctionBegin; 9660 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9661 if (S) { 9662 PetscValidHeaderSpecific(*S, MAT_CLASSID, 2); 9663 *S = NULL; 9664 } 9665 F->schur_status = status; 9666 PetscCall(MatFactorUpdateSchurStatus_Private(F)); 9667 PetscFunctionReturn(PETSC_SUCCESS); 9668 } 9669 9670 /*@ 9671 MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step 9672 9673 Logically Collective 9674 9675 Input Parameters: 9676 + F - the factored matrix obtained by calling `MatGetFactor()` 9677 . rhs - location where the right hand side of the Schur complement system is stored 9678 - sol - location where the solution of the Schur complement system has to be returned 9679 9680 Level: advanced 9681 9682 Notes: 9683 The sizes of the vectors should match the size of the Schur complement 9684 9685 Must be called after `MatFactorSetSchurIS()` 9686 9687 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()` 9688 @*/ 9689 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol) 9690 { 9691 PetscFunctionBegin; 9692 PetscValidType(F, 1); 9693 PetscValidType(rhs, 2); 9694 PetscValidType(sol, 3); 9695 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9696 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9697 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9698 PetscCheckSameComm(F, 1, rhs, 2); 9699 PetscCheckSameComm(F, 1, sol, 3); 9700 PetscCall(MatFactorFactorizeSchurComplement(F)); 9701 switch (F->schur_status) { 9702 case MAT_FACTOR_SCHUR_FACTORED: 9703 PetscCall(MatSolveTranspose(F->schur, rhs, sol)); 9704 break; 9705 case MAT_FACTOR_SCHUR_INVERTED: 9706 PetscCall(MatMultTranspose(F->schur, rhs, sol)); 9707 break; 9708 default: 9709 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9710 } 9711 PetscFunctionReturn(PETSC_SUCCESS); 9712 } 9713 9714 /*@ 9715 MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step 9716 9717 Logically Collective 9718 9719 Input Parameters: 9720 + F - the factored matrix obtained by calling `MatGetFactor()` 9721 . rhs - location where the right hand side of the Schur complement system is stored 9722 - sol - location where the solution of the Schur complement system has to be returned 9723 9724 Level: advanced 9725 9726 Notes: 9727 The sizes of the vectors should match the size of the Schur complement 9728 9729 Must be called after `MatFactorSetSchurIS()` 9730 9731 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()` 9732 @*/ 9733 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol) 9734 { 9735 PetscFunctionBegin; 9736 PetscValidType(F, 1); 9737 PetscValidType(rhs, 2); 9738 PetscValidType(sol, 3); 9739 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9740 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9741 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9742 PetscCheckSameComm(F, 1, rhs, 2); 9743 PetscCheckSameComm(F, 1, sol, 3); 9744 PetscCall(MatFactorFactorizeSchurComplement(F)); 9745 switch (F->schur_status) { 9746 case MAT_FACTOR_SCHUR_FACTORED: 9747 PetscCall(MatSolve(F->schur, rhs, sol)); 9748 break; 9749 case MAT_FACTOR_SCHUR_INVERTED: 9750 PetscCall(MatMult(F->schur, rhs, sol)); 9751 break; 9752 default: 9753 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9754 } 9755 PetscFunctionReturn(PETSC_SUCCESS); 9756 } 9757 9758 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat); 9759 #if PetscDefined(HAVE_CUDA) 9760 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat); 9761 #endif 9762 9763 /* Schur status updated in the interface */ 9764 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F) 9765 { 9766 Mat S = F->schur; 9767 9768 PetscFunctionBegin; 9769 if (S) { 9770 PetscMPIInt size; 9771 PetscBool isdense, isdensecuda; 9772 9773 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size)); 9774 PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented"); 9775 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense)); 9776 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda)); 9777 PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name); 9778 PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0)); 9779 if (isdense) { 9780 PetscCall(MatSeqDenseInvertFactors_Private(S)); 9781 } else if (isdensecuda) { 9782 #if defined(PETSC_HAVE_CUDA) 9783 PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S)); 9784 #endif 9785 } 9786 // HIP?????????????? 9787 PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0)); 9788 } 9789 PetscFunctionReturn(PETSC_SUCCESS); 9790 } 9791 9792 /*@ 9793 MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step 9794 9795 Logically Collective 9796 9797 Input Parameter: 9798 . F - the factored matrix obtained by calling `MatGetFactor()` 9799 9800 Level: advanced 9801 9802 Notes: 9803 Must be called after `MatFactorSetSchurIS()`. 9804 9805 Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it. 9806 9807 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()` 9808 @*/ 9809 PetscErrorCode MatFactorInvertSchurComplement(Mat F) 9810 { 9811 PetscFunctionBegin; 9812 PetscValidType(F, 1); 9813 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9814 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS); 9815 PetscCall(MatFactorFactorizeSchurComplement(F)); 9816 PetscCall(MatFactorInvertSchurComplement_Private(F)); 9817 F->schur_status = MAT_FACTOR_SCHUR_INVERTED; 9818 PetscFunctionReturn(PETSC_SUCCESS); 9819 } 9820 9821 /*@ 9822 MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step 9823 9824 Logically Collective 9825 9826 Input Parameter: 9827 . F - the factored matrix obtained by calling `MatGetFactor()` 9828 9829 Level: advanced 9830 9831 Note: 9832 Must be called after `MatFactorSetSchurIS()` 9833 9834 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()` 9835 @*/ 9836 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F) 9837 { 9838 MatFactorInfo info; 9839 9840 PetscFunctionBegin; 9841 PetscValidType(F, 1); 9842 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9843 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS); 9844 PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0)); 9845 PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo))); 9846 if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */ 9847 PetscCall(MatCholeskyFactor(F->schur, NULL, &info)); 9848 } else { 9849 PetscCall(MatLUFactor(F->schur, NULL, NULL, &info)); 9850 } 9851 PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0)); 9852 F->schur_status = MAT_FACTOR_SCHUR_FACTORED; 9853 PetscFunctionReturn(PETSC_SUCCESS); 9854 } 9855 9856 /*@ 9857 MatPtAP - Creates the matrix product C = P^T * A * P 9858 9859 Neighbor-wise Collective 9860 9861 Input Parameters: 9862 + A - the matrix 9863 . P - the projection matrix 9864 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9865 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate 9866 if the result is a dense matrix this is irrelevant 9867 9868 Output Parameter: 9869 . C - the product matrix 9870 9871 Level: intermediate 9872 9873 Notes: 9874 C will be created and must be destroyed by the user with `MatDestroy()`. 9875 9876 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9877 9878 Developer Note: 9879 For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`. 9880 9881 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()` 9882 @*/ 9883 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C) 9884 { 9885 PetscFunctionBegin; 9886 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 9887 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9888 9889 if (scall == MAT_INITIAL_MATRIX) { 9890 PetscCall(MatProductCreate(A, P, NULL, C)); 9891 PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP)); 9892 PetscCall(MatProductSetAlgorithm(*C, "default")); 9893 PetscCall(MatProductSetFill(*C, fill)); 9894 9895 (*C)->product->api_user = PETSC_TRUE; 9896 PetscCall(MatProductSetFromOptions(*C)); 9897 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); 9898 PetscCall(MatProductSymbolic(*C)); 9899 } else { /* scall == MAT_REUSE_MATRIX */ 9900 PetscCall(MatProductReplaceMats(A, P, NULL, *C)); 9901 } 9902 9903 PetscCall(MatProductNumeric(*C)); 9904 (*C)->symmetric = A->symmetric; 9905 (*C)->spd = A->spd; 9906 PetscFunctionReturn(PETSC_SUCCESS); 9907 } 9908 9909 /*@ 9910 MatRARt - Creates the matrix product C = R * A * R^T 9911 9912 Neighbor-wise Collective 9913 9914 Input Parameters: 9915 + A - the matrix 9916 . R - the projection matrix 9917 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9918 - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate 9919 if the result is a dense matrix this is irrelevant 9920 9921 Output Parameter: 9922 . C - the product matrix 9923 9924 Level: intermediate 9925 9926 Notes: 9927 C will be created and must be destroyed by the user with `MatDestroy()`. 9928 9929 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9930 9931 This routine is currently only implemented for pairs of `MATAIJ` matrices and classes 9932 which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes, 9933 parallel MatRARt is implemented via explicit transpose of R, which could be very expensive. 9934 We recommend using MatPtAP(). 9935 9936 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()` 9937 @*/ 9938 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C) 9939 { 9940 PetscFunctionBegin; 9941 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 9942 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9943 9944 if (scall == MAT_INITIAL_MATRIX) { 9945 PetscCall(MatProductCreate(A, R, NULL, C)); 9946 PetscCall(MatProductSetType(*C, MATPRODUCT_RARt)); 9947 PetscCall(MatProductSetAlgorithm(*C, "default")); 9948 PetscCall(MatProductSetFill(*C, fill)); 9949 9950 (*C)->product->api_user = PETSC_TRUE; 9951 PetscCall(MatProductSetFromOptions(*C)); 9952 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); 9953 PetscCall(MatProductSymbolic(*C)); 9954 } else { /* scall == MAT_REUSE_MATRIX */ 9955 PetscCall(MatProductReplaceMats(A, R, NULL, *C)); 9956 } 9957 9958 PetscCall(MatProductNumeric(*C)); 9959 if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 9960 PetscFunctionReturn(PETSC_SUCCESS); 9961 } 9962 9963 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C) 9964 { 9965 PetscFunctionBegin; 9966 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9967 9968 if (scall == MAT_INITIAL_MATRIX) { 9969 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype])); 9970 PetscCall(MatProductCreate(A, B, NULL, C)); 9971 PetscCall(MatProductSetType(*C, ptype)); 9972 PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT)); 9973 PetscCall(MatProductSetFill(*C, fill)); 9974 9975 (*C)->product->api_user = PETSC_TRUE; 9976 PetscCall(MatProductSetFromOptions(*C)); 9977 PetscCall(MatProductSymbolic(*C)); 9978 } else { /* scall == MAT_REUSE_MATRIX */ 9979 Mat_Product *product = (*C)->product; 9980 PetscBool isdense; 9981 9982 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, "")); 9983 if (isdense && product && product->type != ptype) { 9984 PetscCall(MatProductClear(*C)); 9985 product = NULL; 9986 } 9987 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype])); 9988 if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */ 9989 PetscCheck(isdense, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first"); 9990 PetscCall(MatProductCreate_Private(A, B, NULL, *C)); 9991 product = (*C)->product; 9992 product->fill = fill; 9993 product->api_user = PETSC_TRUE; 9994 product->clear = PETSC_TRUE; 9995 9996 PetscCall(MatProductSetType(*C, ptype)); 9997 PetscCall(MatProductSetFromOptions(*C)); 9998 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); 9999 PetscCall(MatProductSymbolic(*C)); 10000 } else { /* user may change input matrices A or B when REUSE */ 10001 PetscCall(MatProductReplaceMats(A, B, NULL, *C)); 10002 } 10003 } 10004 PetscCall(MatProductNumeric(*C)); 10005 PetscFunctionReturn(PETSC_SUCCESS); 10006 } 10007 10008 /*@ 10009 MatMatMult - Performs matrix-matrix multiplication C=A*B. 10010 10011 Neighbor-wise Collective 10012 10013 Input Parameters: 10014 + A - the left matrix 10015 . B - the right matrix 10016 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10017 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate 10018 if the result is a dense matrix this is irrelevant 10019 10020 Output Parameter: 10021 . C - the product matrix 10022 10023 Notes: 10024 Unless scall is `MAT_REUSE_MATRIX` C will be created. 10025 10026 `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 10027 call to this function with `MAT_INITIAL_MATRIX`. 10028 10029 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed. 10030 10031 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`, 10032 rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse. 10033 10034 Example of Usage: 10035 .vb 10036 MatProductCreate(A,B,NULL,&C); 10037 MatProductSetType(C,MATPRODUCT_AB); 10038 MatProductSymbolic(C); 10039 MatProductNumeric(C); // compute C=A * B 10040 MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1 10041 MatProductNumeric(C); 10042 MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1 10043 MatProductNumeric(C); 10044 .ve 10045 10046 Level: intermediate 10047 10048 .seealso: [](chapter_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()` 10049 @*/ 10050 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10051 { 10052 PetscFunctionBegin; 10053 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C)); 10054 PetscFunctionReturn(PETSC_SUCCESS); 10055 } 10056 10057 /*@ 10058 MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T. 10059 10060 Neighbor-wise Collective 10061 10062 Input Parameters: 10063 + A - the left matrix 10064 . B - the right matrix 10065 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10066 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 10067 10068 Output Parameter: 10069 . C - the product matrix 10070 10071 Level: intermediate 10072 10073 Notes: 10074 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10075 10076 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call 10077 10078 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10079 actually needed. 10080 10081 This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class, 10082 and for pairs of `MATMPIDENSE` matrices. 10083 10084 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt` 10085 10086 Options Database Keys: 10087 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the 10088 first redundantly copies the transposed B matrix on each process and requiers O(log P) communication complexity; 10089 the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity. 10090 10091 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductCreate()`, `MatProductAlgorithm`, `MatProductType`, `MATPRODUCT_ABt` 10092 @*/ 10093 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10094 { 10095 PetscFunctionBegin; 10096 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C)); 10097 if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10098 PetscFunctionReturn(PETSC_SUCCESS); 10099 } 10100 10101 /*@ 10102 MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B. 10103 10104 Neighbor-wise Collective 10105 10106 Input Parameters: 10107 + A - the left matrix 10108 . B - the right matrix 10109 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10110 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 10111 10112 Output Parameter: 10113 . C - the product matrix 10114 10115 Level: intermediate 10116 10117 Notes: 10118 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10119 10120 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call. 10121 10122 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB` 10123 10124 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10125 actually needed. 10126 10127 This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes 10128 which inherit from `MATSEQAIJ`. C will be of the same type as the input matrices. 10129 10130 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()` 10131 @*/ 10132 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10133 { 10134 PetscFunctionBegin; 10135 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C)); 10136 PetscFunctionReturn(PETSC_SUCCESS); 10137 } 10138 10139 /*@ 10140 MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C. 10141 10142 Neighbor-wise Collective 10143 10144 Input Parameters: 10145 + A - the left matrix 10146 . B - the middle matrix 10147 . C - the right matrix 10148 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10149 - 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 10150 if the result is a dense matrix this is irrelevant 10151 10152 Output Parameter: 10153 . D - the product matrix 10154 10155 Level: intermediate 10156 10157 Notes: 10158 Unless scall is `MAT_REUSE_MATRIX` D will be created. 10159 10160 `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call 10161 10162 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC` 10163 10164 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10165 actually needed. 10166 10167 If you have many matrices with the same non-zero structure to multiply, you 10168 should use `MAT_REUSE_MATRIX` in all calls but the first 10169 10170 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()` 10171 @*/ 10172 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D) 10173 { 10174 PetscFunctionBegin; 10175 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6); 10176 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10177 10178 if (scall == MAT_INITIAL_MATRIX) { 10179 PetscCall(MatProductCreate(A, B, C, D)); 10180 PetscCall(MatProductSetType(*D, MATPRODUCT_ABC)); 10181 PetscCall(MatProductSetAlgorithm(*D, "default")); 10182 PetscCall(MatProductSetFill(*D, fill)); 10183 10184 (*D)->product->api_user = PETSC_TRUE; 10185 PetscCall(MatProductSetFromOptions(*D)); 10186 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, 10187 ((PetscObject)C)->type_name); 10188 PetscCall(MatProductSymbolic(*D)); 10189 } else { /* user may change input matrices when REUSE */ 10190 PetscCall(MatProductReplaceMats(A, B, C, *D)); 10191 } 10192 PetscCall(MatProductNumeric(*D)); 10193 PetscFunctionReturn(PETSC_SUCCESS); 10194 } 10195 10196 /*@ 10197 MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators. 10198 10199 Collective 10200 10201 Input Parameters: 10202 + mat - the matrix 10203 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices) 10204 . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used) 10205 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10206 10207 Output Parameter: 10208 . matredundant - redundant matrix 10209 10210 Level: advanced 10211 10212 Notes: 10213 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 10214 original matrix has not changed from that last call to MatCreateRedundantMatrix(). 10215 10216 This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before 10217 calling it. 10218 10219 `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be. 10220 10221 .seealso: [](chapter_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubComm` 10222 @*/ 10223 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant) 10224 { 10225 MPI_Comm comm; 10226 PetscMPIInt size; 10227 PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs; 10228 Mat_Redundant *redund = NULL; 10229 PetscSubcomm psubcomm = NULL; 10230 MPI_Comm subcomm_in = subcomm; 10231 Mat *matseq; 10232 IS isrow, iscol; 10233 PetscBool newsubcomm = PETSC_FALSE; 10234 10235 PetscFunctionBegin; 10236 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10237 if (nsubcomm && reuse == MAT_REUSE_MATRIX) { 10238 PetscValidPointer(*matredundant, 5); 10239 PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5); 10240 } 10241 10242 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10243 if (size == 1 || nsubcomm == 1) { 10244 if (reuse == MAT_INITIAL_MATRIX) { 10245 PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant)); 10246 } else { 10247 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"); 10248 PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN)); 10249 } 10250 PetscFunctionReturn(PETSC_SUCCESS); 10251 } 10252 10253 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10254 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10255 MatCheckPreallocated(mat, 1); 10256 10257 PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0)); 10258 if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */ 10259 /* create psubcomm, then get subcomm */ 10260 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10261 PetscCallMPI(MPI_Comm_size(comm, &size)); 10262 PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size); 10263 10264 PetscCall(PetscSubcommCreate(comm, &psubcomm)); 10265 PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm)); 10266 PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS)); 10267 PetscCall(PetscSubcommSetFromOptions(psubcomm)); 10268 PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL)); 10269 newsubcomm = PETSC_TRUE; 10270 PetscCall(PetscSubcommDestroy(&psubcomm)); 10271 } 10272 10273 /* get isrow, iscol and a local sequential matrix matseq[0] */ 10274 if (reuse == MAT_INITIAL_MATRIX) { 10275 mloc_sub = PETSC_DECIDE; 10276 nloc_sub = PETSC_DECIDE; 10277 if (bs < 1) { 10278 PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M)); 10279 PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N)); 10280 } else { 10281 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M)); 10282 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N)); 10283 } 10284 PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm)); 10285 rstart = rend - mloc_sub; 10286 PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow)); 10287 PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol)); 10288 } else { /* reuse == MAT_REUSE_MATRIX */ 10289 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"); 10290 /* retrieve subcomm */ 10291 PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm)); 10292 redund = (*matredundant)->redundant; 10293 isrow = redund->isrow; 10294 iscol = redund->iscol; 10295 matseq = redund->matseq; 10296 } 10297 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq)); 10298 10299 /* get matredundant over subcomm */ 10300 if (reuse == MAT_INITIAL_MATRIX) { 10301 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant)); 10302 10303 /* create a supporting struct and attach it to C for reuse */ 10304 PetscCall(PetscNew(&redund)); 10305 (*matredundant)->redundant = redund; 10306 redund->isrow = isrow; 10307 redund->iscol = iscol; 10308 redund->matseq = matseq; 10309 if (newsubcomm) { 10310 redund->subcomm = subcomm; 10311 } else { 10312 redund->subcomm = MPI_COMM_NULL; 10313 } 10314 } else { 10315 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant)); 10316 } 10317 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 10318 if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) { 10319 PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE)); 10320 PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE)); 10321 } 10322 #endif 10323 PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0)); 10324 PetscFunctionReturn(PETSC_SUCCESS); 10325 } 10326 10327 /*@C 10328 MatGetMultiProcBlock - Create multiple 'parallel submatrices' from 10329 a given `Mat`. Each submatrix can span multiple procs. 10330 10331 Collective 10332 10333 Input Parameters: 10334 + mat - the matrix 10335 . subcomm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))` 10336 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10337 10338 Output Parameter: 10339 . subMat - parallel sub-matrices each spanning a given `subcomm` 10340 10341 Level: advanced 10342 10343 Notes: 10344 The submatrix partition across processors is dictated by `subComm` a 10345 communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm` 10346 is not restricted to be grouped with consecutive original ranks. 10347 10348 Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices 10349 map directly to the layout of the original matrix [wrt the local 10350 row,col partitioning]. So the original 'DiagonalMat' naturally maps 10351 into the 'DiagonalMat' of the `subMat`, hence it is used directly from 10352 the `subMat`. However the offDiagMat looses some columns - and this is 10353 reconstructed with `MatSetValues()` 10354 10355 This is used by `PCBJACOBI` when a single block spans multiple MPI ranks 10356 10357 .seealso: [](chapter_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI` 10358 @*/ 10359 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) 10360 { 10361 PetscMPIInt commsize, subCommSize; 10362 10363 PetscFunctionBegin; 10364 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize)); 10365 PetscCallMPI(MPI_Comm_size(subComm, &subCommSize)); 10366 PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize); 10367 10368 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"); 10369 PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10370 PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat); 10371 PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10372 PetscFunctionReturn(PETSC_SUCCESS); 10373 } 10374 10375 /*@ 10376 MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering 10377 10378 Not Collective 10379 10380 Input Parameters: 10381 + mat - matrix to extract local submatrix from 10382 . isrow - local row indices for submatrix 10383 - iscol - local column indices for submatrix 10384 10385 Output Parameter: 10386 . submat - the submatrix 10387 10388 Level: intermediate 10389 10390 Notes: 10391 `submat` should be disposed of with `MatRestoreLocalSubMatrix()`. 10392 10393 Depending on the format of `mat`, the returned submat may not implement `MatMult()`. Its communicator may be 10394 the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of `mat`'s. 10395 10396 `submat` always implements `MatSetValuesLocal()`. If `isrow` and `iscol` have the same block size, then 10397 `MatSetValuesBlockedLocal()` will also be implemented. 10398 10399 `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`. 10400 Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided. 10401 10402 .seealso: [](chapter_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()` 10403 @*/ 10404 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10405 { 10406 PetscFunctionBegin; 10407 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10408 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10409 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10410 PetscCheckSameComm(isrow, 2, iscol, 3); 10411 PetscValidPointer(submat, 4); 10412 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call"); 10413 10414 if (mat->ops->getlocalsubmatrix) { 10415 PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat); 10416 } else { 10417 PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat)); 10418 } 10419 PetscFunctionReturn(PETSC_SUCCESS); 10420 } 10421 10422 /*@ 10423 MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()` 10424 10425 Not Collective 10426 10427 Input Parameters: 10428 + mat - matrix to extract local submatrix from 10429 . isrow - local row indices for submatrix 10430 . iscol - local column indices for submatrix 10431 - submat - the submatrix 10432 10433 Level: intermediate 10434 10435 .seealso: [](chapter_matrices), `Mat`, `MatGetLocalSubMatrix()` 10436 @*/ 10437 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10438 { 10439 PetscFunctionBegin; 10440 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10441 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10442 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10443 PetscCheckSameComm(isrow, 2, iscol, 3); 10444 PetscValidPointer(submat, 4); 10445 if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4); 10446 10447 if (mat->ops->restorelocalsubmatrix) { 10448 PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat); 10449 } else { 10450 PetscCall(MatDestroy(submat)); 10451 } 10452 *submat = NULL; 10453 PetscFunctionReturn(PETSC_SUCCESS); 10454 } 10455 10456 /*@ 10457 MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix 10458 10459 Collective 10460 10461 Input Parameter: 10462 . mat - the matrix 10463 10464 Output Parameter: 10465 . is - if any rows have zero diagonals this contains the list of them 10466 10467 Level: developer 10468 10469 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10470 @*/ 10471 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is) 10472 { 10473 PetscFunctionBegin; 10474 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10475 PetscValidType(mat, 1); 10476 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10477 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10478 10479 if (!mat->ops->findzerodiagonals) { 10480 Vec diag; 10481 const PetscScalar *a; 10482 PetscInt *rows; 10483 PetscInt rStart, rEnd, r, nrow = 0; 10484 10485 PetscCall(MatCreateVecs(mat, &diag, NULL)); 10486 PetscCall(MatGetDiagonal(mat, diag)); 10487 PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd)); 10488 PetscCall(VecGetArrayRead(diag, &a)); 10489 for (r = 0; r < rEnd - rStart; ++r) 10490 if (a[r] == 0.0) ++nrow; 10491 PetscCall(PetscMalloc1(nrow, &rows)); 10492 nrow = 0; 10493 for (r = 0; r < rEnd - rStart; ++r) 10494 if (a[r] == 0.0) rows[nrow++] = r + rStart; 10495 PetscCall(VecRestoreArrayRead(diag, &a)); 10496 PetscCall(VecDestroy(&diag)); 10497 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is)); 10498 } else { 10499 PetscUseTypeMethod(mat, findzerodiagonals, is); 10500 } 10501 PetscFunctionReturn(PETSC_SUCCESS); 10502 } 10503 10504 /*@ 10505 MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size) 10506 10507 Collective 10508 10509 Input Parameter: 10510 . mat - the matrix 10511 10512 Output Parameter: 10513 . is - contains the list of rows with off block diagonal entries 10514 10515 Level: developer 10516 10517 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10518 @*/ 10519 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is) 10520 { 10521 PetscFunctionBegin; 10522 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10523 PetscValidType(mat, 1); 10524 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10525 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10526 10527 PetscUseTypeMethod(mat, findoffblockdiagonalentries, is); 10528 PetscFunctionReturn(PETSC_SUCCESS); 10529 } 10530 10531 /*@C 10532 MatInvertBlockDiagonal - Inverts the block diagonal entries. 10533 10534 Collective; No Fortran Support 10535 10536 Input Parameter: 10537 . mat - the matrix 10538 10539 Output Parameter: 10540 . values - the block inverses in column major order (FORTRAN-like) 10541 10542 Level: advanced 10543 10544 Notes: 10545 The size of the blocks is determined by the block size of the matrix. 10546 10547 The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case 10548 10549 The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size 10550 10551 .seealso: [](chapter_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()` 10552 @*/ 10553 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values) 10554 { 10555 PetscFunctionBegin; 10556 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10557 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10558 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10559 PetscUseTypeMethod(mat, invertblockdiagonal, values); 10560 PetscFunctionReturn(PETSC_SUCCESS); 10561 } 10562 10563 /*@C 10564 MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries. 10565 10566 Collective; No Fortran Support 10567 10568 Input Parameters: 10569 + mat - the matrix 10570 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()` 10571 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()` 10572 10573 Output Parameter: 10574 . values - the block inverses in column major order (FORTRAN-like) 10575 10576 Level: advanced 10577 10578 Notes: 10579 Use `MatInvertBlockDiagonal()` if all blocks have the same size 10580 10581 The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case 10582 10583 .seealso: [](chapter_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()` 10584 @*/ 10585 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values) 10586 { 10587 PetscFunctionBegin; 10588 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10589 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10590 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10591 PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values); 10592 PetscFunctionReturn(PETSC_SUCCESS); 10593 } 10594 10595 /*@ 10596 MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A 10597 10598 Collective 10599 10600 Input Parameters: 10601 + A - the matrix 10602 - C - matrix with inverted block diagonal of `A`. This matrix should be created and may have its type set. 10603 10604 Level: advanced 10605 10606 Note: 10607 The blocksize of the matrix is used to determine the blocks on the diagonal of `C` 10608 10609 .seealso: [](chapter_matrices), `Mat`, `MatInvertBlockDiagonal()` 10610 @*/ 10611 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C) 10612 { 10613 const PetscScalar *vals; 10614 PetscInt *dnnz; 10615 PetscInt m, rstart, rend, bs, i, j; 10616 10617 PetscFunctionBegin; 10618 PetscCall(MatInvertBlockDiagonal(A, &vals)); 10619 PetscCall(MatGetBlockSize(A, &bs)); 10620 PetscCall(MatGetLocalSize(A, &m, NULL)); 10621 PetscCall(MatSetLayouts(C, A->rmap, A->cmap)); 10622 PetscCall(PetscMalloc1(m / bs, &dnnz)); 10623 for (j = 0; j < m / bs; j++) dnnz[j] = 1; 10624 PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL)); 10625 PetscCall(PetscFree(dnnz)); 10626 PetscCall(MatGetOwnershipRange(C, &rstart, &rend)); 10627 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE)); 10628 for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES)); 10629 PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 10630 PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 10631 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE)); 10632 PetscFunctionReturn(PETSC_SUCCESS); 10633 } 10634 10635 /*@C 10636 MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created 10637 via `MatTransposeColoringCreate()`. 10638 10639 Collective 10640 10641 Input Parameter: 10642 . c - coloring context 10643 10644 Level: intermediate 10645 10646 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringCreate()` 10647 @*/ 10648 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c) 10649 { 10650 MatTransposeColoring matcolor = *c; 10651 10652 PetscFunctionBegin; 10653 if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS); 10654 if (--((PetscObject)matcolor)->refct > 0) { 10655 matcolor = NULL; 10656 PetscFunctionReturn(PETSC_SUCCESS); 10657 } 10658 10659 PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow)); 10660 PetscCall(PetscFree(matcolor->rows)); 10661 PetscCall(PetscFree(matcolor->den2sp)); 10662 PetscCall(PetscFree(matcolor->colorforcol)); 10663 PetscCall(PetscFree(matcolor->columns)); 10664 if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart)); 10665 PetscCall(PetscHeaderDestroy(c)); 10666 PetscFunctionReturn(PETSC_SUCCESS); 10667 } 10668 10669 /*@C 10670 MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which 10671 a `MatTransposeColoring` context has been created, computes a dense B^T by applying 10672 `MatTransposeColoring` to sparse B. 10673 10674 Collective 10675 10676 Input Parameters: 10677 + coloring - coloring context created with `MatTransposeColoringCreate()` 10678 - B - sparse matrix 10679 10680 Output Parameter: 10681 . Btdense - dense matrix B^T 10682 10683 Level: developer 10684 10685 Note: 10686 These are used internally for some implementations of `MatRARt()` 10687 10688 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()` 10689 @*/ 10690 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense) 10691 { 10692 PetscFunctionBegin; 10693 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 10694 PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3); 10695 PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10696 10697 PetscCall((B->ops->transcoloringapplysptoden)(coloring, B, Btdense)); 10698 PetscFunctionReturn(PETSC_SUCCESS); 10699 } 10700 10701 /*@C 10702 MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which 10703 a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense 10704 in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix 10705 `Csp` from `Cden`. 10706 10707 Collective 10708 10709 Input Parameters: 10710 + matcoloring - coloring context created with `MatTransposeColoringCreate()` 10711 - Cden - matrix product of a sparse matrix and a dense matrix Btdense 10712 10713 Output Parameter: 10714 . Csp - sparse matrix 10715 10716 Level: developer 10717 10718 Note: 10719 These are used internally for some implementations of `MatRARt()` 10720 10721 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()` 10722 @*/ 10723 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp) 10724 { 10725 PetscFunctionBegin; 10726 PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10727 PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2); 10728 PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3); 10729 10730 PetscCall((Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp)); 10731 PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY)); 10732 PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY)); 10733 PetscFunctionReturn(PETSC_SUCCESS); 10734 } 10735 10736 /*@C 10737 MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T. 10738 10739 Collective 10740 10741 Input Parameters: 10742 + mat - the matrix product C 10743 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()` 10744 10745 Output Parameter: 10746 . color - the new coloring context 10747 10748 Level: intermediate 10749 10750 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`, 10751 `MatTransColoringApplyDenToSp()` 10752 @*/ 10753 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color) 10754 { 10755 MatTransposeColoring c; 10756 MPI_Comm comm; 10757 10758 PetscFunctionBegin; 10759 PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10760 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10761 PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL)); 10762 10763 c->ctype = iscoloring->ctype; 10764 PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c); 10765 10766 *color = c; 10767 PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10768 PetscFunctionReturn(PETSC_SUCCESS); 10769 } 10770 10771 /*@ 10772 MatGetNonzeroState - Returns a 64 bit integer representing the current state of nonzeros in the matrix. If the 10773 matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the 10774 same, otherwise it will be larger 10775 10776 Not Collective 10777 10778 Input Parameter: 10779 . A - the matrix 10780 10781 Output Parameter: 10782 . state - the current state 10783 10784 Level: intermediate 10785 10786 Notes: 10787 You can only compare states from two different calls to the SAME matrix, you cannot compare calls between 10788 different matrices 10789 10790 Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix 10791 10792 Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers. 10793 10794 .seealso: [](chapter_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()` 10795 @*/ 10796 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state) 10797 { 10798 PetscFunctionBegin; 10799 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10800 *state = mat->nonzerostate; 10801 PetscFunctionReturn(PETSC_SUCCESS); 10802 } 10803 10804 /*@ 10805 MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential 10806 matrices from each processor 10807 10808 Collective 10809 10810 Input Parameters: 10811 + comm - the communicators the parallel matrix will live on 10812 . seqmat - the input sequential matrices 10813 . n - number of local columns (or `PETSC_DECIDE`) 10814 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10815 10816 Output Parameter: 10817 . mpimat - the parallel matrix generated 10818 10819 Level: developer 10820 10821 Note: 10822 The number of columns of the matrix in EACH processor MUST be the same. 10823 10824 .seealso: [](chapter_matrices), `Mat` 10825 @*/ 10826 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat) 10827 { 10828 PetscMPIInt size; 10829 10830 PetscFunctionBegin; 10831 PetscCallMPI(MPI_Comm_size(comm, &size)); 10832 if (size == 1) { 10833 if (reuse == MAT_INITIAL_MATRIX) { 10834 PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat)); 10835 } else { 10836 PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN)); 10837 } 10838 PetscFunctionReturn(PETSC_SUCCESS); 10839 } 10840 10841 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"); 10842 10843 PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0)); 10844 PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat)); 10845 PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0)); 10846 PetscFunctionReturn(PETSC_SUCCESS); 10847 } 10848 10849 /*@ 10850 MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent ranks' ownership ranges. 10851 10852 Collective 10853 10854 Input Parameters: 10855 + A - the matrix to create subdomains from 10856 - N - requested number of subdomains 10857 10858 Output Parameters: 10859 + n - number of subdomains resulting on this rank 10860 - iss - `IS` list with indices of subdomains on this rank 10861 10862 Level: advanced 10863 10864 Note: 10865 The number of subdomains must be smaller than the communicator size 10866 10867 .seealso: [](chapter_matrices), `Mat`, `IS` 10868 @*/ 10869 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[]) 10870 { 10871 MPI_Comm comm, subcomm; 10872 PetscMPIInt size, rank, color; 10873 PetscInt rstart, rend, k; 10874 10875 PetscFunctionBegin; 10876 PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 10877 PetscCallMPI(MPI_Comm_size(comm, &size)); 10878 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 10879 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); 10880 *n = 1; 10881 k = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */ 10882 color = rank / k; 10883 PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm)); 10884 PetscCall(PetscMalloc1(1, iss)); 10885 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 10886 PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0])); 10887 PetscCallMPI(MPI_Comm_free(&subcomm)); 10888 PetscFunctionReturn(PETSC_SUCCESS); 10889 } 10890 10891 /*@ 10892 MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection. 10893 10894 If the interpolation and restriction operators are the same, uses `MatPtAP()`. 10895 If they are not the same, uses `MatMatMatMult()`. 10896 10897 Once the coarse grid problem is constructed, correct for interpolation operators 10898 that are not of full rank, which can legitimately happen in the case of non-nested 10899 geometric multigrid. 10900 10901 Input Parameters: 10902 + restrct - restriction operator 10903 . dA - fine grid matrix 10904 . interpolate - interpolation operator 10905 . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10906 - fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate 10907 10908 Output Parameter: 10909 . A - the Galerkin coarse matrix 10910 10911 Options Database Key: 10912 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used 10913 10914 Level: developer 10915 10916 .seealso: [](chapter_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()` 10917 @*/ 10918 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A) 10919 { 10920 IS zerorows; 10921 Vec diag; 10922 10923 PetscFunctionBegin; 10924 PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10925 /* Construct the coarse grid matrix */ 10926 if (interpolate == restrct) { 10927 PetscCall(MatPtAP(dA, interpolate, reuse, fill, A)); 10928 } else { 10929 PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A)); 10930 } 10931 10932 /* If the interpolation matrix is not of full rank, A will have zero rows. 10933 This can legitimately happen in the case of non-nested geometric multigrid. 10934 In that event, we set the rows of the matrix to the rows of the identity, 10935 ignoring the equations (as the RHS will also be zero). */ 10936 10937 PetscCall(MatFindZeroRows(*A, &zerorows)); 10938 10939 if (zerorows != NULL) { /* if there are any zero rows */ 10940 PetscCall(MatCreateVecs(*A, &diag, NULL)); 10941 PetscCall(MatGetDiagonal(*A, diag)); 10942 PetscCall(VecISSet(diag, zerorows, 1.0)); 10943 PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES)); 10944 PetscCall(VecDestroy(&diag)); 10945 PetscCall(ISDestroy(&zerorows)); 10946 } 10947 PetscFunctionReturn(PETSC_SUCCESS); 10948 } 10949 10950 /*@C 10951 MatSetOperation - Allows user to set a matrix operation for any matrix type 10952 10953 Logically Collective 10954 10955 Input Parameters: 10956 + mat - the matrix 10957 . op - the name of the operation 10958 - f - the function that provides the operation 10959 10960 Level: developer 10961 10962 Usage: 10963 .vb 10964 extern PetscErrorCode usermult(Mat, Vec, Vec); 10965 10966 PetscCall(MatCreateXXX(comm, ..., &A)); 10967 PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFunction)usermult)); 10968 .ve 10969 10970 Notes: 10971 See the file `include/petscmat.h` for a complete list of matrix 10972 operations, which all have the form MATOP_<OPERATION>, where 10973 <OPERATION> is the name (in all capital letters) of the 10974 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 10975 10976 All user-provided functions (except for `MATOP_DESTROY`) should have the same calling 10977 sequence as the usual matrix interface routines, since they 10978 are intended to be accessed via the usual matrix interface 10979 routines, e.g., 10980 .vb 10981 MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec) 10982 .ve 10983 10984 In particular each function MUST return `PETSC_SUCCESS` on success and 10985 nonzero on failure. 10986 10987 This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type. 10988 10989 .seealso: [](chapter_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()` 10990 @*/ 10991 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void)) 10992 { 10993 PetscFunctionBegin; 10994 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10995 if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view; 10996 (((void (**)(void))mat->ops)[op]) = f; 10997 PetscFunctionReturn(PETSC_SUCCESS); 10998 } 10999 11000 /*@C 11001 MatGetOperation - Gets a matrix operation for any matrix type. 11002 11003 Not Collective 11004 11005 Input Parameters: 11006 + mat - the matrix 11007 - op - the name of the operation 11008 11009 Output Parameter: 11010 . f - the function that provides the operation 11011 11012 Level: developer 11013 11014 Usage: 11015 .vb 11016 PetscErrorCode (*usermult)(Mat, Vec, Vec); 11017 MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult); 11018 .ve 11019 11020 Notes: 11021 See the file include/petscmat.h for a complete list of matrix 11022 operations, which all have the form MATOP_<OPERATION>, where 11023 <OPERATION> is the name (in all capital letters) of the 11024 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11025 11026 This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type. 11027 11028 .seealso: [](chapter_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()` 11029 @*/ 11030 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void)) 11031 { 11032 PetscFunctionBegin; 11033 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11034 *f = (((void (**)(void))mat->ops)[op]); 11035 PetscFunctionReturn(PETSC_SUCCESS); 11036 } 11037 11038 /*@ 11039 MatHasOperation - Determines whether the given matrix supports the particular operation. 11040 11041 Not Collective 11042 11043 Input Parameters: 11044 + mat - the matrix 11045 - op - the operation, for example, `MATOP_GET_DIAGONAL` 11046 11047 Output Parameter: 11048 . has - either `PETSC_TRUE` or `PETSC_FALSE` 11049 11050 Level: advanced 11051 11052 Note: 11053 See `MatSetOperation()` for additional discussion on naming convention and usage of `op`. 11054 11055 .seealso: [](chapter_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()` 11056 @*/ 11057 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has) 11058 { 11059 PetscFunctionBegin; 11060 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11061 PetscValidBoolPointer(has, 3); 11062 if (mat->ops->hasoperation) { 11063 PetscUseTypeMethod(mat, hasoperation, op, has); 11064 } else { 11065 if (((void **)mat->ops)[op]) *has = PETSC_TRUE; 11066 else { 11067 *has = PETSC_FALSE; 11068 if (op == MATOP_CREATE_SUBMATRIX) { 11069 PetscMPIInt size; 11070 11071 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 11072 if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has)); 11073 } 11074 } 11075 } 11076 PetscFunctionReturn(PETSC_SUCCESS); 11077 } 11078 11079 /*@ 11080 MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent 11081 11082 Collective 11083 11084 Input Parameter: 11085 . mat - the matrix 11086 11087 Output Parameter: 11088 . cong - either `PETSC_TRUE` or `PETSC_FALSE` 11089 11090 Level: beginner 11091 11092 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout` 11093 @*/ 11094 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong) 11095 { 11096 PetscFunctionBegin; 11097 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11098 PetscValidType(mat, 1); 11099 PetscValidBoolPointer(cong, 2); 11100 if (!mat->rmap || !mat->cmap) { 11101 *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE; 11102 PetscFunctionReturn(PETSC_SUCCESS); 11103 } 11104 if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */ 11105 PetscCall(PetscLayoutSetUp(mat->rmap)); 11106 PetscCall(PetscLayoutSetUp(mat->cmap)); 11107 PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong)); 11108 if (*cong) mat->congruentlayouts = 1; 11109 else mat->congruentlayouts = 0; 11110 } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE; 11111 PetscFunctionReturn(PETSC_SUCCESS); 11112 } 11113 11114 PetscErrorCode MatSetInf(Mat A) 11115 { 11116 PetscFunctionBegin; 11117 PetscUseTypeMethod(A, setinf); 11118 PetscFunctionReturn(PETSC_SUCCESS); 11119 } 11120 11121 /*@C 11122 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 11123 and possibly removes small values from the graph structure. 11124 11125 Collective 11126 11127 Input Parameters: 11128 + A - the matrix 11129 . sym - `PETSC_TRUE` indicates that the graph should be symmetrized 11130 . scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry 11131 - filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value 11132 11133 Output Parameter: 11134 . graph - the resulting graph 11135 11136 Level: advanced 11137 11138 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `PCGAMG` 11139 @*/ 11140 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph) 11141 { 11142 PetscFunctionBegin; 11143 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11144 PetscValidType(A, 1); 11145 PetscValidLogicalCollectiveBool(A, scale, 3); 11146 PetscValidPointer(graph, 5); 11147 PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph); 11148 PetscFunctionReturn(PETSC_SUCCESS); 11149 } 11150 11151 /*@ 11152 MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place, 11153 meaning the same memory is used for the matrix, and no new memory is allocated. 11154 11155 Collective 11156 11157 Input Parameter: 11158 . A - the matrix 11159 11160 Level: intermediate 11161 11162 Developer Note: 11163 The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end 11164 of the arrays in the data structure are unneeded. 11165 11166 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatChop()` 11167 @*/ 11168 PetscErrorCode MatEliminateZeros(Mat A) 11169 { 11170 PetscFunctionBegin; 11171 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11172 PetscUseTypeMethod(A, eliminatezeros); 11173 PetscFunctionReturn(PETSC_SUCCESS); 11174 } 11175