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