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