1 /* 2 This is where the abstract matrix operations are defined 3 Portions of this code are under: 4 Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved. 5 */ 6 7 #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/ 8 #include <petsc/private/isimpl.h> 9 #include <petsc/private/vecimpl.h> 10 11 /* Logging support */ 12 PetscClassId MAT_CLASSID; 13 PetscClassId MAT_COLORING_CLASSID; 14 PetscClassId MAT_FDCOLORING_CLASSID; 15 PetscClassId MAT_TRANSPOSECOLORING_CLASSID; 16 17 PetscLogEvent MAT_Mult, MAT_MultAdd, MAT_MultTranspose; 18 PetscLogEvent MAT_MultTransposeAdd, MAT_Solve, MAT_Solves, MAT_SolveAdd, MAT_SolveTranspose, MAT_MatSolve, MAT_MatTrSolve; 19 PetscLogEvent MAT_SolveTransposeAdd, MAT_SOR, MAT_ForwardSolve, MAT_BackwardSolve, MAT_LUFactor, MAT_LUFactorSymbolic; 20 PetscLogEvent MAT_LUFactorNumeric, MAT_CholeskyFactor, MAT_CholeskyFactorSymbolic, MAT_CholeskyFactorNumeric, MAT_ILUFactor; 21 PetscLogEvent MAT_ILUFactorSymbolic, MAT_ICCFactorSymbolic, MAT_Copy, MAT_Convert, MAT_Scale, MAT_AssemblyBegin; 22 PetscLogEvent MAT_QRFactorNumeric, MAT_QRFactorSymbolic, MAT_QRFactor; 23 PetscLogEvent MAT_AssemblyEnd, MAT_SetValues, MAT_GetValues, MAT_GetRow, MAT_GetRowIJ, MAT_CreateSubMats, MAT_GetOrdering, MAT_RedundantMat, MAT_GetSeqNonzeroStructure; 24 PetscLogEvent MAT_IncreaseOverlap, MAT_Partitioning, MAT_PartitioningND, MAT_Coarsen, MAT_ZeroEntries, MAT_Load, MAT_View, MAT_AXPY, MAT_FDColoringCreate; 25 PetscLogEvent MAT_FDColoringSetUp, MAT_FDColoringApply, MAT_Transpose, MAT_FDColoringFunction, MAT_CreateSubMat; 26 PetscLogEvent MAT_TransposeColoringCreate; 27 PetscLogEvent MAT_MatMult, MAT_MatMultSymbolic, MAT_MatMultNumeric; 28 PetscLogEvent MAT_PtAP, MAT_PtAPSymbolic, MAT_PtAPNumeric, MAT_RARt, MAT_RARtSymbolic, MAT_RARtNumeric; 29 PetscLogEvent MAT_MatTransposeMult, MAT_MatTransposeMultSymbolic, MAT_MatTransposeMultNumeric; 30 PetscLogEvent MAT_TransposeMatMult, MAT_TransposeMatMultSymbolic, MAT_TransposeMatMultNumeric; 31 PetscLogEvent MAT_MatMatMult, MAT_MatMatMultSymbolic, MAT_MatMatMultNumeric; 32 PetscLogEvent MAT_MultHermitianTranspose, MAT_MultHermitianTransposeAdd; 33 PetscLogEvent MAT_Getsymtransreduced, MAT_GetBrowsOfAcols; 34 PetscLogEvent MAT_GetBrowsOfAocols, MAT_Getlocalmat, MAT_Getlocalmatcondensed, MAT_Seqstompi, MAT_Seqstompinum, MAT_Seqstompisym; 35 PetscLogEvent MAT_GetMultiProcBlock; 36 PetscLogEvent MAT_CUSPARSECopyToGPU, MAT_CUSPARSECopyFromGPU, MAT_CUSPARSEGenerateTranspose, MAT_CUSPARSESolveAnalysis; 37 PetscLogEvent MAT_HIPSPARSECopyToGPU, MAT_HIPSPARSECopyFromGPU, MAT_HIPSPARSEGenerateTranspose, MAT_HIPSPARSESolveAnalysis; 38 PetscLogEvent MAT_PreallCOO, MAT_SetVCOO; 39 PetscLogEvent MAT_SetValuesBatch; 40 PetscLogEvent MAT_ViennaCLCopyToGPU; 41 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU; 42 PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom; 43 PetscLogEvent MAT_FactorFactS, MAT_FactorInvS; 44 PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights; 45 PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR; 46 47 const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL}; 48 49 /*@ 50 MatSetRandom - Sets all components of a matrix to random numbers. 51 52 Logically Collective 53 54 Input Parameters: 55 + x - the matrix 56 - rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or `NULL` and 57 it will create one internally. 58 59 Example: 60 .vb 61 PetscRandomCreate(PETSC_COMM_WORLD,&rctx); 62 MatSetRandom(x,rctx); 63 PetscRandomDestroy(rctx); 64 .ve 65 66 Level: intermediate 67 68 Notes: 69 For sparse matrices that have been preallocated but not been assembled it randomly selects appropriate locations, 70 71 for sparse matrices that already have locations it fills the locations with random numbers. 72 73 It generates an error if used on sparse matrices that have not been preallocated. 74 75 .seealso: [](ch_matrices), `Mat`, `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomCreate()`, `PetscRandomDestroy()` 76 @*/ 77 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx) 78 { 79 PetscRandom randObj = NULL; 80 81 PetscFunctionBegin; 82 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 83 if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2); 84 PetscValidType(x, 1); 85 MatCheckPreallocated(x, 1); 86 87 if (!rctx) { 88 MPI_Comm comm; 89 PetscCall(PetscObjectGetComm((PetscObject)x, &comm)); 90 PetscCall(PetscRandomCreate(comm, &randObj)); 91 PetscCall(PetscRandomSetType(randObj, x->defaultrandtype)); 92 PetscCall(PetscRandomSetFromOptions(randObj)); 93 rctx = randObj; 94 } 95 PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0)); 96 PetscUseTypeMethod(x, setrandom, rctx); 97 PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0)); 98 99 PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY)); 100 PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY)); 101 PetscCall(PetscRandomDestroy(&randObj)); 102 PetscFunctionReturn(PETSC_SUCCESS); 103 } 104 105 /*@ 106 MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in 107 108 Logically Collective 109 110 Input Parameter: 111 . mat - the factored matrix 112 113 Output Parameters: 114 + pivot - the pivot value computed 115 - row - the row that the zero pivot occurred. This row value must be interpreted carefully due to row reorderings and which processes 116 the share the matrix 117 118 Level: advanced 119 120 Notes: 121 This routine does not work for factorizations done with external packages. 122 123 This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT` 124 125 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 126 127 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, 128 `MAT_FACTOR_NUMERIC_ZEROPIVOT` 129 @*/ 130 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row) 131 { 132 PetscFunctionBegin; 133 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 134 PetscValidRealPointer(pivot, 2); 135 PetscValidIntPointer(row, 3); 136 *pivot = mat->factorerror_zeropivot_value; 137 *row = mat->factorerror_zeropivot_row; 138 PetscFunctionReturn(PETSC_SUCCESS); 139 } 140 141 /*@ 142 MatFactorGetError - gets the error code from a factorization 143 144 Logically Collective 145 146 Input Parameter: 147 . mat - the factored matrix 148 149 Output Parameter: 150 . err - the error code 151 152 Level: advanced 153 154 Note: 155 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 156 157 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, 158 `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, `MatFactorError` 159 @*/ 160 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err) 161 { 162 PetscFunctionBegin; 163 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 164 PetscValidPointer(err, 2); 165 *err = mat->factorerrortype; 166 PetscFunctionReturn(PETSC_SUCCESS); 167 } 168 169 /*@ 170 MatFactorClearError - clears the error code in a factorization 171 172 Logically Collective 173 174 Input Parameter: 175 . mat - the factored matrix 176 177 Level: developer 178 179 Note: 180 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 181 182 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`, 183 `MatGetErrorCode()`, `MatFactorError` 184 @*/ 185 PetscErrorCode MatFactorClearError(Mat mat) 186 { 187 PetscFunctionBegin; 188 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 189 mat->factorerrortype = MAT_FACTOR_NOERROR; 190 mat->factorerror_zeropivot_value = 0.0; 191 mat->factorerror_zeropivot_row = 0; 192 PetscFunctionReturn(PETSC_SUCCESS); 193 } 194 195 PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero) 196 { 197 Vec r, l; 198 const PetscScalar *al; 199 PetscInt i, nz, gnz, N, n; 200 201 PetscFunctionBegin; 202 PetscCall(MatCreateVecs(mat, &r, &l)); 203 if (!cols) { /* nonzero rows */ 204 PetscCall(MatGetSize(mat, &N, NULL)); 205 PetscCall(MatGetLocalSize(mat, &n, NULL)); 206 PetscCall(VecSet(l, 0.0)); 207 PetscCall(VecSetRandom(r, NULL)); 208 PetscCall(MatMult(mat, r, l)); 209 PetscCall(VecGetArrayRead(l, &al)); 210 } else { /* nonzero columns */ 211 PetscCall(MatGetSize(mat, NULL, &N)); 212 PetscCall(MatGetLocalSize(mat, NULL, &n)); 213 PetscCall(VecSet(r, 0.0)); 214 PetscCall(VecSetRandom(l, NULL)); 215 PetscCall(MatMultTranspose(mat, l, r)); 216 PetscCall(VecGetArrayRead(r, &al)); 217 } 218 if (tol <= 0.0) { 219 for (i = 0, nz = 0; i < n; i++) 220 if (al[i] != 0.0) nz++; 221 } else { 222 for (i = 0, nz = 0; i < n; i++) 223 if (PetscAbsScalar(al[i]) > tol) nz++; 224 } 225 PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 226 if (gnz != N) { 227 PetscInt *nzr; 228 PetscCall(PetscMalloc1(nz, &nzr)); 229 if (nz) { 230 if (tol < 0) { 231 for (i = 0, nz = 0; i < n; i++) 232 if (al[i] != 0.0) nzr[nz++] = i; 233 } else { 234 for (i = 0, nz = 0; i < n; i++) 235 if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i; 236 } 237 } 238 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero)); 239 } else *nonzero = NULL; 240 if (!cols) { /* nonzero rows */ 241 PetscCall(VecRestoreArrayRead(l, &al)); 242 } else { 243 PetscCall(VecRestoreArrayRead(r, &al)); 244 } 245 PetscCall(VecDestroy(&l)); 246 PetscCall(VecDestroy(&r)); 247 PetscFunctionReturn(PETSC_SUCCESS); 248 } 249 250 /*@ 251 MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix 252 253 Input Parameter: 254 . A - the matrix 255 256 Output Parameter: 257 . keptrows - the rows that are not completely zero 258 259 Level: intermediate 260 261 Note: 262 `keptrows` is set to `NULL` if all rows are nonzero. 263 264 .seealso: [](ch_matrices), `Mat`, `MatFindZeroRows()` 265 @*/ 266 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows) 267 { 268 PetscFunctionBegin; 269 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 270 PetscValidType(mat, 1); 271 PetscValidPointer(keptrows, 2); 272 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 273 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 274 if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows); 275 else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows)); 276 PetscFunctionReturn(PETSC_SUCCESS); 277 } 278 279 /*@ 280 MatFindZeroRows - Locate all rows that are completely zero in the matrix 281 282 Input Parameter: 283 . A - the matrix 284 285 Output Parameter: 286 . zerorows - the rows that are completely zero 287 288 Level: intermediate 289 290 Note: 291 `zerorows` is set to `NULL` if no rows are zero. 292 293 .seealso: [](ch_matrices), `Mat`, `MatFindNonzeroRows()` 294 @*/ 295 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows) 296 { 297 IS keptrows; 298 PetscInt m, n; 299 300 PetscFunctionBegin; 301 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 302 PetscValidType(mat, 1); 303 PetscValidPointer(zerorows, 2); 304 PetscCall(MatFindNonzeroRows(mat, &keptrows)); 305 /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows. 306 In keeping with this convention, we set zerorows to NULL if there are no zero 307 rows. */ 308 if (keptrows == NULL) { 309 *zerorows = NULL; 310 } else { 311 PetscCall(MatGetOwnershipRange(mat, &m, &n)); 312 PetscCall(ISComplement(keptrows, m, n, zerorows)); 313 PetscCall(ISDestroy(&keptrows)); 314 } 315 PetscFunctionReturn(PETSC_SUCCESS); 316 } 317 318 /*@ 319 MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling 320 321 Not Collective 322 323 Input Parameter: 324 . A - the matrix 325 326 Output Parameter: 327 . a - the diagonal part (which is a SEQUENTIAL matrix) 328 329 Level: advanced 330 331 Notes: 332 See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix. 333 334 Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation. 335 336 .seealso: [](ch_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ` 337 @*/ 338 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a) 339 { 340 PetscFunctionBegin; 341 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 342 PetscValidType(A, 1); 343 PetscValidPointer(a, 2); 344 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 345 if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a); 346 else { 347 PetscMPIInt size; 348 349 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 350 PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name); 351 *a = A; 352 } 353 PetscFunctionReturn(PETSC_SUCCESS); 354 } 355 356 /*@ 357 MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries. 358 359 Collective 360 361 Input Parameter: 362 . mat - the matrix 363 364 Output Parameter: 365 . trace - the sum of the diagonal entries 366 367 Level: advanced 368 369 .seealso: [](ch_matrices), `Mat` 370 @*/ 371 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace) 372 { 373 Vec diag; 374 375 PetscFunctionBegin; 376 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 377 PetscValidScalarPointer(trace, 2); 378 PetscCall(MatCreateVecs(mat, &diag, NULL)); 379 PetscCall(MatGetDiagonal(mat, diag)); 380 PetscCall(VecSum(diag, trace)); 381 PetscCall(VecDestroy(&diag)); 382 PetscFunctionReturn(PETSC_SUCCESS); 383 } 384 385 /*@ 386 MatRealPart - Zeros out the imaginary part of the matrix 387 388 Logically Collective 389 390 Input Parameter: 391 . mat - the matrix 392 393 Level: advanced 394 395 .seealso: [](ch_matrices), `Mat`, `MatImaginaryPart()` 396 @*/ 397 PetscErrorCode MatRealPart(Mat mat) 398 { 399 PetscFunctionBegin; 400 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 401 PetscValidType(mat, 1); 402 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 403 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 404 MatCheckPreallocated(mat, 1); 405 PetscUseTypeMethod(mat, realpart); 406 PetscFunctionReturn(PETSC_SUCCESS); 407 } 408 409 /*@C 410 MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix 411 412 Collective 413 414 Input Parameter: 415 . mat - the matrix 416 417 Output Parameters: 418 + nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each block) 419 - ghosts - the global indices of the ghost points 420 421 Level: advanced 422 423 Note: 424 `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()` 425 426 .seealso: [](ch_matrices), `Mat`, `VecCreateGhost()` 427 @*/ 428 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[]) 429 { 430 PetscFunctionBegin; 431 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 432 PetscValidType(mat, 1); 433 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 434 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 435 if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts); 436 else { 437 if (nghosts) *nghosts = 0; 438 if (ghosts) *ghosts = NULL; 439 } 440 PetscFunctionReturn(PETSC_SUCCESS); 441 } 442 443 /*@ 444 MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part 445 446 Logically Collective 447 448 Input Parameter: 449 . mat - the matrix 450 451 Level: advanced 452 453 .seealso: [](ch_matrices), `Mat`, `MatRealPart()` 454 @*/ 455 PetscErrorCode MatImaginaryPart(Mat mat) 456 { 457 PetscFunctionBegin; 458 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 459 PetscValidType(mat, 1); 460 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 461 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 462 MatCheckPreallocated(mat, 1); 463 PetscUseTypeMethod(mat, imaginarypart); 464 PetscFunctionReturn(PETSC_SUCCESS); 465 } 466 467 /*@ 468 MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices) 469 470 Not Collective 471 472 Input Parameter: 473 . mat - the matrix 474 475 Output Parameters: 476 + missing - is any diagonal missing 477 - dd - first diagonal entry that is missing (optional) on this process 478 479 Level: advanced 480 481 .seealso: [](ch_matrices), `Mat` 482 @*/ 483 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd) 484 { 485 PetscFunctionBegin; 486 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 487 PetscValidType(mat, 1); 488 PetscValidBoolPointer(missing, 2); 489 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name); 490 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 491 PetscUseTypeMethod(mat, missingdiagonal, missing, dd); 492 PetscFunctionReturn(PETSC_SUCCESS); 493 } 494 495 /*@C 496 MatGetRow - Gets a row of a matrix. You MUST call `MatRestoreRow()` 497 for each row that you get to ensure that your application does 498 not bleed memory. 499 500 Not Collective 501 502 Input Parameters: 503 + mat - the matrix 504 - row - the row to get 505 506 Output Parameters: 507 + ncols - if not `NULL`, the number of nonzeros in the row 508 . cols - if not `NULL`, the column numbers 509 - vals - if not `NULL`, the values 510 511 Level: advanced 512 513 Notes: 514 This routine is provided for people who need to have direct access 515 to the structure of a matrix. We hope that we provide enough 516 high-level matrix routines that few users will need it. 517 518 `MatGetRow()` always returns 0-based column indices, regardless of 519 whether the internal representation is 0-based (default) or 1-based. 520 521 For better efficiency, set cols and/or vals to `NULL` if you do 522 not wish to extract these quantities. 523 524 The user can only examine the values extracted with `MatGetRow()`; 525 the values cannot be altered. To change the matrix entries, one 526 must use `MatSetValues()`. 527 528 You can only have one call to `MatGetRow()` outstanding for a particular 529 matrix at a time, per processor. `MatGetRow()` can only obtain rows 530 associated with the given processor, it cannot get rows from the 531 other processors; for that we suggest using `MatCreateSubMatrices()`, then 532 MatGetRow() on the submatrix. The row index passed to `MatGetRow()` 533 is in the global number of rows. 534 535 Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix. 536 537 Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly. 538 539 Fortran Note: 540 The calling sequence is 541 .vb 542 MatGetRow(matrix,row,ncols,cols,values,ierr) 543 Mat matrix (input) 544 integer row (input) 545 integer ncols (output) 546 integer cols(maxcols) (output) 547 double precision (or double complex) values(maxcols) output 548 .ve 549 where maxcols >= maximum nonzeros in any row of the matrix. 550 551 Caution: 552 Do not try to change the contents of the output arrays (`cols` and `vals`). 553 In some cases, this may corrupt the matrix. 554 555 .seealso: [](ch_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()` 556 @*/ 557 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 558 { 559 PetscInt incols; 560 561 PetscFunctionBegin; 562 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 563 PetscValidType(mat, 1); 564 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 565 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 566 MatCheckPreallocated(mat, 1); 567 PetscCheck(row >= mat->rmap->rstart && row < mat->rmap->rend, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Only for local rows, %" PetscInt_FMT " not in [%" PetscInt_FMT ",%" PetscInt_FMT ")", row, mat->rmap->rstart, mat->rmap->rend); 568 PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0)); 569 PetscUseTypeMethod(mat, getrow, row, &incols, (PetscInt **)cols, (PetscScalar **)vals); 570 if (ncols) *ncols = incols; 571 PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0)); 572 PetscFunctionReturn(PETSC_SUCCESS); 573 } 574 575 /*@ 576 MatConjugate - replaces the matrix values with their complex conjugates 577 578 Logically Collective 579 580 Input Parameter: 581 . mat - the matrix 582 583 Level: advanced 584 585 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()` 586 @*/ 587 PetscErrorCode MatConjugate(Mat mat) 588 { 589 PetscFunctionBegin; 590 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 591 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 592 if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) { 593 PetscUseTypeMethod(mat, conjugate); 594 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 595 } 596 PetscFunctionReturn(PETSC_SUCCESS); 597 } 598 599 /*@C 600 MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`. 601 602 Not Collective 603 604 Input Parameters: 605 + mat - the matrix 606 . row - the row to get 607 . ncols - the number of nonzeros 608 . cols - the columns of the nonzeros 609 - vals - if nonzero the column values 610 611 Level: advanced 612 613 Notes: 614 This routine should be called after you have finished examining the entries. 615 616 This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental 617 us of the array after it has been restored. If you pass `NULL`, it will 618 not zero the pointers. Use of `cols` or `vals` after `MatRestoreRow()` is invalid. 619 620 Fortran Notes: 621 The calling sequence is 622 .vb 623 MatRestoreRow(matrix,row,ncols,cols,values,ierr) 624 Mat matrix (input) 625 integer row (input) 626 integer ncols (output) 627 integer cols(maxcols) (output) 628 double precision (or double complex) values(maxcols) output 629 .ve 630 Where maxcols >= maximum nonzeros in any row of the matrix. 631 632 In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()` 633 before another call to `MatGetRow()` can be made. 634 635 .seealso: [](ch_matrices), `Mat`, `MatGetRow()` 636 @*/ 637 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 638 { 639 PetscFunctionBegin; 640 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 641 if (ncols) PetscValidIntPointer(ncols, 3); 642 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 643 if (!mat->ops->restorerow) PetscFunctionReturn(PETSC_SUCCESS); 644 PetscUseTypeMethod(mat, restorerow, row, ncols, (PetscInt **)cols, (PetscScalar **)vals); 645 if (ncols) *ncols = 0; 646 if (cols) *cols = NULL; 647 if (vals) *vals = NULL; 648 PetscFunctionReturn(PETSC_SUCCESS); 649 } 650 651 /*@ 652 MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 653 You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag. 654 655 Not Collective 656 657 Input Parameter: 658 . mat - the matrix 659 660 Level: advanced 661 662 Note: 663 The flag is to ensure that users are aware that `MatGetRow()` only provides the upper triangular part of the row for the matrices in `MATSBAIJ` format. 664 665 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()` 666 @*/ 667 PetscErrorCode MatGetRowUpperTriangular(Mat mat) 668 { 669 PetscFunctionBegin; 670 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 671 PetscValidType(mat, 1); 672 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 673 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 674 MatCheckPreallocated(mat, 1); 675 if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS); 676 PetscUseTypeMethod(mat, getrowuppertriangular); 677 PetscFunctionReturn(PETSC_SUCCESS); 678 } 679 680 /*@ 681 MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 682 683 Not Collective 684 685 Input Parameter: 686 . mat - the matrix 687 688 Level: advanced 689 690 Note: 691 This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`. 692 693 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()` 694 @*/ 695 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat) 696 { 697 PetscFunctionBegin; 698 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 699 PetscValidType(mat, 1); 700 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 701 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 702 MatCheckPreallocated(mat, 1); 703 if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS); 704 PetscUseTypeMethod(mat, restorerowuppertriangular); 705 PetscFunctionReturn(PETSC_SUCCESS); 706 } 707 708 /*@C 709 MatSetOptionsPrefix - Sets the prefix used for searching for all 710 `Mat` options in the database. 711 712 Logically Collective 713 714 Input Parameters: 715 + A - the matrix 716 - prefix - the prefix to prepend to all option names 717 718 Level: advanced 719 720 Notes: 721 A hyphen (-) must NOT be given at the beginning of the prefix name. 722 The first character of all runtime options is AUTOMATICALLY the hyphen. 723 724 This is NOT used for options for the factorization of the matrix. Normally the 725 prefix is automatically passed in from the PC calling the factorization. To set 726 it directly use `MatSetOptionsPrefixFactor()` 727 728 .seealso: [](ch_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()` 729 @*/ 730 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[]) 731 { 732 PetscFunctionBegin; 733 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 734 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix)); 735 PetscFunctionReturn(PETSC_SUCCESS); 736 } 737 738 /*@C 739 MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for 740 for matrices created with `MatGetFactor()` 741 742 Logically Collective 743 744 Input Parameters: 745 + A - the matrix 746 - prefix - the prefix to prepend to all option names for the factored matrix 747 748 Level: developer 749 750 Notes: 751 A hyphen (-) must NOT be given at the beginning of the prefix name. 752 The first character of all runtime options is AUTOMATICALLY the hyphen. 753 754 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 755 it directly when not using `KSP`/`PC` use `MatSetOptionsPrefixFactor()` 756 757 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()` 758 @*/ 759 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[]) 760 { 761 PetscFunctionBegin; 762 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 763 if (prefix) { 764 PetscValidCharPointer(prefix, 2); 765 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 766 if (prefix != A->factorprefix) { 767 PetscCall(PetscFree(A->factorprefix)); 768 PetscCall(PetscStrallocpy(prefix, &A->factorprefix)); 769 } 770 } else PetscCall(PetscFree(A->factorprefix)); 771 PetscFunctionReturn(PETSC_SUCCESS); 772 } 773 774 /*@C 775 MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for 776 for matrices created with `MatGetFactor()` 777 778 Logically Collective 779 780 Input Parameters: 781 + A - the matrix 782 - prefix - the prefix to prepend to all option names for the factored matrix 783 784 Level: developer 785 786 Notes: 787 A hyphen (-) must NOT be given at the beginning of the prefix name. 788 The first character of all runtime options is AUTOMATICALLY the hyphen. 789 790 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 791 it directly when not using `KSP`/`PC` use `MatAppendOptionsPrefixFactor()` 792 793 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`, 794 `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`, 795 `MatSetOptionsPrefix()` 796 @*/ 797 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[]) 798 { 799 size_t len1, len2, new_len; 800 801 PetscFunctionBegin; 802 PetscValidHeader(A, 1); 803 if (!prefix) PetscFunctionReturn(PETSC_SUCCESS); 804 if (!A->factorprefix) { 805 PetscCall(MatSetOptionsPrefixFactor(A, prefix)); 806 PetscFunctionReturn(PETSC_SUCCESS); 807 } 808 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 809 810 PetscCall(PetscStrlen(A->factorprefix, &len1)); 811 PetscCall(PetscStrlen(prefix, &len2)); 812 new_len = len1 + len2 + 1; 813 PetscCall(PetscRealloc(new_len * sizeof(*(A->factorprefix)), &A->factorprefix)); 814 PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1)); 815 PetscFunctionReturn(PETSC_SUCCESS); 816 } 817 818 /*@C 819 MatAppendOptionsPrefix - Appends to the prefix used for searching for all 820 matrix options in the database. 821 822 Logically Collective 823 824 Input Parameters: 825 + A - the matrix 826 - prefix - the prefix to prepend to all option names 827 828 Level: advanced 829 830 Note: 831 A hyphen (-) must NOT be given at the beginning of the prefix name. 832 The first character of all runtime options is AUTOMATICALLY the hyphen. 833 834 .seealso: [](ch_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()` 835 @*/ 836 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[]) 837 { 838 PetscFunctionBegin; 839 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 840 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix)); 841 PetscFunctionReturn(PETSC_SUCCESS); 842 } 843 844 /*@C 845 MatGetOptionsPrefix - Gets the prefix used for searching for all 846 matrix options in the database. 847 848 Not Collective 849 850 Input Parameter: 851 . A - the matrix 852 853 Output Parameter: 854 . prefix - pointer to the prefix string used 855 856 Level: advanced 857 858 Fortran Note: 859 The user should pass in a string `prefix` of 860 sufficient length to hold the prefix. 861 862 .seealso: [](ch_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()` 863 @*/ 864 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[]) 865 { 866 PetscFunctionBegin; 867 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 868 PetscValidPointer(prefix, 2); 869 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix)); 870 PetscFunctionReturn(PETSC_SUCCESS); 871 } 872 873 /*@ 874 MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by users. 875 876 Collective 877 878 Input Parameter: 879 . A - the matrix 880 881 Level: beginner 882 883 Notes: 884 The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`. 885 886 Users can reset the preallocation to access the original memory. 887 888 Currently only supported for `MATAIJ` matrices. 889 890 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()` 891 @*/ 892 PetscErrorCode MatResetPreallocation(Mat A) 893 { 894 PetscFunctionBegin; 895 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 896 PetscValidType(A, 1); 897 PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A)); 898 PetscFunctionReturn(PETSC_SUCCESS); 899 } 900 901 /*@ 902 MatSetUp - Sets up the internal matrix data structures for later use. 903 904 Collective 905 906 Input Parameter: 907 . A - the matrix 908 909 Level: intermediate 910 911 Notes: 912 If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of 913 setting values in the matrix. 914 915 If a suitable preallocation routine is used, this function does not need to be called. 916 917 This routine is called internally by other matrix functions when needed so rarely needs to be called by users 918 919 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()` 920 @*/ 921 PetscErrorCode MatSetUp(Mat A) 922 { 923 PetscFunctionBegin; 924 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 925 if (!((PetscObject)A)->type_name) { 926 PetscMPIInt size; 927 928 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 929 PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ)); 930 } 931 if (!A->preallocated) PetscTryTypeMethod(A, setup); 932 PetscCall(PetscLayoutSetUp(A->rmap)); 933 PetscCall(PetscLayoutSetUp(A->cmap)); 934 A->preallocated = PETSC_TRUE; 935 PetscFunctionReturn(PETSC_SUCCESS); 936 } 937 938 #if defined(PETSC_HAVE_SAWS) 939 #include <petscviewersaws.h> 940 #endif 941 942 /*@C 943 MatViewFromOptions - View properties of the matrix based on options set in the options database 944 945 Collective 946 947 Input Parameters: 948 + A - the matrix 949 . obj - optional additional object that provides the options prefix to use 950 - name - command line option 951 952 Options Database Key: 953 . -mat_view [viewertype]:... - the viewer and its options 954 955 Level: intermediate 956 957 Notes: 958 .vb 959 If no value is provided ascii:stdout is used 960 ascii[:[filename][:[format][:append]]] defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab, 961 for example ascii::ascii_info prints just the information about the object not all details 962 unless :append is given filename opens in write mode, overwriting what was already there 963 binary[:[filename][:[format][:append]]] defaults to the file binaryoutput 964 draw[:drawtype[:filename]] for example, draw:tikz, draw:tikz:figure.tex or draw:x 965 socket[:port] defaults to the standard output port 966 saws[:communicatorname] publishes object to the Scientific Application Webserver (SAWs) 967 .ve 968 969 .seealso: [](ch_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()` 970 @*/ 971 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[]) 972 { 973 PetscFunctionBegin; 974 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 975 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 976 PetscFunctionReturn(PETSC_SUCCESS); 977 } 978 979 /*@C 980 MatView - display information about a matrix in a variety ways 981 982 Collective 983 984 Input Parameters: 985 + mat - the matrix 986 - viewer - visualization context 987 988 Options Database Keys: 989 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 990 . -mat_view ::ascii_info_detail - Prints more detailed info 991 . -mat_view - Prints matrix in ASCII format 992 . -mat_view ::ascii_matlab - Prints matrix in Matlab format 993 . -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 994 . -display <name> - Sets display name (default is host) 995 . -draw_pause <sec> - Sets number of seconds to pause after display 996 . -mat_view socket - Sends matrix to socket, can be accessed from Matlab (see Users-Manual: ch_matlab for details) 997 . -viewer_socket_machine <machine> - 998 . -viewer_socket_port <port> - 999 . -mat_view binary - save matrix to file in binary format 1000 - -viewer_binary_filename <name> - 1001 1002 Level: beginner 1003 1004 Notes: 1005 The available visualization contexts include 1006 + `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices 1007 . `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD` 1008 . `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm 1009 - `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure 1010 1011 The user can open alternative visualization contexts with 1012 + `PetscViewerASCIIOpen()` - Outputs matrix to a specified file 1013 . `PetscViewerBinaryOpen()` - Outputs matrix in binary to a 1014 specified file; corresponding input uses MatLoad() 1015 . `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to 1016 an X window display 1017 - `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer. 1018 Currently only the sequential dense and AIJ 1019 matrix types support the Socket viewer. 1020 1021 The user can call `PetscViewerPushFormat()` to specify the output 1022 format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`, 1023 `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`). Available formats include 1024 + `PETSC_VIEWER_DEFAULT` - default, prints matrix contents 1025 . `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in Matlab format 1026 . `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros 1027 . `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse 1028 format common among all matrix types 1029 . `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific 1030 format (which is in many cases the same as the default) 1031 . `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix 1032 size and structure (not the matrix entries) 1033 - `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about 1034 the matrix structure 1035 1036 The ASCII viewers are only recommended for small matrices on at most a moderate number of processes, 1037 the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format. 1038 1039 In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer). 1040 1041 See the manual page for `MatLoad()` for the exact format of the binary file when the binary 1042 viewer is used. 1043 1044 See share/petsc/matlab/PetscBinaryRead.m for a Matlab code that can read in the binary file when the binary 1045 viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python. 1046 1047 One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure, 1048 and then use the following mouse functions. 1049 .vb 1050 left mouse: zoom in 1051 middle mouse: zoom out 1052 right mouse: continue with the simulation 1053 .ve 1054 1055 .seealso: [](ch_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`, 1056 `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()` 1057 @*/ 1058 PetscErrorCode MatView(Mat mat, PetscViewer viewer) 1059 { 1060 PetscInt rows, cols, rbs, cbs; 1061 PetscBool isascii, isstring, issaws; 1062 PetscViewerFormat format; 1063 PetscMPIInt size; 1064 1065 PetscFunctionBegin; 1066 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1067 PetscValidType(mat, 1); 1068 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer)); 1069 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1070 PetscCheckSameComm(mat, 1, viewer, 2); 1071 1072 PetscCall(PetscViewerGetFormat(viewer, &format)); 1073 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 1074 if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS); 1075 1076 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 1077 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 1078 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws)); 1079 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"); 1080 1081 PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0)); 1082 if (isascii) { 1083 if (!mat->preallocated) { 1084 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n")); 1085 PetscFunctionReturn(PETSC_SUCCESS); 1086 } 1087 if (!mat->assembled) { 1088 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n")); 1089 PetscFunctionReturn(PETSC_SUCCESS); 1090 } 1091 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer)); 1092 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1093 MatNullSpace nullsp, transnullsp; 1094 1095 PetscCall(PetscViewerASCIIPushTab(viewer)); 1096 PetscCall(MatGetSize(mat, &rows, &cols)); 1097 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1098 if (rbs != 1 || cbs != 1) { 1099 if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs)); 1100 else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs)); 1101 } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols)); 1102 if (mat->factortype) { 1103 MatSolverType solver; 1104 PetscCall(MatFactorGetSolverType(mat, &solver)); 1105 PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver)); 1106 } 1107 if (mat->ops->getinfo) { 1108 MatInfo info; 1109 PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info)); 1110 PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated)); 1111 if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs)); 1112 } 1113 PetscCall(MatGetNullSpace(mat, &nullsp)); 1114 PetscCall(MatGetTransposeNullSpace(mat, &transnullsp)); 1115 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached null space\n")); 1116 if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached transposed null space\n")); 1117 PetscCall(MatGetNearNullSpace(mat, &nullsp)); 1118 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached near null space\n")); 1119 PetscCall(PetscViewerASCIIPushTab(viewer)); 1120 PetscCall(MatProductView(mat, viewer)); 1121 PetscCall(PetscViewerASCIIPopTab(viewer)); 1122 } 1123 } else if (issaws) { 1124 #if defined(PETSC_HAVE_SAWS) 1125 PetscMPIInt rank; 1126 1127 PetscCall(PetscObjectName((PetscObject)mat)); 1128 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 1129 if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer)); 1130 #endif 1131 } else if (isstring) { 1132 const char *type; 1133 PetscCall(MatGetType(mat, &type)); 1134 PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type)); 1135 PetscTryTypeMethod(mat, view, viewer); 1136 } 1137 if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) { 1138 PetscCall(PetscViewerASCIIPushTab(viewer)); 1139 PetscUseTypeMethod(mat, viewnative, viewer); 1140 PetscCall(PetscViewerASCIIPopTab(viewer)); 1141 } else if (mat->ops->view) { 1142 PetscCall(PetscViewerASCIIPushTab(viewer)); 1143 PetscUseTypeMethod(mat, view, viewer); 1144 PetscCall(PetscViewerASCIIPopTab(viewer)); 1145 } 1146 if (isascii) { 1147 PetscCall(PetscViewerGetFormat(viewer, &format)); 1148 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer)); 1149 } 1150 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1151 PetscFunctionReturn(PETSC_SUCCESS); 1152 } 1153 1154 #if defined(PETSC_USE_DEBUG) 1155 #include <../src/sys/totalview/tv_data_display.h> 1156 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat) 1157 { 1158 TV_add_row("Local rows", "int", &mat->rmap->n); 1159 TV_add_row("Local columns", "int", &mat->cmap->n); 1160 TV_add_row("Global rows", "int", &mat->rmap->N); 1161 TV_add_row("Global columns", "int", &mat->cmap->N); 1162 TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name); 1163 return TV_format_OK; 1164 } 1165 #endif 1166 1167 /*@C 1168 MatLoad - Loads a matrix that has been stored in binary/HDF5 format 1169 with `MatView()`. The matrix format is determined from the options database. 1170 Generates a parallel MPI matrix if the communicator has more than one 1171 processor. The default matrix type is `MATAIJ`. 1172 1173 Collective 1174 1175 Input Parameters: 1176 + mat - the newly loaded matrix, this needs to have been created with `MatCreate()` 1177 or some related function before a call to `MatLoad()` 1178 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer 1179 1180 Options Database Keys: 1181 Used with block matrix formats (`MATSEQBAIJ`, ...) to specify 1182 block size 1183 . -matload_block_size <bs> - set block size 1184 1185 Level: beginner 1186 1187 Notes: 1188 If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the 1189 `Mat` before calling this routine if you wish to set it from the options database. 1190 1191 `MatLoad()` automatically loads into the options database any options 1192 given in the file filename.info where filename is the name of the file 1193 that was passed to the `PetscViewerBinaryOpen()`. The options in the info 1194 file will be ignored if you use the -viewer_binary_skip_info option. 1195 1196 If the type or size of mat is not set before a call to `MatLoad()`, PETSc 1197 sets the default matrix type AIJ and sets the local and global sizes. 1198 If type and/or size is already set, then the same are used. 1199 1200 In parallel, each processor can load a subset of rows (or the 1201 entire matrix). This routine is especially useful when a large 1202 matrix is stored on disk and only part of it is desired on each 1203 processor. For example, a parallel solver may access only some of 1204 the rows from each processor. The algorithm used here reads 1205 relatively small blocks of data rather than reading the entire 1206 matrix and then subsetting it. 1207 1208 Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`. 1209 Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`, 1210 or the sequence like 1211 .vb 1212 `PetscViewer` v; 1213 `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v); 1214 `PetscViewerSetType`(v,`PETSCVIEWERBINARY`); 1215 `PetscViewerSetFromOptions`(v); 1216 `PetscViewerFileSetMode`(v,`FILE_MODE_READ`); 1217 `PetscViewerFileSetName`(v,"datafile"); 1218 .ve 1219 The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option 1220 $ -viewer_type {binary, hdf5} 1221 1222 See the example src/ksp/ksp/tutorials/ex27.c with the first approach, 1223 and src/mat/tutorials/ex10.c with the second approach. 1224 1225 In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks 1226 is read onto rank 0 and then shipped to its destination rank, one after another. 1227 Multiple objects, both matrices and vectors, can be stored within the same file. 1228 Their PetscObject name is ignored; they are loaded in the order of their storage. 1229 1230 Most users should not need to know the details of the binary storage 1231 format, since `MatLoad()` and `MatView()` completely hide these details. 1232 But for anyone who's interested, the standard binary matrix storage 1233 format is 1234 1235 .vb 1236 PetscInt MAT_FILE_CLASSID 1237 PetscInt number of rows 1238 PetscInt number of columns 1239 PetscInt total number of nonzeros 1240 PetscInt *number nonzeros in each row 1241 PetscInt *column indices of all nonzeros (starting index is zero) 1242 PetscScalar *values of all nonzeros 1243 .ve 1244 1245 PETSc automatically does the byte swapping for 1246 machines that store the bytes reversed. Thus if you write your own binary 1247 read/write routines you have to swap the bytes; see `PetscBinaryRead()` 1248 and `PetscBinaryWrite()` to see how this may be done. 1249 1250 In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used. 1251 Each processor's chunk is loaded independently by its owning rank. 1252 Multiple objects, both matrices and vectors, can be stored within the same file. 1253 They are looked up by their PetscObject name. 1254 1255 As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use 1256 by default the same structure and naming of the AIJ arrays and column count 1257 within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g. 1258 $ save example.mat A b -v7.3 1259 can be directly read by this routine (see Reference 1 for details). 1260 1261 Depending on your MATLAB version, this format might be a default, 1262 otherwise you can set it as default in Preferences. 1263 1264 Unless -nocompression flag is used to save the file in MATLAB, 1265 PETSc must be configured with ZLIB package. 1266 1267 See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c 1268 1269 This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5` 1270 1271 Corresponding `MatView()` is not yet implemented. 1272 1273 The loaded matrix is actually a transpose of the original one in MATLAB, 1274 unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above). 1275 With this format, matrix is automatically transposed by PETSc, 1276 unless the matrix is marked as SPD or symmetric 1277 (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`). 1278 1279 References: 1280 . * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version 1281 1282 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()` 1283 @*/ 1284 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer) 1285 { 1286 PetscBool flg; 1287 1288 PetscFunctionBegin; 1289 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1290 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1291 1292 if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ)); 1293 1294 flg = PETSC_FALSE; 1295 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL)); 1296 if (flg) { 1297 PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE)); 1298 PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE)); 1299 } 1300 flg = PETSC_FALSE; 1301 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL)); 1302 if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE)); 1303 1304 PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0)); 1305 PetscUseTypeMethod(mat, load, viewer); 1306 PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0)); 1307 PetscFunctionReturn(PETSC_SUCCESS); 1308 } 1309 1310 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant) 1311 { 1312 Mat_Redundant *redund = *redundant; 1313 1314 PetscFunctionBegin; 1315 if (redund) { 1316 if (redund->matseq) { /* via MatCreateSubMatrices() */ 1317 PetscCall(ISDestroy(&redund->isrow)); 1318 PetscCall(ISDestroy(&redund->iscol)); 1319 PetscCall(MatDestroySubMatrices(1, &redund->matseq)); 1320 } else { 1321 PetscCall(PetscFree2(redund->send_rank, redund->recv_rank)); 1322 PetscCall(PetscFree(redund->sbuf_j)); 1323 PetscCall(PetscFree(redund->sbuf_a)); 1324 for (PetscInt i = 0; i < redund->nrecvs; i++) { 1325 PetscCall(PetscFree(redund->rbuf_j[i])); 1326 PetscCall(PetscFree(redund->rbuf_a[i])); 1327 } 1328 PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a)); 1329 } 1330 1331 if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm)); 1332 PetscCall(PetscFree(redund)); 1333 } 1334 PetscFunctionReturn(PETSC_SUCCESS); 1335 } 1336 1337 /*@C 1338 MatDestroy - Frees space taken by a matrix. 1339 1340 Collective 1341 1342 Input Parameter: 1343 . A - the matrix 1344 1345 Level: beginner 1346 1347 Developer Note: 1348 Some special arrays of matrices are not destroyed in this routine but instead by the routines called by 1349 `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines. 1350 `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes 1351 if changes are needed here. 1352 1353 .seealso: [](ch_matrices), `Mat`, `MatCreate()` 1354 @*/ 1355 PetscErrorCode MatDestroy(Mat *A) 1356 { 1357 PetscFunctionBegin; 1358 if (!*A) PetscFunctionReturn(PETSC_SUCCESS); 1359 PetscValidHeaderSpecific(*A, MAT_CLASSID, 1); 1360 if (--((PetscObject)(*A))->refct > 0) { 1361 *A = NULL; 1362 PetscFunctionReturn(PETSC_SUCCESS); 1363 } 1364 1365 /* if memory was published with SAWs then destroy it */ 1366 PetscCall(PetscObjectSAWsViewOff((PetscObject)*A)); 1367 PetscTryTypeMethod((*A), destroy); 1368 1369 PetscCall(PetscFree((*A)->factorprefix)); 1370 PetscCall(PetscFree((*A)->defaultvectype)); 1371 PetscCall(PetscFree((*A)->defaultrandtype)); 1372 PetscCall(PetscFree((*A)->bsizes)); 1373 PetscCall(PetscFree((*A)->solvertype)); 1374 for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i])); 1375 if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL; 1376 PetscCall(MatDestroy_Redundant(&(*A)->redundant)); 1377 PetscCall(MatProductClear(*A)); 1378 PetscCall(MatNullSpaceDestroy(&(*A)->nullsp)); 1379 PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp)); 1380 PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp)); 1381 PetscCall(MatDestroy(&(*A)->schur)); 1382 PetscCall(PetscLayoutDestroy(&(*A)->rmap)); 1383 PetscCall(PetscLayoutDestroy(&(*A)->cmap)); 1384 PetscCall(PetscHeaderDestroy(A)); 1385 PetscFunctionReturn(PETSC_SUCCESS); 1386 } 1387 1388 /*@C 1389 MatSetValues - Inserts or adds a block of values into a matrix. 1390 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1391 MUST be called after all calls to `MatSetValues()` have been completed. 1392 1393 Not Collective 1394 1395 Input Parameters: 1396 + mat - the matrix 1397 . v - a logically two-dimensional array of values 1398 . m - the number of rows 1399 . idxm - the global indices of the rows 1400 . n - the number of columns 1401 . idxn - the global indices of the columns 1402 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1403 1404 Level: beginner 1405 1406 Notes: 1407 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1408 1409 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1410 options cannot be mixed without intervening calls to the assembly 1411 routines. 1412 1413 `MatSetValues()` uses 0-based row and column numbers in Fortran 1414 as well as in C. 1415 1416 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1417 simply ignored. This allows easily inserting element stiffness matrices 1418 with homogeneous Dirchlet boundary conditions that you don't want represented 1419 in the matrix. 1420 1421 Efficiency Alert: 1422 The routine `MatSetValuesBlocked()` may offer much better efficiency 1423 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1424 1425 Developer Note: 1426 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1427 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1428 1429 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1430 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1431 @*/ 1432 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1433 { 1434 PetscFunctionBeginHot; 1435 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1436 PetscValidType(mat, 1); 1437 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1438 PetscValidIntPointer(idxm, 3); 1439 PetscValidIntPointer(idxn, 5); 1440 MatCheckPreallocated(mat, 1); 1441 1442 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1443 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1444 1445 if (PetscDefined(USE_DEBUG)) { 1446 PetscInt i, j; 1447 1448 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1449 for (i = 0; i < m; i++) { 1450 for (j = 0; j < n; j++) { 1451 if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j])) 1452 #if defined(PETSC_USE_COMPLEX) 1453 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]); 1454 #else 1455 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]); 1456 #endif 1457 } 1458 } 1459 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); 1460 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); 1461 } 1462 1463 if (mat->assembled) { 1464 mat->was_assembled = PETSC_TRUE; 1465 mat->assembled = PETSC_FALSE; 1466 } 1467 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1468 PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv); 1469 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1470 PetscFunctionReturn(PETSC_SUCCESS); 1471 } 1472 1473 /*@C 1474 MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns 1475 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1476 MUST be called after all calls to `MatSetValues()` have been completed. 1477 1478 Not Collective 1479 1480 Input Parameters: 1481 + mat - the matrix 1482 . v - a logically two-dimensional array of values 1483 . ism - the rows to provide 1484 . isn - the columns to provide 1485 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1486 1487 Level: beginner 1488 1489 Notes: 1490 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1491 1492 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1493 options cannot be mixed without intervening calls to the assembly 1494 routines. 1495 1496 `MatSetValues()` uses 0-based row and column numbers in Fortran 1497 as well as in C. 1498 1499 Negative indices may be passed in `ism` and `isn`, these rows and columns are 1500 simply ignored. This allows easily inserting element stiffness matrices 1501 with homogeneous Dirchlet boundary conditions that you don't want represented 1502 in the matrix. 1503 1504 Efficiency Alert: 1505 The routine `MatSetValuesBlocked()` may offer much better efficiency 1506 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1507 1508 This is currently not optimized for any particular `ISType` 1509 1510 Developer Notes: 1511 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1512 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1513 1514 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1515 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()` 1516 @*/ 1517 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv) 1518 { 1519 PetscInt m, n; 1520 const PetscInt *rows, *cols; 1521 1522 PetscFunctionBeginHot; 1523 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1524 PetscCall(ISGetIndices(ism, &rows)); 1525 PetscCall(ISGetIndices(isn, &cols)); 1526 PetscCall(ISGetLocalSize(ism, &m)); 1527 PetscCall(ISGetLocalSize(isn, &n)); 1528 PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv)); 1529 PetscCall(ISRestoreIndices(ism, &rows)); 1530 PetscCall(ISRestoreIndices(isn, &cols)); 1531 PetscFunctionReturn(PETSC_SUCCESS); 1532 } 1533 1534 /*@ 1535 MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1536 values into a matrix 1537 1538 Not Collective 1539 1540 Input Parameters: 1541 + mat - the matrix 1542 . row - the (block) row to set 1543 - v - a logically two-dimensional array of values 1544 1545 Level: intermediate 1546 1547 Notes: 1548 The values, `v`, are column-oriented (for the block version) and sorted 1549 1550 All the nonzeros in the row must be provided 1551 1552 The matrix must have previously had its column indices set, likely by having been assembled. 1553 1554 The row must belong to this process 1555 1556 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1557 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()` 1558 @*/ 1559 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[]) 1560 { 1561 PetscInt globalrow; 1562 1563 PetscFunctionBegin; 1564 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1565 PetscValidType(mat, 1); 1566 PetscValidScalarPointer(v, 3); 1567 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow)); 1568 PetscCall(MatSetValuesRow(mat, globalrow, v)); 1569 PetscFunctionReturn(PETSC_SUCCESS); 1570 } 1571 1572 /*@ 1573 MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1574 values into a matrix 1575 1576 Not Collective 1577 1578 Input Parameters: 1579 + mat - the matrix 1580 . row - the (block) row to set 1581 - 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 1582 1583 Level: advanced 1584 1585 Notes: 1586 The values, `v`, are column-oriented for the block version. 1587 1588 All the nonzeros in the row must be provided 1589 1590 THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used. 1591 1592 The row must belong to this process 1593 1594 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1595 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()` 1596 @*/ 1597 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[]) 1598 { 1599 PetscFunctionBeginHot; 1600 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1601 PetscValidType(mat, 1); 1602 MatCheckPreallocated(mat, 1); 1603 PetscValidScalarPointer(v, 3); 1604 PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values"); 1605 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1606 mat->insertmode = INSERT_VALUES; 1607 1608 if (mat->assembled) { 1609 mat->was_assembled = PETSC_TRUE; 1610 mat->assembled = PETSC_FALSE; 1611 } 1612 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1613 PetscUseTypeMethod(mat, setvaluesrow, row, v); 1614 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1615 PetscFunctionReturn(PETSC_SUCCESS); 1616 } 1617 1618 /*@ 1619 MatSetValuesStencil - Inserts or adds a block of values into a matrix. 1620 Using structured grid indexing 1621 1622 Not Collective 1623 1624 Input Parameters: 1625 + mat - the matrix 1626 . m - number of rows being entered 1627 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered 1628 . n - number of columns being entered 1629 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered 1630 . v - a logically two-dimensional array of values 1631 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values 1632 1633 Level: beginner 1634 1635 Notes: 1636 By default the values, `v`, are row-oriented. See `MatSetOption()` for other options. 1637 1638 Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1639 options cannot be mixed without intervening calls to the assembly 1640 routines. 1641 1642 The grid coordinates are across the entire grid, not just the local portion 1643 1644 `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran 1645 as well as in C. 1646 1647 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1648 1649 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1650 or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1651 1652 The columns and rows in the stencil passed in MUST be contained within the 1653 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1654 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1655 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1656 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1657 1658 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 1659 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 1660 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 1661 `DM_BOUNDARY_PERIODIC` boundary type. 1662 1663 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 1664 a single value per point) you can skip filling those indices. 1665 1666 Inspired by the structured grid interface to the HYPRE package 1667 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1668 1669 Efficiency Alert: 1670 The routine `MatSetValuesBlockedStencil()` may offer much better efficiency 1671 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1672 1673 Fortran Note: 1674 `idxm` and `idxn` should be declared as 1675 $ MatStencil idxm(4,m),idxn(4,n) 1676 and the values inserted using 1677 .vb 1678 idxm(MatStencil_i,1) = i 1679 idxm(MatStencil_j,1) = j 1680 idxm(MatStencil_k,1) = k 1681 idxm(MatStencil_c,1) = c 1682 etc 1683 .ve 1684 1685 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1686 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil` 1687 @*/ 1688 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1689 { 1690 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1691 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1692 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1693 1694 PetscFunctionBegin; 1695 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1696 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1697 PetscValidType(mat, 1); 1698 PetscValidPointer(idxm, 3); 1699 PetscValidPointer(idxn, 5); 1700 1701 if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 1702 jdxm = buf; 1703 jdxn = buf + m; 1704 } else { 1705 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1706 jdxm = bufm; 1707 jdxn = bufn; 1708 } 1709 for (i = 0; i < m; i++) { 1710 for (j = 0; j < 3 - sdim; j++) dxm++; 1711 tmp = *dxm++ - starts[0]; 1712 for (j = 0; j < dim - 1; j++) { 1713 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1714 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1715 } 1716 if (mat->stencil.noc) dxm++; 1717 jdxm[i] = tmp; 1718 } 1719 for (i = 0; i < n; i++) { 1720 for (j = 0; j < 3 - sdim; j++) dxn++; 1721 tmp = *dxn++ - starts[0]; 1722 for (j = 0; j < dim - 1; j++) { 1723 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1724 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1725 } 1726 if (mat->stencil.noc) dxn++; 1727 jdxn[i] = tmp; 1728 } 1729 PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv)); 1730 PetscCall(PetscFree2(bufm, bufn)); 1731 PetscFunctionReturn(PETSC_SUCCESS); 1732 } 1733 1734 /*@ 1735 MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix. 1736 Using structured grid indexing 1737 1738 Not Collective 1739 1740 Input Parameters: 1741 + mat - the matrix 1742 . m - number of rows being entered 1743 . idxm - grid coordinates for matrix rows being entered 1744 . n - number of columns being entered 1745 . idxn - grid coordinates for matrix columns being entered 1746 . v - a logically two-dimensional array of values 1747 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values 1748 1749 Level: beginner 1750 1751 Notes: 1752 By default the values, `v`, are row-oriented and unsorted. 1753 See `MatSetOption()` for other options. 1754 1755 Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1756 options cannot be mixed without intervening calls to the assembly 1757 routines. 1758 1759 The grid coordinates are across the entire grid, not just the local portion 1760 1761 `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran 1762 as well as in C. 1763 1764 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1765 1766 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1767 or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1768 1769 The columns and rows in the stencil passed in MUST be contained within the 1770 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1771 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1772 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1773 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1774 1775 Negative indices may be passed in idxm and idxn, these rows and columns are 1776 simply ignored. This allows easily inserting element stiffness matrices 1777 with homogeneous Dirchlet boundary conditions that you don't want represented 1778 in the matrix. 1779 1780 Inspired by the structured grid interface to the HYPRE package 1781 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1782 1783 Fortran Note: 1784 `idxm` and `idxn` should be declared as 1785 $ MatStencil idxm(4,m),idxn(4,n) 1786 and the values inserted using 1787 .vb 1788 idxm(MatStencil_i,1) = i 1789 idxm(MatStencil_j,1) = j 1790 idxm(MatStencil_k,1) = k 1791 etc 1792 .ve 1793 1794 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1795 `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`, 1796 `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` 1797 @*/ 1798 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1799 { 1800 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1801 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1802 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1803 1804 PetscFunctionBegin; 1805 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1806 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1807 PetscValidType(mat, 1); 1808 PetscValidPointer(idxm, 3); 1809 PetscValidPointer(idxn, 5); 1810 PetscValidScalarPointer(v, 6); 1811 1812 if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 1813 jdxm = buf; 1814 jdxn = buf + m; 1815 } else { 1816 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1817 jdxm = bufm; 1818 jdxn = bufn; 1819 } 1820 for (i = 0; i < m; i++) { 1821 for (j = 0; j < 3 - sdim; j++) dxm++; 1822 tmp = *dxm++ - starts[0]; 1823 for (j = 0; j < sdim - 1; j++) { 1824 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1825 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1826 } 1827 dxm++; 1828 jdxm[i] = tmp; 1829 } 1830 for (i = 0; i < n; i++) { 1831 for (j = 0; j < 3 - sdim; j++) dxn++; 1832 tmp = *dxn++ - starts[0]; 1833 for (j = 0; j < sdim - 1; j++) { 1834 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1835 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1836 } 1837 dxn++; 1838 jdxn[i] = tmp; 1839 } 1840 PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv)); 1841 PetscCall(PetscFree2(bufm, bufn)); 1842 PetscFunctionReturn(PETSC_SUCCESS); 1843 } 1844 1845 /*@ 1846 MatSetStencil - Sets the grid information for setting values into a matrix via 1847 `MatSetValuesStencil()` 1848 1849 Not Collective 1850 1851 Input Parameters: 1852 + mat - the matrix 1853 . dim - dimension of the grid 1, 2, or 3 1854 . dims - number of grid points in x, y, and z direction, including ghost points on your processor 1855 . starts - starting point of ghost nodes on your processor in x, y, and z direction 1856 - dof - number of degrees of freedom per node 1857 1858 Level: beginner 1859 1860 Notes: 1861 Inspired by the structured grid interface to the HYPRE package 1862 (www.llnl.gov/CASC/hyper) 1863 1864 For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the 1865 user. 1866 1867 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1868 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()` 1869 @*/ 1870 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof) 1871 { 1872 PetscFunctionBegin; 1873 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1874 PetscValidIntPointer(dims, 3); 1875 PetscValidIntPointer(starts, 4); 1876 1877 mat->stencil.dim = dim + (dof > 1); 1878 for (PetscInt i = 0; i < dim; i++) { 1879 mat->stencil.dims[i] = dims[dim - i - 1]; /* copy the values in backwards */ 1880 mat->stencil.starts[i] = starts[dim - i - 1]; 1881 } 1882 mat->stencil.dims[dim] = dof; 1883 mat->stencil.starts[dim] = 0; 1884 mat->stencil.noc = (PetscBool)(dof == 1); 1885 PetscFunctionReturn(PETSC_SUCCESS); 1886 } 1887 1888 /*@C 1889 MatSetValuesBlocked - Inserts or adds a block of values into a matrix. 1890 1891 Not Collective 1892 1893 Input Parameters: 1894 + mat - the matrix 1895 . v - a logically two-dimensional array of values 1896 . m - the number of block rows 1897 . idxm - the global block indices 1898 . n - the number of block columns 1899 . idxn - the global block indices 1900 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values 1901 1902 Level: intermediate 1903 1904 Notes: 1905 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call 1906 MatXXXXSetPreallocation() or `MatSetUp()` before using this routine. 1907 1908 The `m` and `n` count the NUMBER of blocks in the row direction and column direction, 1909 NOT the total number of rows/columns; for example, if the block size is 2 and 1910 you are passing in values for rows 2,3,4,5 then m would be 2 (not 4). 1911 The values in idxm would be 1 2; that is the first index for each block divided by 1912 the block size. 1913 1914 You must call `MatSetBlockSize()` when constructing this matrix (before 1915 preallocating it). 1916 1917 By default the values, `v`, are row-oriented, so the layout of 1918 `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options. 1919 1920 Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES` 1921 options cannot be mixed without intervening calls to the assembly 1922 routines. 1923 1924 `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran 1925 as well as in C. 1926 1927 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1928 simply ignored. This allows easily inserting element stiffness matrices 1929 with homogeneous Dirchlet boundary conditions that you don't want represented 1930 in the matrix. 1931 1932 Each time an entry is set within a sparse matrix via `MatSetValues()`, 1933 internal searching must be done to determine where to place the 1934 data in the matrix storage space. By instead inserting blocks of 1935 entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is 1936 reduced. 1937 1938 Example: 1939 .vb 1940 Suppose m=n=2 and block size(bs) = 2 The array is 1941 1942 1 2 | 3 4 1943 5 6 | 7 8 1944 - - - | - - - 1945 9 10 | 11 12 1946 13 14 | 15 16 1947 1948 v[] should be passed in like 1949 v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] 1950 1951 If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then 1952 v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16] 1953 .ve 1954 1955 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()` 1956 @*/ 1957 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1958 { 1959 PetscFunctionBeginHot; 1960 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1961 PetscValidType(mat, 1); 1962 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1963 PetscValidIntPointer(idxm, 3); 1964 PetscValidIntPointer(idxn, 5); 1965 MatCheckPreallocated(mat, 1); 1966 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1967 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1968 if (PetscDefined(USE_DEBUG)) { 1969 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1970 PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 1971 } 1972 if (PetscDefined(USE_DEBUG)) { 1973 PetscInt rbs, cbs, M, N, i; 1974 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1975 PetscCall(MatGetSize(mat, &M, &N)); 1976 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); 1977 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); 1978 } 1979 if (mat->assembled) { 1980 mat->was_assembled = PETSC_TRUE; 1981 mat->assembled = PETSC_FALSE; 1982 } 1983 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1984 if (mat->ops->setvaluesblocked) { 1985 PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv); 1986 } else { 1987 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn; 1988 PetscInt i, j, bs, cbs; 1989 1990 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 1991 if (m * bs + n * cbs <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 1992 iidxm = buf; 1993 iidxn = buf + m * bs; 1994 } else { 1995 PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc)); 1996 iidxm = bufr; 1997 iidxn = bufc; 1998 } 1999 for (i = 0; i < m; i++) { 2000 for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j; 2001 } 2002 if (m != n || bs != cbs || idxm != idxn) { 2003 for (i = 0; i < n; i++) { 2004 for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j; 2005 } 2006 } else iidxn = iidxm; 2007 PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv)); 2008 PetscCall(PetscFree2(bufr, bufc)); 2009 } 2010 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2011 PetscFunctionReturn(PETSC_SUCCESS); 2012 } 2013 2014 /*@C 2015 MatGetValues - Gets a block of local values from a matrix. 2016 2017 Not Collective; can only return values that are owned by the give process 2018 2019 Input Parameters: 2020 + mat - the matrix 2021 . v - a logically two-dimensional array for storing the values 2022 . m - the number of rows 2023 . idxm - the global indices of the rows 2024 . n - the number of columns 2025 - idxn - the global indices of the columns 2026 2027 Level: advanced 2028 2029 Notes: 2030 The user must allocate space (m*n `PetscScalar`s) for the values, `v`. 2031 The values, `v`, are then returned in a row-oriented format, 2032 analogous to that used by default in `MatSetValues()`. 2033 2034 `MatGetValues()` uses 0-based row and column numbers in 2035 Fortran as well as in C. 2036 2037 `MatGetValues()` requires that the matrix has been assembled 2038 with `MatAssemblyBegin()`/`MatAssemblyEnd()`. Thus, calls to 2039 `MatSetValues()` and `MatGetValues()` CANNOT be made in succession 2040 without intermediate matrix assembly. 2041 2042 Negative row or column indices will be ignored and those locations in `v` will be 2043 left unchanged. 2044 2045 For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI rank. 2046 That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable 2047 from `MatGetOwnershipRange`(mat,&rstart,&rend). 2048 2049 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()` 2050 @*/ 2051 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) 2052 { 2053 PetscFunctionBegin; 2054 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2055 PetscValidType(mat, 1); 2056 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); 2057 PetscValidIntPointer(idxm, 3); 2058 PetscValidIntPointer(idxn, 5); 2059 PetscValidScalarPointer(v, 6); 2060 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2061 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2062 MatCheckPreallocated(mat, 1); 2063 2064 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2065 PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v); 2066 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2067 PetscFunctionReturn(PETSC_SUCCESS); 2068 } 2069 2070 /*@C 2071 MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices 2072 defined previously by `MatSetLocalToGlobalMapping()` 2073 2074 Not Collective 2075 2076 Input Parameters: 2077 + mat - the matrix 2078 . nrow - number of rows 2079 . irow - the row local indices 2080 . ncol - number of columns 2081 - icol - the column local indices 2082 2083 Output Parameter: 2084 . y - a logically two-dimensional array of values 2085 2086 Level: advanced 2087 2088 Notes: 2089 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine. 2090 2091 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, 2092 are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can 2093 determine if the resulting global row associated with the local row r is owned by the requesting MPI rank by applying the `ISLocalToGlobalMapping` set 2094 with `MatSetLocalToGlobalMapping()`. 2095 2096 Developer Note: 2097 This is labelled with C so does not automatically generate Fortran stubs and interfaces 2098 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2099 2100 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2101 `MatSetValuesLocal()`, `MatGetValues()` 2102 @*/ 2103 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[]) 2104 { 2105 PetscFunctionBeginHot; 2106 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2107 PetscValidType(mat, 1); 2108 MatCheckPreallocated(mat, 1); 2109 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */ 2110 PetscValidIntPointer(irow, 3); 2111 PetscValidIntPointer(icol, 5); 2112 if (PetscDefined(USE_DEBUG)) { 2113 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2114 PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2115 } 2116 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2117 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2118 if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y); 2119 else { 2120 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm; 2121 if ((nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2122 irowm = buf; 2123 icolm = buf + nrow; 2124 } else { 2125 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2126 irowm = bufr; 2127 icolm = bufc; 2128 } 2129 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping())."); 2130 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping())."); 2131 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm)); 2132 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm)); 2133 PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y)); 2134 PetscCall(PetscFree2(bufr, bufc)); 2135 } 2136 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2137 PetscFunctionReturn(PETSC_SUCCESS); 2138 } 2139 2140 /*@ 2141 MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and 2142 the same size. Currently, this can only be called once and creates the given matrix. 2143 2144 Not Collective 2145 2146 Input Parameters: 2147 + mat - the matrix 2148 . nb - the number of blocks 2149 . bs - the number of rows (and columns) in each block 2150 . rows - a concatenation of the rows for each block 2151 - v - a concatenation of logically two-dimensional arrays of values 2152 2153 Level: advanced 2154 2155 Note: 2156 `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values 2157 2158 In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix. 2159 2160 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 2161 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()` 2162 @*/ 2163 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[]) 2164 { 2165 PetscFunctionBegin; 2166 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2167 PetscValidType(mat, 1); 2168 PetscValidIntPointer(rows, 4); 2169 PetscValidScalarPointer(v, 5); 2170 PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2171 2172 PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0)); 2173 if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v); 2174 else { 2175 for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES)); 2176 } 2177 PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0)); 2178 PetscFunctionReturn(PETSC_SUCCESS); 2179 } 2180 2181 /*@ 2182 MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by 2183 the routine `MatSetValuesLocal()` to allow users to insert matrix entries 2184 using a local (per-processor) numbering. 2185 2186 Not Collective 2187 2188 Input Parameters: 2189 + x - the matrix 2190 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()` 2191 - cmapping - column mapping 2192 2193 Level: intermediate 2194 2195 Note: 2196 If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix 2197 2198 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()` 2199 @*/ 2200 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping) 2201 { 2202 PetscFunctionBegin; 2203 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 2204 PetscValidType(x, 1); 2205 if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2); 2206 if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3); 2207 if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping); 2208 else { 2209 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping)); 2210 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping)); 2211 } 2212 PetscFunctionReturn(PETSC_SUCCESS); 2213 } 2214 2215 /*@ 2216 MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()` 2217 2218 Not Collective 2219 2220 Input Parameter: 2221 . A - the matrix 2222 2223 Output Parameters: 2224 + rmapping - row mapping 2225 - cmapping - column mapping 2226 2227 Level: advanced 2228 2229 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()` 2230 @*/ 2231 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping) 2232 { 2233 PetscFunctionBegin; 2234 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2235 PetscValidType(A, 1); 2236 if (rmapping) { 2237 PetscValidPointer(rmapping, 2); 2238 *rmapping = A->rmap->mapping; 2239 } 2240 if (cmapping) { 2241 PetscValidPointer(cmapping, 3); 2242 *cmapping = A->cmap->mapping; 2243 } 2244 PetscFunctionReturn(PETSC_SUCCESS); 2245 } 2246 2247 /*@ 2248 MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix 2249 2250 Logically Collective 2251 2252 Input Parameters: 2253 + A - the matrix 2254 . rmap - row layout 2255 - cmap - column layout 2256 2257 Level: advanced 2258 2259 Note: 2260 The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called. 2261 2262 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()` 2263 @*/ 2264 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap) 2265 { 2266 PetscFunctionBegin; 2267 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2268 PetscCall(PetscLayoutReference(rmap, &A->rmap)); 2269 PetscCall(PetscLayoutReference(cmap, &A->cmap)); 2270 PetscFunctionReturn(PETSC_SUCCESS); 2271 } 2272 2273 /*@ 2274 MatGetLayouts - Gets the `PetscLayout` objects for rows and columns 2275 2276 Not Collective 2277 2278 Input Parameter: 2279 . A - the matrix 2280 2281 Output Parameters: 2282 + rmap - row layout 2283 - cmap - column layout 2284 2285 Level: advanced 2286 2287 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()` 2288 @*/ 2289 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap) 2290 { 2291 PetscFunctionBegin; 2292 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2293 PetscValidType(A, 1); 2294 if (rmap) { 2295 PetscValidPointer(rmap, 2); 2296 *rmap = A->rmap; 2297 } 2298 if (cmap) { 2299 PetscValidPointer(cmap, 3); 2300 *cmap = A->cmap; 2301 } 2302 PetscFunctionReturn(PETSC_SUCCESS); 2303 } 2304 2305 /*@C 2306 MatSetValuesLocal - Inserts or adds values into certain locations of a matrix, 2307 using a local numbering of the nodes. 2308 2309 Not Collective 2310 2311 Input Parameters: 2312 + mat - the matrix 2313 . nrow - number of rows 2314 . irow - the row local indices 2315 . ncol - number of columns 2316 . icol - the column local indices 2317 . y - a logically two-dimensional array of values 2318 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2319 2320 Level: intermediate 2321 2322 Notes: 2323 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 2324 `MatSetUp()` before using this routine 2325 2326 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine 2327 2328 Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2329 options cannot be mixed without intervening calls to the assembly 2330 routines. 2331 2332 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2333 MUST be called after all calls to `MatSetValuesLocal()` have been completed. 2334 2335 Developer Note: 2336 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2337 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2338 2339 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2340 `MatGetValuesLocal()` 2341 @*/ 2342 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2343 { 2344 PetscFunctionBeginHot; 2345 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2346 PetscValidType(mat, 1); 2347 MatCheckPreallocated(mat, 1); 2348 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2349 PetscValidIntPointer(irow, 3); 2350 PetscValidIntPointer(icol, 5); 2351 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2352 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2353 if (PetscDefined(USE_DEBUG)) { 2354 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2355 PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2356 } 2357 2358 if (mat->assembled) { 2359 mat->was_assembled = PETSC_TRUE; 2360 mat->assembled = PETSC_FALSE; 2361 } 2362 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2363 if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv); 2364 else { 2365 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2366 const PetscInt *irowm, *icolm; 2367 2368 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2369 bufr = buf; 2370 bufc = buf + nrow; 2371 irowm = bufr; 2372 icolm = bufc; 2373 } else { 2374 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2375 irowm = bufr; 2376 icolm = bufc; 2377 } 2378 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr)); 2379 else irowm = irow; 2380 if (mat->cmap->mapping) { 2381 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2382 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc)); 2383 } else icolm = irowm; 2384 } else icolm = icol; 2385 PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv)); 2386 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2387 } 2388 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2389 PetscFunctionReturn(PETSC_SUCCESS); 2390 } 2391 2392 /*@C 2393 MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix, 2394 using a local ordering of the nodes a block at a time. 2395 2396 Not Collective 2397 2398 Input Parameters: 2399 + x - the matrix 2400 . nrow - number of rows 2401 . irow - the row local indices 2402 . ncol - number of columns 2403 . icol - the column local indices 2404 . y - a logically two-dimensional array of values 2405 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2406 2407 Level: intermediate 2408 2409 Notes: 2410 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 2411 `MatSetUp()` before using this routine 2412 2413 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()` 2414 before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the 2415 2416 Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2417 options cannot be mixed without intervening calls to the assembly 2418 routines. 2419 2420 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2421 MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed. 2422 2423 Developer Note: 2424 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2425 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2426 2427 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, 2428 `MatSetValuesLocal()`, `MatSetValuesBlocked()` 2429 @*/ 2430 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2431 { 2432 PetscFunctionBeginHot; 2433 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2434 PetscValidType(mat, 1); 2435 MatCheckPreallocated(mat, 1); 2436 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2437 PetscValidIntPointer(irow, 3); 2438 PetscValidIntPointer(icol, 5); 2439 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2440 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2441 if (PetscDefined(USE_DEBUG)) { 2442 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2443 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); 2444 } 2445 2446 if (mat->assembled) { 2447 mat->was_assembled = PETSC_TRUE; 2448 mat->assembled = PETSC_FALSE; 2449 } 2450 if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */ 2451 PetscInt irbs, rbs; 2452 PetscCall(MatGetBlockSizes(mat, &rbs, NULL)); 2453 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs)); 2454 PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs); 2455 } 2456 if (PetscUnlikelyDebug(mat->cmap->mapping)) { 2457 PetscInt icbs, cbs; 2458 PetscCall(MatGetBlockSizes(mat, NULL, &cbs)); 2459 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs)); 2460 PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs); 2461 } 2462 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2463 if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv); 2464 else { 2465 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2466 const PetscInt *irowm, *icolm; 2467 2468 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2469 bufr = buf; 2470 bufc = buf + nrow; 2471 irowm = bufr; 2472 icolm = bufc; 2473 } else { 2474 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2475 irowm = bufr; 2476 icolm = bufc; 2477 } 2478 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr)); 2479 else irowm = irow; 2480 if (mat->cmap->mapping) { 2481 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2482 PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc)); 2483 } else icolm = irowm; 2484 } else icolm = icol; 2485 PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv)); 2486 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2487 } 2488 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2489 PetscFunctionReturn(PETSC_SUCCESS); 2490 } 2491 2492 /*@ 2493 MatMultDiagonalBlock - Computes the matrix-vector product, y = Dx. Where D is defined by the inode or block structure of the diagonal 2494 2495 Collective 2496 2497 Input Parameters: 2498 + mat - the matrix 2499 - x - the vector to be multiplied 2500 2501 Output Parameter: 2502 . y - the result 2503 2504 Level: developer 2505 2506 Note: 2507 The vectors `x` and `y` cannot be the same. I.e., one cannot 2508 call `MatMultDiagonalBlock`(A,y,y). 2509 2510 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2511 @*/ 2512 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y) 2513 { 2514 PetscFunctionBegin; 2515 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2516 PetscValidType(mat, 1); 2517 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2518 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2519 2520 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2521 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2522 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2523 MatCheckPreallocated(mat, 1); 2524 2525 PetscUseTypeMethod(mat, multdiagonalblock, x, y); 2526 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2527 PetscFunctionReturn(PETSC_SUCCESS); 2528 } 2529 2530 /*@ 2531 MatMult - Computes the matrix-vector product, y = Ax. 2532 2533 Neighbor-wise Collective 2534 2535 Input Parameters: 2536 + mat - the matrix 2537 - x - the vector to be multiplied 2538 2539 Output Parameter: 2540 . y - the result 2541 2542 Level: beginner 2543 2544 Note: 2545 The vectors `x` and `y` cannot be the same. I.e., one cannot 2546 call `MatMult`(A,y,y). 2547 2548 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2549 @*/ 2550 PetscErrorCode MatMult(Mat mat, Vec x, Vec y) 2551 { 2552 PetscFunctionBegin; 2553 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2554 PetscValidType(mat, 1); 2555 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2556 VecCheckAssembled(x); 2557 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2558 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2559 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2560 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2561 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); 2562 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); 2563 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); 2564 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); 2565 PetscCall(VecSetErrorIfLocked(y, 3)); 2566 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2567 MatCheckPreallocated(mat, 1); 2568 2569 PetscCall(VecLockReadPush(x)); 2570 PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0)); 2571 PetscUseTypeMethod(mat, mult, x, y); 2572 PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0)); 2573 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2574 PetscCall(VecLockReadPop(x)); 2575 PetscFunctionReturn(PETSC_SUCCESS); 2576 } 2577 2578 /*@ 2579 MatMultTranspose - Computes matrix transpose times a vector y = A^T * x. 2580 2581 Neighbor-wise Collective 2582 2583 Input Parameters: 2584 + mat - the matrix 2585 - x - the vector to be multiplied 2586 2587 Output Parameter: 2588 . y - the result 2589 2590 Level: beginner 2591 2592 Notes: 2593 The vectors `x` and `y` cannot be the same. I.e., one cannot 2594 call `MatMultTranspose`(A,y,y). 2595 2596 For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple, 2597 use `MatMultHermitianTranspose()` 2598 2599 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()` 2600 @*/ 2601 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y) 2602 { 2603 PetscErrorCode (*op)(Mat, Vec, Vec) = NULL; 2604 2605 PetscFunctionBegin; 2606 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2607 PetscValidType(mat, 1); 2608 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2609 VecCheckAssembled(x); 2610 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2611 2612 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2613 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2614 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2615 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); 2616 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); 2617 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); 2618 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); 2619 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2620 MatCheckPreallocated(mat, 1); 2621 2622 if (!mat->ops->multtranspose) { 2623 if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult; 2624 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); 2625 } else op = mat->ops->multtranspose; 2626 PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0)); 2627 PetscCall(VecLockReadPush(x)); 2628 PetscCall((*op)(mat, x, y)); 2629 PetscCall(VecLockReadPop(x)); 2630 PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0)); 2631 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2632 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2633 PetscFunctionReturn(PETSC_SUCCESS); 2634 } 2635 2636 /*@ 2637 MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector. 2638 2639 Neighbor-wise Collective 2640 2641 Input Parameters: 2642 + mat - the matrix 2643 - x - the vector to be multilplied 2644 2645 Output Parameter: 2646 . y - the result 2647 2648 Level: beginner 2649 2650 Notes: 2651 The vectors `x` and `y` cannot be the same. I.e., one cannot 2652 call `MatMultHermitianTranspose`(A,y,y). 2653 2654 Also called the conjugate transpose, complex conjugate transpose, or adjoint. 2655 2656 For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical. 2657 2658 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()` 2659 @*/ 2660 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y) 2661 { 2662 PetscFunctionBegin; 2663 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2664 PetscValidType(mat, 1); 2665 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2666 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2667 2668 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2669 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2670 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2671 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); 2672 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); 2673 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); 2674 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); 2675 MatCheckPreallocated(mat, 1); 2676 2677 PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0)); 2678 #if defined(PETSC_USE_COMPLEX) 2679 if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) { 2680 PetscCall(VecLockReadPush(x)); 2681 if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y); 2682 else PetscUseTypeMethod(mat, mult, x, y); 2683 PetscCall(VecLockReadPop(x)); 2684 } else { 2685 Vec w; 2686 PetscCall(VecDuplicate(x, &w)); 2687 PetscCall(VecCopy(x, w)); 2688 PetscCall(VecConjugate(w)); 2689 PetscCall(MatMultTranspose(mat, w, y)); 2690 PetscCall(VecDestroy(&w)); 2691 PetscCall(VecConjugate(y)); 2692 } 2693 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2694 #else 2695 PetscCall(MatMultTranspose(mat, x, y)); 2696 #endif 2697 PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0)); 2698 PetscFunctionReturn(PETSC_SUCCESS); 2699 } 2700 2701 /*@ 2702 MatMultAdd - Computes v3 = v2 + A * v1. 2703 2704 Neighbor-wise Collective 2705 2706 Input Parameters: 2707 + mat - the matrix 2708 . v1 - the vector to be multiplied by `mat` 2709 - v2 - the vector to be added to the result 2710 2711 Output Parameter: 2712 . v3 - the result 2713 2714 Level: beginner 2715 2716 Note: 2717 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2718 call `MatMultAdd`(A,v1,v2,v1). 2719 2720 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()` 2721 @*/ 2722 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2723 { 2724 PetscFunctionBegin; 2725 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2726 PetscValidType(mat, 1); 2727 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2728 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2729 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2730 2731 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2732 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2733 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); 2734 /* 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); 2735 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); */ 2736 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); 2737 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); 2738 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2739 MatCheckPreallocated(mat, 1); 2740 2741 PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3)); 2742 PetscCall(VecLockReadPush(v1)); 2743 PetscUseTypeMethod(mat, multadd, v1, v2, v3); 2744 PetscCall(VecLockReadPop(v1)); 2745 PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3)); 2746 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2747 PetscFunctionReturn(PETSC_SUCCESS); 2748 } 2749 2750 /*@ 2751 MatMultTransposeAdd - Computes v3 = v2 + A' * v1. 2752 2753 Neighbor-wise Collective 2754 2755 Input Parameters: 2756 + mat - the matrix 2757 . v1 - the vector to be multiplied by the transpose of the matrix 2758 - v2 - the vector to be added to the result 2759 2760 Output Parameter: 2761 . v3 - the result 2762 2763 Level: beginner 2764 2765 Note: 2766 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2767 call `MatMultTransposeAdd`(A,v1,v2,v1). 2768 2769 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2770 @*/ 2771 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2772 { 2773 PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd; 2774 2775 PetscFunctionBegin; 2776 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2777 PetscValidType(mat, 1); 2778 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2779 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2780 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2781 2782 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2783 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2784 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); 2785 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); 2786 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); 2787 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2788 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2789 MatCheckPreallocated(mat, 1); 2790 2791 PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2792 PetscCall(VecLockReadPush(v1)); 2793 PetscCall((*op)(mat, v1, v2, v3)); 2794 PetscCall(VecLockReadPop(v1)); 2795 PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2796 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2797 PetscFunctionReturn(PETSC_SUCCESS); 2798 } 2799 2800 /*@ 2801 MatMultHermitianTransposeAdd - Computes v3 = v2 + A^H * v1. 2802 2803 Neighbor-wise Collective 2804 2805 Input Parameters: 2806 + mat - the matrix 2807 . v1 - the vector to be multiplied by the Hermitian transpose 2808 - v2 - the vector to be added to the result 2809 2810 Output Parameter: 2811 . v3 - the result 2812 2813 Level: beginner 2814 2815 Note: 2816 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2817 call `MatMultHermitianTransposeAdd`(A,v1,v2,v1). 2818 2819 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2820 @*/ 2821 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2822 { 2823 PetscFunctionBegin; 2824 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2825 PetscValidType(mat, 1); 2826 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2827 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2828 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2829 2830 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2831 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2832 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2833 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); 2834 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); 2835 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); 2836 MatCheckPreallocated(mat, 1); 2837 2838 PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2839 PetscCall(VecLockReadPush(v1)); 2840 if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3); 2841 else { 2842 Vec w, z; 2843 PetscCall(VecDuplicate(v1, &w)); 2844 PetscCall(VecCopy(v1, w)); 2845 PetscCall(VecConjugate(w)); 2846 PetscCall(VecDuplicate(v3, &z)); 2847 PetscCall(MatMultTranspose(mat, w, z)); 2848 PetscCall(VecDestroy(&w)); 2849 PetscCall(VecConjugate(z)); 2850 if (v2 != v3) { 2851 PetscCall(VecWAXPY(v3, 1.0, v2, z)); 2852 } else { 2853 PetscCall(VecAXPY(v3, 1.0, z)); 2854 } 2855 PetscCall(VecDestroy(&z)); 2856 } 2857 PetscCall(VecLockReadPop(v1)); 2858 PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2859 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2860 PetscFunctionReturn(PETSC_SUCCESS); 2861 } 2862 2863 /*@C 2864 MatGetFactorType - gets the type of factorization it is 2865 2866 Not Collective 2867 2868 Input Parameter: 2869 . mat - the matrix 2870 2871 Output Parameter: 2872 . 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` 2873 2874 Level: intermediate 2875 2876 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2877 `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2878 @*/ 2879 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t) 2880 { 2881 PetscFunctionBegin; 2882 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2883 PetscValidType(mat, 1); 2884 PetscValidPointer(t, 2); 2885 *t = mat->factortype; 2886 PetscFunctionReturn(PETSC_SUCCESS); 2887 } 2888 2889 /*@C 2890 MatSetFactorType - sets the type of factorization it is 2891 2892 Logically Collective 2893 2894 Input Parameters: 2895 + mat - the matrix 2896 - 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` 2897 2898 Level: intermediate 2899 2900 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2901 `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2902 @*/ 2903 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t) 2904 { 2905 PetscFunctionBegin; 2906 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2907 PetscValidType(mat, 1); 2908 mat->factortype = t; 2909 PetscFunctionReturn(PETSC_SUCCESS); 2910 } 2911 2912 /*@C 2913 MatGetInfo - Returns information about matrix storage (number of 2914 nonzeros, memory, etc.). 2915 2916 Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag 2917 2918 Input Parameters: 2919 + mat - the matrix 2920 - 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) 2921 2922 Output Parameter: 2923 . info - matrix information context 2924 2925 Options Database Key: 2926 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT` 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.). 2934 2935 Example: 2936 See the file ${PETSC_DIR}/include/petscmat.h for a complete list of 2937 data within the MatInfo context. For example, 2938 .vb 2939 MatInfo info; 2940 Mat A; 2941 double mal, nz_a, nz_u; 2942 2943 MatGetInfo(A, MAT_LOCAL, &info); 2944 mal = info.mallocs; 2945 nz_a = info.nz_allocated; 2946 .ve 2947 2948 Fortran users should declare info as a double precision 2949 array of dimension `MAT_INFO_SIZE`, and then extract the parameters 2950 of interest. See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h 2951 a complete list of parameter names. 2952 .vb 2953 double precision info(MAT_INFO_SIZE) 2954 double precision mal, nz_a 2955 Mat A 2956 integer ierr 2957 2958 call MatGetInfo(A, MAT_LOCAL, info, ierr) 2959 mal = info(MAT_INFO_MALLOCS) 2960 nz_a = info(MAT_INFO_NZ_ALLOCATED) 2961 .ve 2962 2963 Level: intermediate 2964 2965 Developer Note: 2966 The Fortran interface is not autogenerated as the 2967 interface definition cannot be generated correctly [due to `MatInfo` argument] 2968 2969 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()` 2970 @*/ 2971 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info) 2972 { 2973 PetscFunctionBegin; 2974 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2975 PetscValidType(mat, 1); 2976 PetscValidPointer(info, 3); 2977 MatCheckPreallocated(mat, 1); 2978 PetscUseTypeMethod(mat, getinfo, flag, info); 2979 PetscFunctionReturn(PETSC_SUCCESS); 2980 } 2981 2982 /* 2983 This is used by external packages where it is not easy to get the info from the actual 2984 matrix factorization. 2985 */ 2986 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info) 2987 { 2988 PetscFunctionBegin; 2989 PetscCall(PetscMemzero(info, sizeof(MatInfo))); 2990 PetscFunctionReturn(PETSC_SUCCESS); 2991 } 2992 2993 /*@C 2994 MatLUFactor - Performs in-place LU factorization of matrix. 2995 2996 Collective 2997 2998 Input Parameters: 2999 + mat - the matrix 3000 . row - row permutation 3001 . col - column permutation 3002 - info - options for factorization, includes 3003 .vb 3004 fill - expected fill as ratio of original fill. 3005 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3006 Run with the option -info to determine an optimal value to use 3007 .ve 3008 Level: developer 3009 3010 Notes: 3011 Most users should employ the `KSP` interface for linear solvers 3012 instead of working directly with matrix algebra routines such as this. 3013 See, e.g., `KSPCreate()`. 3014 3015 This changes the state of the matrix to a factored matrix; it cannot be used 3016 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3017 3018 This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()` 3019 when not using `KSP`. 3020 3021 Developer Note: 3022 The Fortran interface is not autogenerated as the 3023 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3024 3025 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, 3026 `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3027 @*/ 3028 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3029 { 3030 MatFactorInfo tinfo; 3031 3032 PetscFunctionBegin; 3033 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3034 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3035 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3036 if (info) PetscValidPointer(info, 4); 3037 PetscValidType(mat, 1); 3038 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3039 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3040 MatCheckPreallocated(mat, 1); 3041 if (!info) { 3042 PetscCall(MatFactorInfoInitialize(&tinfo)); 3043 info = &tinfo; 3044 } 3045 3046 PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0)); 3047 PetscUseTypeMethod(mat, lufactor, row, col, info); 3048 PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0)); 3049 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3050 PetscFunctionReturn(PETSC_SUCCESS); 3051 } 3052 3053 /*@C 3054 MatILUFactor - Performs in-place ILU factorization of matrix. 3055 3056 Collective 3057 3058 Input Parameters: 3059 + mat - the matrix 3060 . row - row permutation 3061 . col - column permutation 3062 - info - structure containing 3063 .vb 3064 levels - number of levels of fill. 3065 expected fill - as ratio of original fill. 3066 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 3067 missing diagonal entries) 3068 .ve 3069 3070 Level: developer 3071 3072 Notes: 3073 Most users should employ the `KSP` interface for linear solvers 3074 instead of working directly with matrix algebra routines such as this. 3075 See, e.g., `KSPCreate()`. 3076 3077 Probably really in-place only when level of fill is zero, otherwise allocates 3078 new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()` 3079 when not using `KSP`. 3080 3081 Developer Note: 3082 The Fortran interface is not autogenerated as the 3083 interface definition cannot be generated correctly [due to MatFactorInfo] 3084 3085 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 3086 @*/ 3087 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3088 { 3089 PetscFunctionBegin; 3090 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3091 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3092 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3093 PetscValidPointer(info, 4); 3094 PetscValidType(mat, 1); 3095 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 3096 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3097 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3098 MatCheckPreallocated(mat, 1); 3099 3100 PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0)); 3101 PetscUseTypeMethod(mat, ilufactor, row, col, info); 3102 PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0)); 3103 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3104 PetscFunctionReturn(PETSC_SUCCESS); 3105 } 3106 3107 /*@C 3108 MatLUFactorSymbolic - Performs symbolic LU factorization of matrix. 3109 Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`. 3110 3111 Collective 3112 3113 Input Parameters: 3114 + fact - the factor matrix obtained with `MatGetFactor()` 3115 . mat - the matrix 3116 . row - the row permutation 3117 . col - the column permutation 3118 - info - options for factorization, includes 3119 .vb 3120 fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use 3121 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3122 .ve 3123 3124 Level: developer 3125 3126 Notes: 3127 See [Matrix Factorization](sec_matfactor) for additional information about factorizations 3128 3129 Most users should employ the simplified `KSP` interface for linear solvers 3130 instead of working directly with matrix algebra routines such as this. 3131 See, e.g., `KSPCreate()`. 3132 3133 Developer Note: 3134 The Fortran interface is not autogenerated as the 3135 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3136 3137 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3138 @*/ 3139 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 3140 { 3141 MatFactorInfo tinfo; 3142 3143 PetscFunctionBegin; 3144 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 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(fact, 1); 3150 PetscValidType(mat, 2); 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 MatCheckPreallocated(mat, 2); 3154 if (!info) { 3155 PetscCall(MatFactorInfoInitialize(&tinfo)); 3156 info = &tinfo; 3157 } 3158 3159 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0)); 3160 PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info); 3161 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0)); 3162 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3163 PetscFunctionReturn(PETSC_SUCCESS); 3164 } 3165 3166 /*@C 3167 MatLUFactorNumeric - Performs numeric LU factorization of a matrix. 3168 Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`. 3169 3170 Collective 3171 3172 Input Parameters: 3173 + fact - the factor matrix obtained with `MatGetFactor()` 3174 . mat - the matrix 3175 - info - options for factorization 3176 3177 Level: developer 3178 3179 Notes: 3180 See `MatLUFactor()` for in-place factorization. See 3181 `MatCholeskyFactorNumeric()` for the symmetric, positive definite case. 3182 3183 Most users should employ the `KSP` interface for linear solvers 3184 instead of working directly with matrix algebra routines such as this. 3185 See, e.g., `KSPCreate()`. 3186 3187 Developer Note: 3188 The Fortran interface is not autogenerated as the 3189 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3190 3191 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()` 3192 @*/ 3193 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3194 { 3195 MatFactorInfo tinfo; 3196 3197 PetscFunctionBegin; 3198 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3199 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3200 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3201 PetscValidType(fact, 1); 3202 PetscValidType(mat, 2); 3203 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3204 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, 3205 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3206 3207 MatCheckPreallocated(mat, 2); 3208 if (!info) { 3209 PetscCall(MatFactorInfoInitialize(&tinfo)); 3210 info = &tinfo; 3211 } 3212 3213 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3214 else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0)); 3215 PetscUseTypeMethod(fact, lufactornumeric, mat, info); 3216 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3217 else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0)); 3218 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3219 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3220 PetscFunctionReturn(PETSC_SUCCESS); 3221 } 3222 3223 /*@C 3224 MatCholeskyFactor - Performs in-place Cholesky factorization of a 3225 symmetric matrix. 3226 3227 Collective 3228 3229 Input Parameters: 3230 + mat - the matrix 3231 . perm - row and column permutations 3232 - f - expected fill as ratio of original fill 3233 3234 Level: developer 3235 3236 Notes: 3237 See `MatLUFactor()` for the nonsymmetric case. See also `MatGetFactor()`, 3238 `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`. 3239 3240 Most users should employ the `KSP` interface for linear solvers 3241 instead of working directly with matrix algebra routines such as this. 3242 See, e.g., `KSPCreate()`. 3243 3244 Developer Note: 3245 The Fortran interface is not autogenerated as the 3246 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3247 3248 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()` 3249 `MatGetOrdering()` 3250 @*/ 3251 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info) 3252 { 3253 MatFactorInfo tinfo; 3254 3255 PetscFunctionBegin; 3256 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3257 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2); 3258 if (info) PetscValidPointer(info, 3); 3259 PetscValidType(mat, 1); 3260 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3261 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3262 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3263 MatCheckPreallocated(mat, 1); 3264 if (!info) { 3265 PetscCall(MatFactorInfoInitialize(&tinfo)); 3266 info = &tinfo; 3267 } 3268 3269 PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0)); 3270 PetscUseTypeMethod(mat, choleskyfactor, perm, info); 3271 PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0)); 3272 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3273 PetscFunctionReturn(PETSC_SUCCESS); 3274 } 3275 3276 /*@C 3277 MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization 3278 of a symmetric matrix. 3279 3280 Collective 3281 3282 Input Parameters: 3283 + fact - the factor matrix obtained with `MatGetFactor()` 3284 . mat - the matrix 3285 . perm - row and column permutations 3286 - info - options for factorization, includes 3287 .vb 3288 fill - expected fill as ratio of original fill. 3289 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3290 Run with the option -info to determine an optimal value to use 3291 .ve 3292 3293 Level: developer 3294 3295 Notes: 3296 See `MatLUFactorSymbolic()` for the nonsymmetric case. See also 3297 `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`. 3298 3299 Most users should employ the `KSP` interface for linear solvers 3300 instead of working directly with matrix algebra routines such as this. 3301 See, e.g., `KSPCreate()`. 3302 3303 Developer Note: 3304 The Fortran interface is not autogenerated as the 3305 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3306 3307 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()` 3308 `MatGetOrdering()` 3309 @*/ 3310 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 3311 { 3312 MatFactorInfo tinfo; 3313 3314 PetscFunctionBegin; 3315 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3316 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3317 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 3318 if (info) PetscValidPointer(info, 4); 3319 PetscValidType(fact, 1); 3320 PetscValidType(mat, 2); 3321 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3322 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3323 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3324 MatCheckPreallocated(mat, 2); 3325 if (!info) { 3326 PetscCall(MatFactorInfoInitialize(&tinfo)); 3327 info = &tinfo; 3328 } 3329 3330 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3331 PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info); 3332 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3333 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3334 PetscFunctionReturn(PETSC_SUCCESS); 3335 } 3336 3337 /*@C 3338 MatCholeskyFactorNumeric - Performs numeric Cholesky factorization 3339 of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and 3340 `MatCholeskyFactorSymbolic()`. 3341 3342 Collective 3343 3344 Input Parameters: 3345 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored 3346 . mat - the initial matrix that is to be factored 3347 - info - options for factorization 3348 3349 Level: developer 3350 3351 Note: 3352 Most users should employ the `KSP` interface for linear solvers 3353 instead of working directly with matrix algebra routines such as this. 3354 See, e.g., `KSPCreate()`. 3355 3356 Developer Note: 3357 The Fortran interface is not autogenerated as the 3358 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3359 3360 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()` 3361 @*/ 3362 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3363 { 3364 MatFactorInfo tinfo; 3365 3366 PetscFunctionBegin; 3367 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3368 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3369 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3370 PetscValidType(fact, 1); 3371 PetscValidType(mat, 2); 3372 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3373 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, 3374 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3375 MatCheckPreallocated(mat, 2); 3376 if (!info) { 3377 PetscCall(MatFactorInfoInitialize(&tinfo)); 3378 info = &tinfo; 3379 } 3380 3381 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3382 else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0)); 3383 PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info); 3384 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3385 else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0)); 3386 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3387 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3388 PetscFunctionReturn(PETSC_SUCCESS); 3389 } 3390 3391 /*@ 3392 MatQRFactor - Performs in-place QR factorization of matrix. 3393 3394 Collective 3395 3396 Input Parameters: 3397 + mat - the matrix 3398 . col - column permutation 3399 - info - options for factorization, includes 3400 .vb 3401 fill - expected fill as ratio of original fill. 3402 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3403 Run with the option -info to determine an optimal value to use 3404 .ve 3405 3406 Level: developer 3407 3408 Notes: 3409 Most users should employ the `KSP` interface for linear solvers 3410 instead of working directly with matrix algebra routines such as this. 3411 See, e.g., `KSPCreate()`. 3412 3413 This changes the state of the matrix to a factored matrix; it cannot be used 3414 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3415 3416 Developer Note: 3417 The Fortran interface is not autogenerated as the 3418 interface definition cannot be generated correctly [due to MatFactorInfo] 3419 3420 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`, 3421 `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3422 @*/ 3423 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info) 3424 { 3425 PetscFunctionBegin; 3426 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3427 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2); 3428 if (info) PetscValidPointer(info, 3); 3429 PetscValidType(mat, 1); 3430 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3431 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3432 MatCheckPreallocated(mat, 1); 3433 PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0)); 3434 PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info)); 3435 PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0)); 3436 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3437 PetscFunctionReturn(PETSC_SUCCESS); 3438 } 3439 3440 /*@ 3441 MatQRFactorSymbolic - Performs symbolic QR factorization of matrix. 3442 Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`. 3443 3444 Collective 3445 3446 Input Parameters: 3447 + fact - the factor matrix obtained with `MatGetFactor()` 3448 . mat - the matrix 3449 . col - column permutation 3450 - info - options for factorization, includes 3451 .vb 3452 fill - expected fill as ratio of original fill. 3453 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3454 Run with the option -info to determine an optimal value to use 3455 .ve 3456 3457 Level: developer 3458 3459 Note: 3460 Most users should employ the `KSP` interface for linear solvers 3461 instead of working directly with matrix algebra routines such as this. 3462 See, e.g., `KSPCreate()`. 3463 3464 Developer Note: 3465 The Fortran interface is not autogenerated as the 3466 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3467 3468 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3469 @*/ 3470 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info) 3471 { 3472 MatFactorInfo tinfo; 3473 3474 PetscFunctionBegin; 3475 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3476 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3477 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3478 if (info) PetscValidPointer(info, 4); 3479 PetscValidType(fact, 1); 3480 PetscValidType(mat, 2); 3481 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3482 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3483 MatCheckPreallocated(mat, 2); 3484 if (!info) { 3485 PetscCall(MatFactorInfoInitialize(&tinfo)); 3486 info = &tinfo; 3487 } 3488 3489 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3490 PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info)); 3491 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3492 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3493 PetscFunctionReturn(PETSC_SUCCESS); 3494 } 3495 3496 /*@ 3497 MatQRFactorNumeric - Performs numeric QR factorization of a matrix. 3498 Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`. 3499 3500 Collective 3501 3502 Input Parameters: 3503 + fact - the factor matrix obtained with `MatGetFactor()` 3504 . mat - the matrix 3505 - info - options for factorization 3506 3507 Level: developer 3508 3509 Notes: 3510 See `MatQRFactor()` for in-place factorization. 3511 3512 Most users should employ the `KSP` interface for linear solvers 3513 instead of working directly with matrix algebra routines such as this. 3514 See, e.g., `KSPCreate()`. 3515 3516 Developer Note: 3517 The Fortran interface is not autogenerated as the 3518 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3519 3520 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()` 3521 @*/ 3522 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3523 { 3524 MatFactorInfo tinfo; 3525 3526 PetscFunctionBegin; 3527 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3528 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3529 PetscValidType(fact, 1); 3530 PetscValidType(mat, 2); 3531 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3532 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, 3533 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3534 3535 MatCheckPreallocated(mat, 2); 3536 if (!info) { 3537 PetscCall(MatFactorInfoInitialize(&tinfo)); 3538 info = &tinfo; 3539 } 3540 3541 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3542 else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0)); 3543 PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info)); 3544 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3545 else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0)); 3546 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3547 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3548 PetscFunctionReturn(PETSC_SUCCESS); 3549 } 3550 3551 /*@ 3552 MatSolve - Solves A x = b, given a factored matrix. 3553 3554 Neighbor-wise Collective 3555 3556 Input Parameters: 3557 + mat - the factored matrix 3558 - b - the right-hand-side vector 3559 3560 Output Parameter: 3561 . x - the result vector 3562 3563 Level: developer 3564 3565 Notes: 3566 The vectors `b` and `x` cannot be the same. I.e., one cannot 3567 call `MatSolve`(A,x,x). 3568 3569 Most users should employ the `KSP` interface for linear solvers 3570 instead of working directly with matrix algebra routines such as this. 3571 See, e.g., `KSPCreate()`. 3572 3573 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3574 @*/ 3575 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x) 3576 { 3577 PetscFunctionBegin; 3578 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3579 PetscValidType(mat, 1); 3580 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3581 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3582 PetscCheckSameComm(mat, 1, b, 2); 3583 PetscCheckSameComm(mat, 1, x, 3); 3584 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3585 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); 3586 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); 3587 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); 3588 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3589 MatCheckPreallocated(mat, 1); 3590 3591 PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0)); 3592 if (mat->factorerrortype) { 3593 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3594 PetscCall(VecSetInf(x)); 3595 } else PetscUseTypeMethod(mat, solve, b, x); 3596 PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0)); 3597 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3598 PetscFunctionReturn(PETSC_SUCCESS); 3599 } 3600 3601 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans) 3602 { 3603 Vec b, x; 3604 PetscInt N, i; 3605 PetscErrorCode (*f)(Mat, Vec, Vec); 3606 PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE; 3607 3608 PetscFunctionBegin; 3609 if (A->factorerrortype) { 3610 PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype)); 3611 PetscCall(MatSetInf(X)); 3612 PetscFunctionReturn(PETSC_SUCCESS); 3613 } 3614 f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose; 3615 PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 3616 PetscCall(MatBoundToCPU(A, &Abound)); 3617 if (!Abound) { 3618 PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3619 PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3620 } 3621 #if PetscDefined(HAVE_CUDA) 3622 if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B)); 3623 if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X)); 3624 #elif PetscDefined(HAVE_HIP) 3625 if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B)); 3626 if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X)); 3627 #endif 3628 PetscCall(MatGetSize(B, NULL, &N)); 3629 for (i = 0; i < N; i++) { 3630 PetscCall(MatDenseGetColumnVecRead(B, i, &b)); 3631 PetscCall(MatDenseGetColumnVecWrite(X, i, &x)); 3632 PetscCall((*f)(A, b, x)); 3633 PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x)); 3634 PetscCall(MatDenseRestoreColumnVecRead(B, i, &b)); 3635 } 3636 if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B)); 3637 if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X)); 3638 PetscFunctionReturn(PETSC_SUCCESS); 3639 } 3640 3641 /*@ 3642 MatMatSolve - Solves A X = B, given a factored matrix. 3643 3644 Neighbor-wise Collective 3645 3646 Input Parameters: 3647 + A - the factored matrix 3648 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS) 3649 3650 Output Parameter: 3651 . X - the result matrix (dense matrix) 3652 3653 Level: developer 3654 3655 Note: 3656 If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`; 3657 otherwise, `B` and `X` cannot be the same. 3658 3659 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3660 @*/ 3661 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X) 3662 { 3663 PetscFunctionBegin; 3664 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3665 PetscValidType(A, 1); 3666 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3667 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3668 PetscCheckSameComm(A, 1, B, 2); 3669 PetscCheckSameComm(A, 1, X, 3); 3670 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); 3671 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); 3672 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"); 3673 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3674 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3675 MatCheckPreallocated(A, 1); 3676 3677 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3678 if (!A->ops->matsolve) { 3679 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name)); 3680 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE)); 3681 } else PetscUseTypeMethod(A, matsolve, B, X); 3682 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3683 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3684 PetscFunctionReturn(PETSC_SUCCESS); 3685 } 3686 3687 /*@ 3688 MatMatSolveTranspose - Solves A^T X = B, given a factored matrix. 3689 3690 Neighbor-wise Collective 3691 3692 Input Parameters: 3693 + A - the factored matrix 3694 - B - the right-hand-side matrix (`MATDENSE` matrix) 3695 3696 Output Parameter: 3697 . X - the result matrix (dense matrix) 3698 3699 Level: developer 3700 3701 Note: 3702 The matrices `B` and `X` cannot be the same. I.e., one cannot 3703 call `MatMatSolveTranspose`(A,X,X). 3704 3705 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()` 3706 @*/ 3707 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X) 3708 { 3709 PetscFunctionBegin; 3710 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3711 PetscValidType(A, 1); 3712 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3713 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3714 PetscCheckSameComm(A, 1, B, 2); 3715 PetscCheckSameComm(A, 1, X, 3); 3716 PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3717 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); 3718 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); 3719 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); 3720 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"); 3721 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3722 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3723 MatCheckPreallocated(A, 1); 3724 3725 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3726 if (!A->ops->matsolvetranspose) { 3727 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name)); 3728 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE)); 3729 } else PetscUseTypeMethod(A, matsolvetranspose, B, X); 3730 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3731 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3732 PetscFunctionReturn(PETSC_SUCCESS); 3733 } 3734 3735 /*@ 3736 MatMatTransposeSolve - Solves A X = B^T, given a factored matrix. 3737 3738 Neighbor-wise Collective 3739 3740 Input Parameters: 3741 + A - the factored matrix 3742 - Bt - the transpose of right-hand-side matrix as a `MATDENSE` 3743 3744 Output Parameter: 3745 . X - the result matrix (dense matrix) 3746 3747 Level: developer 3748 3749 Note: 3750 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 3751 format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`. 3752 3753 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3754 @*/ 3755 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X) 3756 { 3757 PetscFunctionBegin; 3758 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3759 PetscValidType(A, 1); 3760 PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2); 3761 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3762 PetscCheckSameComm(A, 1, Bt, 2); 3763 PetscCheckSameComm(A, 1, X, 3); 3764 3765 PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3766 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); 3767 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); 3768 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"); 3769 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3770 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3771 MatCheckPreallocated(A, 1); 3772 3773 PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0)); 3774 PetscUseTypeMethod(A, mattransposesolve, Bt, X); 3775 PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0)); 3776 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3777 PetscFunctionReturn(PETSC_SUCCESS); 3778 } 3779 3780 /*@ 3781 MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or 3782 U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U, 3783 3784 Neighbor-wise Collective 3785 3786 Input Parameters: 3787 + mat - the factored matrix 3788 - b - the right-hand-side vector 3789 3790 Output Parameter: 3791 . x - the result vector 3792 3793 Level: developer 3794 3795 Notes: 3796 `MatSolve()` should be used for most applications, as it performs 3797 a forward solve followed by a backward solve. 3798 3799 The vectors `b` and `x` cannot be the same, i.e., one cannot 3800 call `MatForwardSolve`(A,x,x). 3801 3802 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3803 the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet. 3804 `MatForwardSolve()` solves U^T*D y = b, and 3805 `MatBackwardSolve()` solves U x = y. 3806 Thus they do not provide a symmetric preconditioner. 3807 3808 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatBackwardSolve()` 3809 @*/ 3810 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x) 3811 { 3812 PetscFunctionBegin; 3813 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3814 PetscValidType(mat, 1); 3815 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3816 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3817 PetscCheckSameComm(mat, 1, b, 2); 3818 PetscCheckSameComm(mat, 1, x, 3); 3819 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3820 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); 3821 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); 3822 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); 3823 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3824 MatCheckPreallocated(mat, 1); 3825 3826 PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0)); 3827 PetscUseTypeMethod(mat, forwardsolve, b, x); 3828 PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0)); 3829 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3830 PetscFunctionReturn(PETSC_SUCCESS); 3831 } 3832 3833 /*@ 3834 MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU. 3835 D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U, 3836 3837 Neighbor-wise Collective 3838 3839 Input Parameters: 3840 + mat - the factored matrix 3841 - b - the right-hand-side vector 3842 3843 Output Parameter: 3844 . x - the result vector 3845 3846 Level: developer 3847 3848 Notes: 3849 `MatSolve()` should be used for most applications, as it performs 3850 a forward solve followed by a backward solve. 3851 3852 The vectors `b` and `x` cannot be the same. I.e., one cannot 3853 call `MatBackwardSolve`(A,x,x). 3854 3855 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3856 the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet. 3857 `MatForwardSolve()` solves U^T*D y = b, and 3858 `MatBackwardSolve()` solves U x = y. 3859 Thus they do not provide a symmetric preconditioner. 3860 3861 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatForwardSolve()` 3862 @*/ 3863 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x) 3864 { 3865 PetscFunctionBegin; 3866 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3867 PetscValidType(mat, 1); 3868 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3869 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3870 PetscCheckSameComm(mat, 1, b, 2); 3871 PetscCheckSameComm(mat, 1, x, 3); 3872 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3873 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); 3874 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); 3875 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); 3876 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3877 MatCheckPreallocated(mat, 1); 3878 3879 PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0)); 3880 PetscUseTypeMethod(mat, backwardsolve, b, x); 3881 PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0)); 3882 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3883 PetscFunctionReturn(PETSC_SUCCESS); 3884 } 3885 3886 /*@ 3887 MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix. 3888 3889 Neighbor-wise Collective 3890 3891 Input Parameters: 3892 + mat - the factored matrix 3893 . b - the right-hand-side vector 3894 - y - the vector to be added to 3895 3896 Output Parameter: 3897 . x - the result vector 3898 3899 Level: developer 3900 3901 Note: 3902 The vectors `b` and `x` cannot be the same. I.e., one cannot 3903 call `MatSolveAdd`(A,x,y,x). 3904 3905 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3906 @*/ 3907 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x) 3908 { 3909 PetscScalar one = 1.0; 3910 Vec tmp; 3911 3912 PetscFunctionBegin; 3913 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3914 PetscValidType(mat, 1); 3915 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 3916 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3917 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 3918 PetscCheckSameComm(mat, 1, b, 2); 3919 PetscCheckSameComm(mat, 1, y, 3); 3920 PetscCheckSameComm(mat, 1, x, 4); 3921 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3922 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); 3923 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); 3924 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); 3925 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); 3926 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); 3927 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3928 MatCheckPreallocated(mat, 1); 3929 3930 PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y)); 3931 if (mat->factorerrortype) { 3932 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3933 PetscCall(VecSetInf(x)); 3934 } else if (mat->ops->solveadd) { 3935 PetscUseTypeMethod(mat, solveadd, b, y, x); 3936 } else { 3937 /* do the solve then the add manually */ 3938 if (x != y) { 3939 PetscCall(MatSolve(mat, b, x)); 3940 PetscCall(VecAXPY(x, one, y)); 3941 } else { 3942 PetscCall(VecDuplicate(x, &tmp)); 3943 PetscCall(VecCopy(x, tmp)); 3944 PetscCall(MatSolve(mat, b, x)); 3945 PetscCall(VecAXPY(x, one, tmp)); 3946 PetscCall(VecDestroy(&tmp)); 3947 } 3948 } 3949 PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y)); 3950 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3951 PetscFunctionReturn(PETSC_SUCCESS); 3952 } 3953 3954 /*@ 3955 MatSolveTranspose - Solves A' x = b, given a factored matrix. 3956 3957 Neighbor-wise Collective 3958 3959 Input Parameters: 3960 + mat - the factored matrix 3961 - b - the right-hand-side vector 3962 3963 Output Parameter: 3964 . x - the result vector 3965 3966 Level: developer 3967 3968 Notes: 3969 The vectors `b` and `x` cannot be the same. I.e., one cannot 3970 call `MatSolveTranspose`(A,x,x). 3971 3972 Most users should employ the `KSP` interface for linear solvers 3973 instead of working directly with matrix algebra routines such as this. 3974 See, e.g., `KSPCreate()`. 3975 3976 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()` 3977 @*/ 3978 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x) 3979 { 3980 PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose; 3981 3982 PetscFunctionBegin; 3983 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3984 PetscValidType(mat, 1); 3985 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3986 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3987 PetscCheckSameComm(mat, 1, b, 2); 3988 PetscCheckSameComm(mat, 1, x, 3); 3989 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3990 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); 3991 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); 3992 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3993 MatCheckPreallocated(mat, 1); 3994 PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0)); 3995 if (mat->factorerrortype) { 3996 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3997 PetscCall(VecSetInf(x)); 3998 } else { 3999 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name); 4000 PetscCall((*f)(mat, b, x)); 4001 } 4002 PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0)); 4003 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4004 PetscFunctionReturn(PETSC_SUCCESS); 4005 } 4006 4007 /*@ 4008 MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a 4009 factored matrix. 4010 4011 Neighbor-wise Collective 4012 4013 Input Parameters: 4014 + mat - the factored matrix 4015 . b - the right-hand-side vector 4016 - y - the vector to be added to 4017 4018 Output Parameter: 4019 . x - the result vector 4020 4021 Level: developer 4022 4023 Note: 4024 The vectors `b` and `x` cannot be the same. I.e., one cannot 4025 call `MatSolveTransposeAdd`(A,x,y,x). 4026 4027 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()` 4028 @*/ 4029 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x) 4030 { 4031 PetscScalar one = 1.0; 4032 Vec tmp; 4033 PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd; 4034 4035 PetscFunctionBegin; 4036 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4037 PetscValidType(mat, 1); 4038 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4039 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4040 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4041 PetscCheckSameComm(mat, 1, b, 2); 4042 PetscCheckSameComm(mat, 1, y, 3); 4043 PetscCheckSameComm(mat, 1, x, 4); 4044 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4045 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); 4046 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); 4047 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); 4048 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); 4049 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4050 MatCheckPreallocated(mat, 1); 4051 4052 PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y)); 4053 if (mat->factorerrortype) { 4054 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4055 PetscCall(VecSetInf(x)); 4056 } else if (f) { 4057 PetscCall((*f)(mat, b, y, x)); 4058 } else { 4059 /* do the solve then the add manually */ 4060 if (x != y) { 4061 PetscCall(MatSolveTranspose(mat, b, x)); 4062 PetscCall(VecAXPY(x, one, y)); 4063 } else { 4064 PetscCall(VecDuplicate(x, &tmp)); 4065 PetscCall(VecCopy(x, tmp)); 4066 PetscCall(MatSolveTranspose(mat, b, x)); 4067 PetscCall(VecAXPY(x, one, tmp)); 4068 PetscCall(VecDestroy(&tmp)); 4069 } 4070 } 4071 PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y)); 4072 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4073 PetscFunctionReturn(PETSC_SUCCESS); 4074 } 4075 4076 /*@ 4077 MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps. 4078 4079 Neighbor-wise Collective 4080 4081 Input Parameters: 4082 + mat - the matrix 4083 . b - the right hand side 4084 . omega - the relaxation factor 4085 . flag - flag indicating the type of SOR (see below) 4086 . shift - diagonal shift 4087 . its - the number of iterations 4088 - lits - the number of local iterations 4089 4090 Output Parameter: 4091 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess) 4092 4093 SOR Flags: 4094 + `SOR_FORWARD_SWEEP` - forward SOR 4095 . `SOR_BACKWARD_SWEEP` - backward SOR 4096 . `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR) 4097 . `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR 4098 . `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR 4099 . `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR 4100 . `SOR_EISENSTAT` - SOR with Eisenstat trick 4101 . `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies 4102 upper/lower triangular part of matrix to 4103 vector (with omega) 4104 - `SOR_ZERO_INITIAL_GUESS` - zero initial guess 4105 4106 Level: developer 4107 4108 Notes: 4109 `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and 4110 `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings 4111 on each processor. 4112 4113 Application programmers will not generally use `MatSOR()` directly, 4114 but instead will employ the `KSP`/`PC` interface. 4115 4116 For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing 4117 4118 Most users should employ the `KSP` interface for linear solvers 4119 instead of working directly with matrix algebra routines such as this. 4120 See, e.g., `KSPCreate()`. 4121 4122 Vectors `x` and `b` CANNOT be the same 4123 4124 The flags are implemented as bitwise inclusive or operations. 4125 For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`) 4126 to specify a zero initial guess for SSOR. 4127 4128 Developer Note: 4129 We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes 4130 4131 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()` 4132 @*/ 4133 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x) 4134 { 4135 PetscFunctionBegin; 4136 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4137 PetscValidType(mat, 1); 4138 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4139 PetscValidHeaderSpecific(x, VEC_CLASSID, 8); 4140 PetscCheckSameComm(mat, 1, b, 2); 4141 PetscCheckSameComm(mat, 1, x, 8); 4142 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4143 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4144 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); 4145 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); 4146 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); 4147 PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its); 4148 PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits); 4149 PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same"); 4150 4151 MatCheckPreallocated(mat, 1); 4152 PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0)); 4153 PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x); 4154 PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0)); 4155 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4156 PetscFunctionReturn(PETSC_SUCCESS); 4157 } 4158 4159 /* 4160 Default matrix copy routine. 4161 */ 4162 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str) 4163 { 4164 PetscInt i, rstart = 0, rend = 0, nz; 4165 const PetscInt *cwork; 4166 const PetscScalar *vwork; 4167 4168 PetscFunctionBegin; 4169 if (B->assembled) PetscCall(MatZeroEntries(B)); 4170 if (str == SAME_NONZERO_PATTERN) { 4171 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 4172 for (i = rstart; i < rend; i++) { 4173 PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork)); 4174 PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES)); 4175 PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork)); 4176 } 4177 } else { 4178 PetscCall(MatAYPX(B, 0.0, A, str)); 4179 } 4180 PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 4181 PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 4182 PetscFunctionReturn(PETSC_SUCCESS); 4183 } 4184 4185 /*@ 4186 MatCopy - Copies a matrix to another matrix. 4187 4188 Collective 4189 4190 Input Parameters: 4191 + A - the matrix 4192 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN` 4193 4194 Output Parameter: 4195 . B - where the copy is put 4196 4197 Level: intermediate 4198 4199 Notes: 4200 If you use `SAME_NONZERO_PATTERN` then the two matrices must have the same nonzero pattern or the routine will crash. 4201 4202 `MatCopy()` copies the matrix entries of a matrix to another existing 4203 matrix (after first zeroing the second matrix). A related routine is 4204 `MatConvert()`, which first creates a new matrix and then copies the data. 4205 4206 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()` 4207 @*/ 4208 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str) 4209 { 4210 PetscInt i; 4211 4212 PetscFunctionBegin; 4213 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 4214 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 4215 PetscValidType(A, 1); 4216 PetscValidType(B, 2); 4217 PetscCheckSameComm(A, 1, B, 2); 4218 MatCheckPreallocated(B, 2); 4219 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4220 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4221 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, 4222 A->cmap->N, B->cmap->N); 4223 MatCheckPreallocated(A, 1); 4224 if (A == B) PetscFunctionReturn(PETSC_SUCCESS); 4225 4226 PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0)); 4227 if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str); 4228 else PetscCall(MatCopy_Basic(A, B, str)); 4229 4230 B->stencil.dim = A->stencil.dim; 4231 B->stencil.noc = A->stencil.noc; 4232 for (i = 0; i <= A->stencil.dim; i++) { 4233 B->stencil.dims[i] = A->stencil.dims[i]; 4234 B->stencil.starts[i] = A->stencil.starts[i]; 4235 } 4236 4237 PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0)); 4238 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4239 PetscFunctionReturn(PETSC_SUCCESS); 4240 } 4241 4242 /*@C 4243 MatConvert - Converts a matrix to another matrix, either of the same 4244 or different type. 4245 4246 Collective 4247 4248 Input Parameters: 4249 + mat - the matrix 4250 . newtype - new matrix type. Use `MATSAME` to create a new matrix of the 4251 same type as the original matrix. 4252 - reuse - denotes if the destination matrix is to be created or reused. 4253 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 4254 `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). 4255 4256 Output Parameter: 4257 . M - pointer to place new matrix 4258 4259 Level: intermediate 4260 4261 Notes: 4262 `MatConvert()` first creates a new matrix and then copies the data from 4263 the first matrix. A related routine is `MatCopy()`, which copies the matrix 4264 entries of one matrix to another already existing matrix context. 4265 4266 Cannot be used to convert a sequential matrix to parallel or parallel to sequential, 4267 the MPI communicator of the generated matrix is always the same as the communicator 4268 of the input matrix. 4269 4270 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 4271 @*/ 4272 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M) 4273 { 4274 PetscBool sametype, issame, flg; 4275 PetscBool3 issymmetric, ishermitian; 4276 char convname[256], mtype[256]; 4277 Mat B; 4278 4279 PetscFunctionBegin; 4280 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4281 PetscValidType(mat, 1); 4282 PetscValidPointer(M, 4); 4283 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4284 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4285 MatCheckPreallocated(mat, 1); 4286 4287 PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg)); 4288 if (flg) newtype = mtype; 4289 4290 PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype)); 4291 PetscCall(PetscStrcmp(newtype, "same", &issame)); 4292 PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix"); 4293 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"); 4294 4295 if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) { 4296 PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4297 PetscFunctionReturn(PETSC_SUCCESS); 4298 } 4299 4300 /* Cache Mat options because some converters use MatHeaderReplace */ 4301 issymmetric = mat->symmetric; 4302 ishermitian = mat->hermitian; 4303 4304 if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) { 4305 PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4306 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4307 } else { 4308 PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL; 4309 const char *prefix[3] = {"seq", "mpi", ""}; 4310 PetscInt i; 4311 /* 4312 Order of precedence: 4313 0) See if newtype is a superclass of the current matrix. 4314 1) See if a specialized converter is known to the current matrix. 4315 2) See if a specialized converter is known to the desired matrix class. 4316 3) See if a good general converter is registered for the desired class 4317 (as of 6/27/03 only MATMPIADJ falls into this category). 4318 4) See if a good general converter is known for the current matrix. 4319 5) Use a really basic converter. 4320 */ 4321 4322 /* 0) See if newtype is a superclass of the current matrix. 4323 i.e mat is mpiaij and newtype is aij */ 4324 for (i = 0; i < 2; i++) { 4325 PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname))); 4326 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4327 PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg)); 4328 PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg)); 4329 if (flg) { 4330 if (reuse == MAT_INPLACE_MATRIX) { 4331 PetscCall(PetscInfo(mat, "Early return\n")); 4332 PetscFunctionReturn(PETSC_SUCCESS); 4333 } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) { 4334 PetscCall(PetscInfo(mat, "Calling MatDuplicate\n")); 4335 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4336 PetscFunctionReturn(PETSC_SUCCESS); 4337 } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) { 4338 PetscCall(PetscInfo(mat, "Calling MatCopy\n")); 4339 PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN)); 4340 PetscFunctionReturn(PETSC_SUCCESS); 4341 } 4342 } 4343 } 4344 /* 1) See if a specialized converter is known to the current matrix and the desired class */ 4345 for (i = 0; i < 3; i++) { 4346 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4347 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4348 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4349 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4350 PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname))); 4351 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4352 PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv)); 4353 PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv)); 4354 if (conv) goto foundconv; 4355 } 4356 4357 /* 2) See if a specialized converter is known to the desired matrix class. */ 4358 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B)); 4359 PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 4360 PetscCall(MatSetType(B, newtype)); 4361 for (i = 0; i < 3; i++) { 4362 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4363 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4364 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4365 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4366 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4367 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4368 PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv)); 4369 PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv)); 4370 if (conv) { 4371 PetscCall(MatDestroy(&B)); 4372 goto foundconv; 4373 } 4374 } 4375 4376 /* 3) See if a good general converter is registered for the desired class */ 4377 conv = B->ops->convertfrom; 4378 PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv)); 4379 PetscCall(MatDestroy(&B)); 4380 if (conv) goto foundconv; 4381 4382 /* 4) See if a good general converter is known for the current matrix */ 4383 if (mat->ops->convert) conv = mat->ops->convert; 4384 PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv)); 4385 if (conv) goto foundconv; 4386 4387 /* 5) Use a really basic converter. */ 4388 PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n")); 4389 conv = MatConvert_Basic; 4390 4391 foundconv: 4392 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4393 PetscCall((*conv)(mat, newtype, reuse, M)); 4394 if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) { 4395 /* the block sizes must be same if the mappings are copied over */ 4396 (*M)->rmap->bs = mat->rmap->bs; 4397 (*M)->cmap->bs = mat->cmap->bs; 4398 PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping)); 4399 PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping)); 4400 (*M)->rmap->mapping = mat->rmap->mapping; 4401 (*M)->cmap->mapping = mat->cmap->mapping; 4402 } 4403 (*M)->stencil.dim = mat->stencil.dim; 4404 (*M)->stencil.noc = mat->stencil.noc; 4405 for (i = 0; i <= mat->stencil.dim; i++) { 4406 (*M)->stencil.dims[i] = mat->stencil.dims[i]; 4407 (*M)->stencil.starts[i] = mat->stencil.starts[i]; 4408 } 4409 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4410 } 4411 PetscCall(PetscObjectStateIncrease((PetscObject)*M)); 4412 4413 /* Copy Mat options */ 4414 if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE)); 4415 else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE)); 4416 if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE)); 4417 else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE)); 4418 PetscFunctionReturn(PETSC_SUCCESS); 4419 } 4420 4421 /*@C 4422 MatFactorGetSolverType - Returns name of the package providing the factorization routines 4423 4424 Not Collective 4425 4426 Input Parameter: 4427 . mat - the matrix, must be a factored matrix 4428 4429 Output Parameter: 4430 . type - the string name of the package (do not free this string) 4431 4432 Level: intermediate 4433 4434 Fortran Note: 4435 Pass in an empty string and the package name will be copied into it. Make sure the string is long enough. 4436 4437 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()` 4438 @*/ 4439 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type) 4440 { 4441 PetscErrorCode (*conv)(Mat, MatSolverType *); 4442 4443 PetscFunctionBegin; 4444 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4445 PetscValidType(mat, 1); 4446 PetscValidPointer(type, 2); 4447 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 4448 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv)); 4449 if (conv) PetscCall((*conv)(mat, type)); 4450 else *type = MATSOLVERPETSC; 4451 PetscFunctionReturn(PETSC_SUCCESS); 4452 } 4453 4454 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType; 4455 struct _MatSolverTypeForSpecifcType { 4456 MatType mtype; 4457 /* no entry for MAT_FACTOR_NONE */ 4458 PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *); 4459 MatSolverTypeForSpecifcType next; 4460 }; 4461 4462 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder; 4463 struct _MatSolverTypeHolder { 4464 char *name; 4465 MatSolverTypeForSpecifcType handlers; 4466 MatSolverTypeHolder next; 4467 }; 4468 4469 static MatSolverTypeHolder MatSolverTypeHolders = NULL; 4470 4471 /*@C 4472 MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type 4473 4474 Input Parameters: 4475 + package - name of the package, for example petsc or superlu 4476 . mtype - the matrix type that works with this package 4477 . ftype - the type of factorization supported by the package 4478 - createfactor - routine that will create the factored matrix ready to be used 4479 4480 Level: developer 4481 4482 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()` 4483 @*/ 4484 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *)) 4485 { 4486 MatSolverTypeHolder next = MatSolverTypeHolders, prev = NULL; 4487 PetscBool flg; 4488 MatSolverTypeForSpecifcType inext, iprev = NULL; 4489 4490 PetscFunctionBegin; 4491 PetscCall(MatInitializePackage()); 4492 if (!next) { 4493 PetscCall(PetscNew(&MatSolverTypeHolders)); 4494 PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name)); 4495 PetscCall(PetscNew(&MatSolverTypeHolders->handlers)); 4496 PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype)); 4497 MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor; 4498 PetscFunctionReturn(PETSC_SUCCESS); 4499 } 4500 while (next) { 4501 PetscCall(PetscStrcasecmp(package, next->name, &flg)); 4502 if (flg) { 4503 PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers"); 4504 inext = next->handlers; 4505 while (inext) { 4506 PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg)); 4507 if (flg) { 4508 inext->createfactor[(int)ftype - 1] = createfactor; 4509 PetscFunctionReturn(PETSC_SUCCESS); 4510 } 4511 iprev = inext; 4512 inext = inext->next; 4513 } 4514 PetscCall(PetscNew(&iprev->next)); 4515 PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype)); 4516 iprev->next->createfactor[(int)ftype - 1] = createfactor; 4517 PetscFunctionReturn(PETSC_SUCCESS); 4518 } 4519 prev = next; 4520 next = next->next; 4521 } 4522 PetscCall(PetscNew(&prev->next)); 4523 PetscCall(PetscStrallocpy(package, &prev->next->name)); 4524 PetscCall(PetscNew(&prev->next->handlers)); 4525 PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype)); 4526 prev->next->handlers->createfactor[(int)ftype - 1] = createfactor; 4527 PetscFunctionReturn(PETSC_SUCCESS); 4528 } 4529 4530 /*@C 4531 MatSolverTypeGet - Gets the function that creates the factor matrix if it exist 4532 4533 Input Parameters: 4534 + type - name of the package, for example petsc or superlu 4535 . ftype - the type of factorization supported by the type 4536 - mtype - the matrix type that works with this type 4537 4538 Output Parameters: 4539 + foundtype - `PETSC_TRUE` if the type was registered 4540 . foundmtype - `PETSC_TRUE` if the type supports the requested mtype 4541 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found 4542 4543 Level: developer 4544 4545 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()` 4546 @*/ 4547 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *)) 4548 { 4549 MatSolverTypeHolder next = MatSolverTypeHolders; 4550 PetscBool flg; 4551 MatSolverTypeForSpecifcType inext; 4552 4553 PetscFunctionBegin; 4554 if (foundtype) *foundtype = PETSC_FALSE; 4555 if (foundmtype) *foundmtype = PETSC_FALSE; 4556 if (createfactor) *createfactor = NULL; 4557 4558 if (type) { 4559 while (next) { 4560 PetscCall(PetscStrcasecmp(type, next->name, &flg)); 4561 if (flg) { 4562 if (foundtype) *foundtype = PETSC_TRUE; 4563 inext = next->handlers; 4564 while (inext) { 4565 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4566 if (flg) { 4567 if (foundmtype) *foundmtype = PETSC_TRUE; 4568 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4569 PetscFunctionReturn(PETSC_SUCCESS); 4570 } 4571 inext = inext->next; 4572 } 4573 } 4574 next = next->next; 4575 } 4576 } else { 4577 while (next) { 4578 inext = next->handlers; 4579 while (inext) { 4580 PetscCall(PetscStrcmp(mtype, inext->mtype, &flg)); 4581 if (flg && inext->createfactor[(int)ftype - 1]) { 4582 if (foundtype) *foundtype = PETSC_TRUE; 4583 if (foundmtype) *foundmtype = PETSC_TRUE; 4584 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4585 PetscFunctionReturn(PETSC_SUCCESS); 4586 } 4587 inext = inext->next; 4588 } 4589 next = next->next; 4590 } 4591 /* try with base classes inext->mtype */ 4592 next = MatSolverTypeHolders; 4593 while (next) { 4594 inext = next->handlers; 4595 while (inext) { 4596 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4597 if (flg && inext->createfactor[(int)ftype - 1]) { 4598 if (foundtype) *foundtype = PETSC_TRUE; 4599 if (foundmtype) *foundmtype = PETSC_TRUE; 4600 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4601 PetscFunctionReturn(PETSC_SUCCESS); 4602 } 4603 inext = inext->next; 4604 } 4605 next = next->next; 4606 } 4607 } 4608 PetscFunctionReturn(PETSC_SUCCESS); 4609 } 4610 4611 PetscErrorCode MatSolverTypeDestroy(void) 4612 { 4613 MatSolverTypeHolder next = MatSolverTypeHolders, prev; 4614 MatSolverTypeForSpecifcType inext, iprev; 4615 4616 PetscFunctionBegin; 4617 while (next) { 4618 PetscCall(PetscFree(next->name)); 4619 inext = next->handlers; 4620 while (inext) { 4621 PetscCall(PetscFree(inext->mtype)); 4622 iprev = inext; 4623 inext = inext->next; 4624 PetscCall(PetscFree(iprev)); 4625 } 4626 prev = next; 4627 next = next->next; 4628 PetscCall(PetscFree(prev)); 4629 } 4630 MatSolverTypeHolders = NULL; 4631 PetscFunctionReturn(PETSC_SUCCESS); 4632 } 4633 4634 /*@C 4635 MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4636 4637 Logically Collective 4638 4639 Input Parameter: 4640 . mat - the matrix 4641 4642 Output Parameter: 4643 . flg - `PETSC_TRUE` if uses the ordering 4644 4645 Level: developer 4646 4647 Note: 4648 Most internal PETSc factorizations use the ordering passed to the factorization routine but external 4649 packages do not, thus we want to skip generating the ordering when it is not needed or used. 4650 4651 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4652 @*/ 4653 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg) 4654 { 4655 PetscFunctionBegin; 4656 *flg = mat->canuseordering; 4657 PetscFunctionReturn(PETSC_SUCCESS); 4658 } 4659 4660 /*@C 4661 MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object 4662 4663 Logically Collective 4664 4665 Input Parameters: 4666 + mat - the matrix obtained with `MatGetFactor()` 4667 - ftype - the factorization type to be used 4668 4669 Output Parameter: 4670 . otype - the preferred ordering type 4671 4672 Level: developer 4673 4674 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4675 @*/ 4676 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype) 4677 { 4678 PetscFunctionBegin; 4679 *otype = mat->preferredordering[ftype]; 4680 PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering"); 4681 PetscFunctionReturn(PETSC_SUCCESS); 4682 } 4683 4684 /*@C 4685 MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic() 4686 4687 Collective 4688 4689 Input Parameters: 4690 + mat - the matrix 4691 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4692 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4693 4694 Output Parameter: 4695 . f - the factor matrix used with MatXXFactorSymbolic() calls 4696 4697 Options Database Key: 4698 . -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory. 4699 One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices. 4700 4701 Level: intermediate 4702 4703 Notes: 4704 Users usually access the factorization solvers via `KSP` 4705 4706 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4707 such as pastix, superlu, mumps etc. 4708 4709 PETSc must have been ./configure to use the external solver, using the option --download-package 4710 4711 Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption 4712 where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set 4713 call `MatSetOptionsPrefixFactor()` on the originating matrix or `MatSetOptionsPrefix()` on the resulting factor matrix. 4714 4715 Developer Note: 4716 This should actually be called `MatCreateFactor()` since it creates a new factor object 4717 4718 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, 4719 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4720 @*/ 4721 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f) 4722 { 4723 PetscBool foundtype, foundmtype; 4724 PetscErrorCode (*conv)(Mat, MatFactorType, Mat *); 4725 4726 PetscFunctionBegin; 4727 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4728 PetscValidType(mat, 1); 4729 4730 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4731 MatCheckPreallocated(mat, 1); 4732 4733 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv)); 4734 if (!foundtype) { 4735 if (type) { 4736 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], 4737 ((PetscObject)mat)->type_name, type); 4738 } else { 4739 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); 4740 } 4741 } 4742 PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name); 4743 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); 4744 4745 PetscCall((*conv)(mat, ftype, f)); 4746 if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix)); 4747 PetscFunctionReturn(PETSC_SUCCESS); 4748 } 4749 4750 /*@C 4751 MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type 4752 4753 Not Collective 4754 4755 Input Parameters: 4756 + mat - the matrix 4757 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4758 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4759 4760 Output Parameter: 4761 . flg - PETSC_TRUE if the factorization is available 4762 4763 Level: intermediate 4764 4765 Notes: 4766 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4767 such as pastix, superlu, mumps etc. 4768 4769 PETSc must have been ./configure to use the external solver, using the option --download-package 4770 4771 Developer Note: 4772 This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object 4773 4774 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactor()`, `MatSolverTypeRegister()`, 4775 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4776 @*/ 4777 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg) 4778 { 4779 PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *); 4780 4781 PetscFunctionBegin; 4782 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4783 PetscValidType(mat, 1); 4784 PetscValidBoolPointer(flg, 4); 4785 4786 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4787 MatCheckPreallocated(mat, 1); 4788 4789 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv)); 4790 *flg = gconv ? PETSC_TRUE : PETSC_FALSE; 4791 PetscFunctionReturn(PETSC_SUCCESS); 4792 } 4793 4794 /*@ 4795 MatDuplicate - Duplicates a matrix including the non-zero structure. 4796 4797 Collective 4798 4799 Input Parameters: 4800 + mat - the matrix 4801 - op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`. 4802 See the manual page for `MatDuplicateOption()` for an explanation of these options. 4803 4804 Output Parameter: 4805 . M - pointer to place new matrix 4806 4807 Level: intermediate 4808 4809 Notes: 4810 You cannot change the nonzero pattern for the parent or child matrix if you use `MAT_SHARE_NONZERO_PATTERN`. 4811 4812 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. 4813 4814 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 4815 is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated. 4816 User should not use `MatDuplicate()` to create new matrix M if M is intended to be reused as the product of matrix operation. 4817 4818 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption` 4819 @*/ 4820 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M) 4821 { 4822 Mat B; 4823 VecType vtype; 4824 PetscInt i; 4825 PetscObject dm; 4826 void (*viewf)(void); 4827 4828 PetscFunctionBegin; 4829 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4830 PetscValidType(mat, 1); 4831 PetscValidPointer(M, 3); 4832 PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix"); 4833 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4834 MatCheckPreallocated(mat, 1); 4835 4836 *M = NULL; 4837 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4838 PetscUseTypeMethod(mat, duplicate, op, M); 4839 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4840 B = *M; 4841 4842 PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf)); 4843 if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf)); 4844 PetscCall(MatGetVecType(mat, &vtype)); 4845 PetscCall(MatSetVecType(B, vtype)); 4846 4847 B->stencil.dim = mat->stencil.dim; 4848 B->stencil.noc = mat->stencil.noc; 4849 for (i = 0; i <= mat->stencil.dim; i++) { 4850 B->stencil.dims[i] = mat->stencil.dims[i]; 4851 B->stencil.starts[i] = mat->stencil.starts[i]; 4852 } 4853 4854 B->nooffproczerorows = mat->nooffproczerorows; 4855 B->nooffprocentries = mat->nooffprocentries; 4856 4857 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm)); 4858 if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm)); 4859 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4860 PetscFunctionReturn(PETSC_SUCCESS); 4861 } 4862 4863 /*@ 4864 MatGetDiagonal - Gets the diagonal of a matrix as a `Vec` 4865 4866 Logically Collective 4867 4868 Input Parameter: 4869 . mat - the matrix 4870 4871 Output Parameter: 4872 . v - the diagonal of the matrix 4873 4874 Level: intermediate 4875 4876 Note: 4877 Currently only correct in parallel for square matrices. 4878 4879 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()` 4880 @*/ 4881 PetscErrorCode MatGetDiagonal(Mat mat, Vec v) 4882 { 4883 PetscFunctionBegin; 4884 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4885 PetscValidType(mat, 1); 4886 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4887 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4888 MatCheckPreallocated(mat, 1); 4889 4890 PetscUseTypeMethod(mat, getdiagonal, v); 4891 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4892 PetscFunctionReturn(PETSC_SUCCESS); 4893 } 4894 4895 /*@C 4896 MatGetRowMin - Gets the minimum value (of the real part) of each 4897 row of the matrix 4898 4899 Logically Collective 4900 4901 Input Parameter: 4902 . mat - the matrix 4903 4904 Output Parameters: 4905 + v - the vector for storing the maximums 4906 - idx - the indices of the column found for each row (optional) 4907 4908 Level: intermediate 4909 4910 Note: 4911 The result of this call are the same as if one converted the matrix to dense format 4912 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 4913 4914 This code is only implemented for a couple of matrix formats. 4915 4916 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, 4917 `MatGetRowMax()` 4918 @*/ 4919 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[]) 4920 { 4921 PetscFunctionBegin; 4922 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4923 PetscValidType(mat, 1); 4924 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4925 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4926 4927 if (!mat->cmap->N) { 4928 PetscCall(VecSet(v, PETSC_MAX_REAL)); 4929 if (idx) { 4930 PetscInt i, m = mat->rmap->n; 4931 for (i = 0; i < m; i++) idx[i] = -1; 4932 } 4933 } else { 4934 MatCheckPreallocated(mat, 1); 4935 } 4936 PetscUseTypeMethod(mat, getrowmin, v, idx); 4937 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4938 PetscFunctionReturn(PETSC_SUCCESS); 4939 } 4940 4941 /*@C 4942 MatGetRowMinAbs - Gets the minimum value (in absolute value) of each 4943 row of the matrix 4944 4945 Logically Collective 4946 4947 Input Parameter: 4948 . mat - the matrix 4949 4950 Output Parameters: 4951 + v - the vector for storing the minimums 4952 - idx - the indices of the column found for each row (or `NULL` if not needed) 4953 4954 Level: intermediate 4955 4956 Notes: 4957 if a row is completely empty or has only 0.0 values then the idx[] value for that 4958 row is 0 (the first column). 4959 4960 This code is only implemented for a couple of matrix formats. 4961 4962 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()` 4963 @*/ 4964 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[]) 4965 { 4966 PetscFunctionBegin; 4967 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4968 PetscValidType(mat, 1); 4969 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4970 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4971 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4972 4973 if (!mat->cmap->N) { 4974 PetscCall(VecSet(v, 0.0)); 4975 if (idx) { 4976 PetscInt i, m = mat->rmap->n; 4977 for (i = 0; i < m; i++) idx[i] = -1; 4978 } 4979 } else { 4980 MatCheckPreallocated(mat, 1); 4981 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 4982 PetscUseTypeMethod(mat, getrowminabs, v, idx); 4983 } 4984 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4985 PetscFunctionReturn(PETSC_SUCCESS); 4986 } 4987 4988 /*@C 4989 MatGetRowMax - Gets the maximum value (of the real part) of each 4990 row of the matrix 4991 4992 Logically Collective 4993 4994 Input Parameter: 4995 . mat - the matrix 4996 4997 Output Parameters: 4998 + v - the vector for storing the maximums 4999 - idx - the indices of the column found for each row (optional) 5000 5001 Level: intermediate 5002 5003 Notes: 5004 The result of this call are the same as if one converted the matrix to dense format 5005 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5006 5007 This code is only implemented for a couple of matrix formats. 5008 5009 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5010 @*/ 5011 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[]) 5012 { 5013 PetscFunctionBegin; 5014 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5015 PetscValidType(mat, 1); 5016 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5017 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5018 5019 if (!mat->cmap->N) { 5020 PetscCall(VecSet(v, PETSC_MIN_REAL)); 5021 if (idx) { 5022 PetscInt i, m = mat->rmap->n; 5023 for (i = 0; i < m; i++) idx[i] = -1; 5024 } 5025 } else { 5026 MatCheckPreallocated(mat, 1); 5027 PetscUseTypeMethod(mat, getrowmax, v, idx); 5028 } 5029 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5030 PetscFunctionReturn(PETSC_SUCCESS); 5031 } 5032 5033 /*@C 5034 MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each 5035 row of the matrix 5036 5037 Logically Collective 5038 5039 Input Parameter: 5040 . mat - the matrix 5041 5042 Output Parameters: 5043 + v - the vector for storing the maximums 5044 - idx - the indices of the column found for each row (or `NULL` if not needed) 5045 5046 Level: intermediate 5047 5048 Notes: 5049 if a row is completely empty or has only 0.0 values then the idx[] value for that 5050 row is 0 (the first column). 5051 5052 This code is only implemented for a couple of matrix formats. 5053 5054 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5055 @*/ 5056 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[]) 5057 { 5058 PetscFunctionBegin; 5059 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5060 PetscValidType(mat, 1); 5061 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5062 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5063 5064 if (!mat->cmap->N) { 5065 PetscCall(VecSet(v, 0.0)); 5066 if (idx) { 5067 PetscInt i, m = mat->rmap->n; 5068 for (i = 0; i < m; i++) idx[i] = -1; 5069 } 5070 } else { 5071 MatCheckPreallocated(mat, 1); 5072 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5073 PetscUseTypeMethod(mat, getrowmaxabs, v, idx); 5074 } 5075 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5076 PetscFunctionReturn(PETSC_SUCCESS); 5077 } 5078 5079 /*@ 5080 MatGetRowSum - Gets the sum of each row of the matrix 5081 5082 Logically or Neighborhood Collective 5083 5084 Input Parameter: 5085 . mat - the matrix 5086 5087 Output Parameter: 5088 . v - the vector for storing the sum of rows 5089 5090 Level: intermediate 5091 5092 Notes: 5093 This code is slow since it is not currently specialized for different formats 5094 5095 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()` 5096 @*/ 5097 PetscErrorCode MatGetRowSum(Mat mat, Vec v) 5098 { 5099 Vec ones; 5100 5101 PetscFunctionBegin; 5102 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5103 PetscValidType(mat, 1); 5104 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5105 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5106 MatCheckPreallocated(mat, 1); 5107 PetscCall(MatCreateVecs(mat, &ones, NULL)); 5108 PetscCall(VecSet(ones, 1.)); 5109 PetscCall(MatMult(mat, ones, v)); 5110 PetscCall(VecDestroy(&ones)); 5111 PetscFunctionReturn(PETSC_SUCCESS); 5112 } 5113 5114 /*@ 5115 MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) 5116 when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B) 5117 5118 Collective 5119 5120 Input Parameter: 5121 . mat - the matrix to provide the transpose 5122 5123 Output Parameter: 5124 . 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 5125 5126 Level: advanced 5127 5128 Note: 5129 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 5130 routine allows bypassing that call. 5131 5132 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5133 @*/ 5134 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B) 5135 { 5136 PetscContainer rB = NULL; 5137 MatParentState *rb = NULL; 5138 5139 PetscFunctionBegin; 5140 PetscCall(PetscNew(&rb)); 5141 rb->id = ((PetscObject)mat)->id; 5142 rb->state = 0; 5143 PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate)); 5144 PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB)); 5145 PetscCall(PetscContainerSetPointer(rB, rb)); 5146 PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault)); 5147 PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB)); 5148 PetscCall(PetscObjectDereference((PetscObject)rB)); 5149 PetscFunctionReturn(PETSC_SUCCESS); 5150 } 5151 5152 /*@ 5153 MatTranspose - Computes an in-place or out-of-place transpose of a matrix. 5154 5155 Collective 5156 5157 Input Parameters: 5158 + mat - the matrix to transpose 5159 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5160 5161 Output Parameter: 5162 . B - the transpose 5163 5164 Level: intermediate 5165 5166 Notes: 5167 If you use `MAT_INPLACE_MATRIX` then you must pass in &mat for B 5168 5169 `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 5170 transpose, call `MatTransposeSetPrecursor`(mat,B) before calling this routine. 5171 5172 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. 5173 5174 Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed. 5175 5176 If mat is unchanged from the last call this function returns immediately without recomputing the result 5177 5178 If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()` 5179 5180 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`, 5181 `MatTransposeSymbolic()`, `MatCreateTranspose()` 5182 @*/ 5183 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B) 5184 { 5185 PetscContainer rB = NULL; 5186 MatParentState *rb = NULL; 5187 5188 PetscFunctionBegin; 5189 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5190 PetscValidType(mat, 1); 5191 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5192 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5193 PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first"); 5194 PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX"); 5195 MatCheckPreallocated(mat, 1); 5196 if (reuse == MAT_REUSE_MATRIX) { 5197 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5198 PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor()."); 5199 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5200 PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5201 if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS); 5202 } 5203 5204 PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0)); 5205 if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) { 5206 PetscUseTypeMethod(mat, transpose, reuse, B); 5207 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5208 } 5209 PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0)); 5210 5211 if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B)); 5212 if (reuse != MAT_INPLACE_MATRIX) { 5213 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5214 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5215 rb->state = ((PetscObject)mat)->state; 5216 rb->nonzerostate = mat->nonzerostate; 5217 } 5218 PetscFunctionReturn(PETSC_SUCCESS); 5219 } 5220 5221 /*@ 5222 MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix. 5223 5224 Collective 5225 5226 Input Parameter: 5227 . A - the matrix to transpose 5228 5229 Output Parameter: 5230 . 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 5231 numerical portion. 5232 5233 Level: intermediate 5234 5235 Note: 5236 This is not supported for many matrix types, use `MatTranspose()` in those cases 5237 5238 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5239 @*/ 5240 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B) 5241 { 5242 PetscFunctionBegin; 5243 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5244 PetscValidType(A, 1); 5245 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5246 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5247 PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0)); 5248 PetscUseTypeMethod(A, transposesymbolic, B); 5249 PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0)); 5250 5251 PetscCall(MatTransposeSetPrecursor(A, *B)); 5252 PetscFunctionReturn(PETSC_SUCCESS); 5253 } 5254 5255 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B) 5256 { 5257 PetscContainer rB; 5258 MatParentState *rb; 5259 5260 PetscFunctionBegin; 5261 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5262 PetscValidType(A, 1); 5263 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5264 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5265 PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB)); 5266 PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()"); 5267 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5268 PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5269 PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure"); 5270 PetscFunctionReturn(PETSC_SUCCESS); 5271 } 5272 5273 /*@ 5274 MatIsTranspose - Test whether a matrix is another one's transpose, 5275 or its own, in which case it tests symmetry. 5276 5277 Collective 5278 5279 Input Parameters: 5280 + A - the matrix to test 5281 . B - the matrix to test against, this can equal the first parameter 5282 - tol - tolerance, differences between entries smaller than this are counted as zero 5283 5284 Output Parameter: 5285 . flg - the result 5286 5287 Level: intermediate 5288 5289 Notes: 5290 Only available for `MATAIJ` matrices. 5291 5292 The sequential algorithm has a running time of the order of the number of nonzeros; the parallel 5293 test involves parallel copies of the block-offdiagonal parts of the matrix. 5294 5295 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()` 5296 @*/ 5297 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5298 { 5299 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5300 5301 PetscFunctionBegin; 5302 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5303 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5304 PetscValidBoolPointer(flg, 4); 5305 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f)); 5306 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g)); 5307 *flg = PETSC_FALSE; 5308 if (f && g) { 5309 PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test"); 5310 PetscCall((*f)(A, B, tol, flg)); 5311 } else { 5312 MatType mattype; 5313 5314 PetscCall(MatGetType(f ? B : A, &mattype)); 5315 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype); 5316 } 5317 PetscFunctionReturn(PETSC_SUCCESS); 5318 } 5319 5320 /*@ 5321 MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate. 5322 5323 Collective 5324 5325 Input Parameters: 5326 + mat - the matrix to transpose and complex conjugate 5327 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5328 5329 Output Parameter: 5330 . B - the Hermitian transpose 5331 5332 Level: intermediate 5333 5334 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse` 5335 @*/ 5336 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B) 5337 { 5338 PetscFunctionBegin; 5339 PetscCall(MatTranspose(mat, reuse, B)); 5340 #if defined(PETSC_USE_COMPLEX) 5341 PetscCall(MatConjugate(*B)); 5342 #endif 5343 PetscFunctionReturn(PETSC_SUCCESS); 5344 } 5345 5346 /*@ 5347 MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose, 5348 5349 Collective 5350 5351 Input Parameters: 5352 + A - the matrix to test 5353 . B - the matrix to test against, this can equal the first parameter 5354 - tol - tolerance, differences between entries smaller than this are counted as zero 5355 5356 Output Parameter: 5357 . flg - the result 5358 5359 Level: intermediate 5360 5361 Notes: 5362 Only available for `MATAIJ` matrices. 5363 5364 The sequential algorithm 5365 has a running time of the order of the number of nonzeros; the parallel 5366 test involves parallel copies of the block-offdiagonal parts of the matrix. 5367 5368 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()` 5369 @*/ 5370 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5371 { 5372 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5373 5374 PetscFunctionBegin; 5375 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5376 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5377 PetscValidBoolPointer(flg, 4); 5378 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f)); 5379 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g)); 5380 if (f && g) { 5381 PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test"); 5382 PetscCall((*f)(A, B, tol, flg)); 5383 } 5384 PetscFunctionReturn(PETSC_SUCCESS); 5385 } 5386 5387 /*@ 5388 MatPermute - Creates a new matrix with rows and columns permuted from the 5389 original. 5390 5391 Collective 5392 5393 Input Parameters: 5394 + mat - the matrix to permute 5395 . row - row permutation, each processor supplies only the permutation for its rows 5396 - col - column permutation, each processor supplies only the permutation for its columns 5397 5398 Output Parameter: 5399 . B - the permuted matrix 5400 5401 Level: advanced 5402 5403 Note: 5404 The index sets map from row/col of permuted matrix to row/col of original matrix. 5405 The index sets should be on the same communicator as mat and have the same local sizes. 5406 5407 Developer Note: 5408 If you want to implement `MatPermute()` for a matrix type, and your approach doesn't 5409 exploit the fact that row and col are permutations, consider implementing the 5410 more general `MatCreateSubMatrix()` instead. 5411 5412 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()` 5413 @*/ 5414 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B) 5415 { 5416 PetscFunctionBegin; 5417 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5418 PetscValidType(mat, 1); 5419 PetscValidHeaderSpecific(row, IS_CLASSID, 2); 5420 PetscValidHeaderSpecific(col, IS_CLASSID, 3); 5421 PetscValidPointer(B, 4); 5422 PetscCheckSameComm(mat, 1, row, 2); 5423 if (row != col) PetscCheckSameComm(row, 2, col, 3); 5424 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5425 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5426 PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name); 5427 MatCheckPreallocated(mat, 1); 5428 5429 if (mat->ops->permute) { 5430 PetscUseTypeMethod(mat, permute, row, col, B); 5431 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5432 } else { 5433 PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B)); 5434 } 5435 PetscFunctionReturn(PETSC_SUCCESS); 5436 } 5437 5438 /*@ 5439 MatEqual - Compares two matrices. 5440 5441 Collective 5442 5443 Input Parameters: 5444 + A - the first matrix 5445 - B - the second matrix 5446 5447 Output Parameter: 5448 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise. 5449 5450 Level: intermediate 5451 5452 .seealso: [](ch_matrices), `Mat` 5453 @*/ 5454 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg) 5455 { 5456 PetscFunctionBegin; 5457 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5458 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5459 PetscValidType(A, 1); 5460 PetscValidType(B, 2); 5461 PetscValidBoolPointer(flg, 3); 5462 PetscCheckSameComm(A, 1, B, 2); 5463 MatCheckPreallocated(A, 1); 5464 MatCheckPreallocated(B, 2); 5465 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5466 PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5467 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, 5468 B->cmap->N); 5469 if (A->ops->equal && A->ops->equal == B->ops->equal) { 5470 PetscUseTypeMethod(A, equal, B, flg); 5471 } else { 5472 PetscCall(MatMultEqual(A, B, 10, flg)); 5473 } 5474 PetscFunctionReturn(PETSC_SUCCESS); 5475 } 5476 5477 /*@ 5478 MatDiagonalScale - Scales a matrix on the left and right by diagonal 5479 matrices that are stored as vectors. Either of the two scaling 5480 matrices can be `NULL`. 5481 5482 Collective 5483 5484 Input Parameters: 5485 + mat - the matrix to be scaled 5486 . l - the left scaling vector (or `NULL`) 5487 - r - the right scaling vector (or `NULL`) 5488 5489 Level: intermediate 5490 5491 Note: 5492 `MatDiagonalScale()` computes A = LAR, where 5493 L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector) 5494 The L scales the rows of the matrix, the R scales the columns of the matrix. 5495 5496 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()` 5497 @*/ 5498 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r) 5499 { 5500 PetscFunctionBegin; 5501 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5502 PetscValidType(mat, 1); 5503 if (l) { 5504 PetscValidHeaderSpecific(l, VEC_CLASSID, 2); 5505 PetscCheckSameComm(mat, 1, l, 2); 5506 } 5507 if (r) { 5508 PetscValidHeaderSpecific(r, VEC_CLASSID, 3); 5509 PetscCheckSameComm(mat, 1, r, 3); 5510 } 5511 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5512 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5513 MatCheckPreallocated(mat, 1); 5514 if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS); 5515 5516 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5517 PetscUseTypeMethod(mat, diagonalscale, l, r); 5518 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5519 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5520 if (l != r) mat->symmetric = PETSC_BOOL3_FALSE; 5521 PetscFunctionReturn(PETSC_SUCCESS); 5522 } 5523 5524 /*@ 5525 MatScale - Scales all elements of a matrix by a given number. 5526 5527 Logically Collective 5528 5529 Input Parameters: 5530 + mat - the matrix to be scaled 5531 - a - the scaling value 5532 5533 Level: intermediate 5534 5535 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 5536 @*/ 5537 PetscErrorCode MatScale(Mat mat, PetscScalar a) 5538 { 5539 PetscFunctionBegin; 5540 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5541 PetscValidType(mat, 1); 5542 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5543 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5544 PetscValidLogicalCollectiveScalar(mat, a, 2); 5545 MatCheckPreallocated(mat, 1); 5546 5547 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5548 if (a != (PetscScalar)1.0) { 5549 PetscUseTypeMethod(mat, scale, a); 5550 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5551 } 5552 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5553 PetscFunctionReturn(PETSC_SUCCESS); 5554 } 5555 5556 /*@ 5557 MatNorm - Calculates various norms of a matrix. 5558 5559 Collective 5560 5561 Input Parameters: 5562 + mat - the matrix 5563 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY` 5564 5565 Output Parameter: 5566 . nrm - the resulting norm 5567 5568 Level: intermediate 5569 5570 .seealso: [](ch_matrices), `Mat` 5571 @*/ 5572 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm) 5573 { 5574 PetscFunctionBegin; 5575 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5576 PetscValidType(mat, 1); 5577 PetscValidRealPointer(nrm, 3); 5578 5579 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5580 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5581 MatCheckPreallocated(mat, 1); 5582 5583 PetscUseTypeMethod(mat, norm, type, nrm); 5584 PetscFunctionReturn(PETSC_SUCCESS); 5585 } 5586 5587 /* 5588 This variable is used to prevent counting of MatAssemblyBegin() that 5589 are called from within a MatAssemblyEnd(). 5590 */ 5591 static PetscInt MatAssemblyEnd_InUse = 0; 5592 /*@ 5593 MatAssemblyBegin - Begins assembling the matrix. This routine should 5594 be called after completing all calls to `MatSetValues()`. 5595 5596 Collective 5597 5598 Input Parameters: 5599 + mat - the matrix 5600 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5601 5602 Level: beginner 5603 5604 Notes: 5605 `MatSetValues()` generally caches the values that belong to other MPI ranks. The matrix is ready to 5606 use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called. 5607 5608 Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES` 5609 in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before 5610 using the matrix. 5611 5612 ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the 5613 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 5614 a global collective operation requiring all processes that share the matrix. 5615 5616 Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed 5617 out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros 5618 before `MAT_FINAL_ASSEMBLY` so the space is not compressed out. 5619 5620 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()` 5621 @*/ 5622 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type) 5623 { 5624 PetscFunctionBegin; 5625 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5626 PetscValidType(mat, 1); 5627 MatCheckPreallocated(mat, 1); 5628 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?"); 5629 if (mat->assembled) { 5630 mat->was_assembled = PETSC_TRUE; 5631 mat->assembled = PETSC_FALSE; 5632 } 5633 5634 if (!MatAssemblyEnd_InUse) { 5635 PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0)); 5636 PetscTryTypeMethod(mat, assemblybegin, type); 5637 PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0)); 5638 } else PetscTryTypeMethod(mat, assemblybegin, type); 5639 PetscFunctionReturn(PETSC_SUCCESS); 5640 } 5641 5642 /*@ 5643 MatAssembled - Indicates if a matrix has been assembled and is ready for 5644 use; for example, in matrix-vector product. 5645 5646 Not Collective 5647 5648 Input Parameter: 5649 . mat - the matrix 5650 5651 Output Parameter: 5652 . assembled - `PETSC_TRUE` or `PETSC_FALSE` 5653 5654 Level: advanced 5655 5656 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()` 5657 @*/ 5658 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled) 5659 { 5660 PetscFunctionBegin; 5661 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5662 PetscValidBoolPointer(assembled, 2); 5663 *assembled = mat->assembled; 5664 PetscFunctionReturn(PETSC_SUCCESS); 5665 } 5666 5667 /*@ 5668 MatAssemblyEnd - Completes assembling the matrix. This routine should 5669 be called after `MatAssemblyBegin()`. 5670 5671 Collective 5672 5673 Input Parameters: 5674 + mat - the matrix 5675 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5676 5677 Options Database Keys: 5678 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatEndAssembly()` 5679 . -mat_view ::ascii_info_detail - Prints more detailed info 5680 . -mat_view - Prints matrix in ASCII format 5681 . -mat_view ::ascii_matlab - Prints matrix in Matlab format 5682 . -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 5683 . -display <name> - Sets display name (default is host) 5684 . -draw_pause <sec> - Sets number of seconds to pause after display 5685 . -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See [Using MATLAB with PETSc](ch_matlab)) 5686 . -viewer_socket_machine <machine> - Machine to use for socket 5687 . -viewer_socket_port <port> - Port number to use for socket 5688 - -mat_view binary:filename[:append] - Save matrix to file in binary format 5689 5690 Level: beginner 5691 5692 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()` 5693 @*/ 5694 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type) 5695 { 5696 static PetscInt inassm = 0; 5697 PetscBool flg = PETSC_FALSE; 5698 5699 PetscFunctionBegin; 5700 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5701 PetscValidType(mat, 1); 5702 5703 inassm++; 5704 MatAssemblyEnd_InUse++; 5705 if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */ 5706 PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0)); 5707 PetscTryTypeMethod(mat, assemblyend, type); 5708 PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0)); 5709 } else PetscTryTypeMethod(mat, assemblyend, type); 5710 5711 /* Flush assembly is not a true assembly */ 5712 if (type != MAT_FLUSH_ASSEMBLY) { 5713 if (mat->num_ass) { 5714 if (!mat->symmetry_eternal) { 5715 mat->symmetric = PETSC_BOOL3_UNKNOWN; 5716 mat->hermitian = PETSC_BOOL3_UNKNOWN; 5717 } 5718 if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN; 5719 if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN; 5720 } 5721 mat->num_ass++; 5722 mat->assembled = PETSC_TRUE; 5723 mat->ass_nonzerostate = mat->nonzerostate; 5724 } 5725 5726 mat->insertmode = NOT_SET_VALUES; 5727 MatAssemblyEnd_InUse--; 5728 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5729 if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) { 5730 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 5731 5732 if (mat->checksymmetryonassembly) { 5733 PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg)); 5734 if (flg) { 5735 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5736 } else { 5737 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5738 } 5739 } 5740 if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL)); 5741 } 5742 inassm--; 5743 PetscFunctionReturn(PETSC_SUCCESS); 5744 } 5745 5746 /*@ 5747 MatSetOption - Sets a parameter option for a matrix. Some options 5748 may be specific to certain storage formats. Some options 5749 determine how values will be inserted (or added). Sorted, 5750 row-oriented input will generally assemble the fastest. The default 5751 is row-oriented. 5752 5753 Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption` 5754 5755 Input Parameters: 5756 + mat - the matrix 5757 . option - the option, one of those listed below (and possibly others), 5758 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5759 5760 Options Describing Matrix Structure: 5761 + `MAT_SPD` - symmetric positive definite 5762 . `MAT_SYMMETRIC` - symmetric in terms of both structure and value 5763 . `MAT_HERMITIAN` - transpose is the complex conjugation 5764 . `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure 5765 . `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix 5766 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix 5767 - `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix 5768 5769 These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they 5770 do not need to be computed (usually at a high cost) 5771 5772 Options For Use with `MatSetValues()`: 5773 Insert a logically dense subblock, which can be 5774 . `MAT_ROW_ORIENTED` - row-oriented (default) 5775 5776 These options reflect the data you pass in with `MatSetValues()`; it has 5777 nothing to do with how the data is stored internally in the matrix 5778 data structure. 5779 5780 When (re)assembling a matrix, we can restrict the input for 5781 efficiency/debugging purposes. These options include 5782 + `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow) 5783 . `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated 5784 . `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries 5785 . `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry 5786 . `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly 5787 . `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if 5788 any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves 5789 performance for very large process counts. 5790 - `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset 5791 of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly 5792 functions, instead sending only neighbor messages. 5793 5794 Level: intermediate 5795 5796 Notes: 5797 Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg! 5798 5799 Some options are relevant only for particular matrix types and 5800 are thus ignored by others. Other options are not supported by 5801 certain matrix types and will generate an error message if set. 5802 5803 If using Fortran to compute a matrix, one may need to 5804 use the column-oriented option (or convert to the row-oriented 5805 format). 5806 5807 `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion 5808 that would generate a new entry in the nonzero structure is instead 5809 ignored. Thus, if memory has not already been allocated for this particular 5810 data, then the insertion is ignored. For dense matrices, in which 5811 the entire array is allocated, no entries are ever ignored. 5812 Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction 5813 5814 `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion 5815 that would generate a new entry in the nonzero structure instead produces 5816 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 5817 5818 `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion 5819 that would generate a new entry that has not been preallocated will 5820 instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats 5821 only.) This is a useful flag when debugging matrix memory preallocation. 5822 If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 5823 5824 `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for 5825 other processors should be dropped, rather than stashed. 5826 This is useful if you know that the "owning" processor is also 5827 always generating the correct matrix entries, so that PETSc need 5828 not transfer duplicate entries generated on another processor. 5829 5830 `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the 5831 searches during matrix assembly. When this flag is set, the hash table 5832 is created during the first matrix assembly. This hash table is 5833 used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()` 5834 to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag 5835 should be used with `MAT_USE_HASH_TABLE` flag. This option is currently 5836 supported by `MATMPIBAIJ` format only. 5837 5838 `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries 5839 are kept in the nonzero structure 5840 5841 `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating 5842 a zero location in the matrix 5843 5844 `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types 5845 5846 `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the 5847 zero row routines and thus improves performance for very large process counts. 5848 5849 `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular 5850 part of the matrix (since they should match the upper triangular part). 5851 5852 `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a 5853 single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common 5854 with finite difference schemes with non-periodic boundary conditions. 5855 5856 Developer Note: 5857 `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other 5858 places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRIC` or `MAT_SPD` would need to be changed back 5859 to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had 5860 not changed. 5861 5862 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()` 5863 @*/ 5864 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg) 5865 { 5866 PetscFunctionBegin; 5867 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5868 if (op > 0) { 5869 PetscValidLogicalCollectiveEnum(mat, op, 2); 5870 PetscValidLogicalCollectiveBool(mat, flg, 3); 5871 } 5872 5873 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); 5874 5875 switch (op) { 5876 case MAT_FORCE_DIAGONAL_ENTRIES: 5877 mat->force_diagonals = flg; 5878 PetscFunctionReturn(PETSC_SUCCESS); 5879 case MAT_NO_OFF_PROC_ENTRIES: 5880 mat->nooffprocentries = flg; 5881 PetscFunctionReturn(PETSC_SUCCESS); 5882 case MAT_SUBSET_OFF_PROC_ENTRIES: 5883 mat->assembly_subset = flg; 5884 if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */ 5885 #if !defined(PETSC_HAVE_MPIUNI) 5886 PetscCall(MatStashScatterDestroy_BTS(&mat->stash)); 5887 #endif 5888 mat->stash.first_assembly_done = PETSC_FALSE; 5889 } 5890 PetscFunctionReturn(PETSC_SUCCESS); 5891 case MAT_NO_OFF_PROC_ZERO_ROWS: 5892 mat->nooffproczerorows = flg; 5893 PetscFunctionReturn(PETSC_SUCCESS); 5894 case MAT_SPD: 5895 if (flg) { 5896 mat->spd = PETSC_BOOL3_TRUE; 5897 mat->symmetric = PETSC_BOOL3_TRUE; 5898 mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5899 } else { 5900 mat->spd = PETSC_BOOL3_FALSE; 5901 } 5902 break; 5903 case MAT_SYMMETRIC: 5904 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5905 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5906 #if !defined(PETSC_USE_COMPLEX) 5907 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5908 #endif 5909 break; 5910 case MAT_HERMITIAN: 5911 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5912 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5913 #if !defined(PETSC_USE_COMPLEX) 5914 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5915 #endif 5916 break; 5917 case MAT_STRUCTURALLY_SYMMETRIC: 5918 mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5919 break; 5920 case MAT_SYMMETRY_ETERNAL: 5921 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"); 5922 mat->symmetry_eternal = flg; 5923 if (flg) mat->structural_symmetry_eternal = PETSC_TRUE; 5924 break; 5925 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 5926 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"); 5927 mat->structural_symmetry_eternal = flg; 5928 break; 5929 case MAT_SPD_ETERNAL: 5930 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"); 5931 mat->spd_eternal = flg; 5932 if (flg) { 5933 mat->structural_symmetry_eternal = PETSC_TRUE; 5934 mat->symmetry_eternal = PETSC_TRUE; 5935 } 5936 break; 5937 case MAT_STRUCTURE_ONLY: 5938 mat->structure_only = flg; 5939 break; 5940 case MAT_SORTED_FULL: 5941 mat->sortedfull = flg; 5942 break; 5943 default: 5944 break; 5945 } 5946 PetscTryTypeMethod(mat, setoption, op, flg); 5947 PetscFunctionReturn(PETSC_SUCCESS); 5948 } 5949 5950 /*@ 5951 MatGetOption - Gets a parameter option that has been set for a matrix. 5952 5953 Logically Collective 5954 5955 Input Parameters: 5956 + mat - the matrix 5957 - option - the option, this only responds to certain options, check the code for which ones 5958 5959 Output Parameter: 5960 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5961 5962 Level: intermediate 5963 5964 Notes: 5965 Can only be called after `MatSetSizes()` and `MatSetType()` have been set. 5966 5967 Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or 5968 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 5969 5970 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, 5971 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 5972 @*/ 5973 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg) 5974 { 5975 PetscFunctionBegin; 5976 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5977 PetscValidType(mat, 1); 5978 5979 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); 5980 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()"); 5981 5982 switch (op) { 5983 case MAT_NO_OFF_PROC_ENTRIES: 5984 *flg = mat->nooffprocentries; 5985 break; 5986 case MAT_NO_OFF_PROC_ZERO_ROWS: 5987 *flg = mat->nooffproczerorows; 5988 break; 5989 case MAT_SYMMETRIC: 5990 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()"); 5991 break; 5992 case MAT_HERMITIAN: 5993 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()"); 5994 break; 5995 case MAT_STRUCTURALLY_SYMMETRIC: 5996 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()"); 5997 break; 5998 case MAT_SPD: 5999 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()"); 6000 break; 6001 case MAT_SYMMETRY_ETERNAL: 6002 *flg = mat->symmetry_eternal; 6003 break; 6004 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6005 *flg = mat->symmetry_eternal; 6006 break; 6007 default: 6008 break; 6009 } 6010 PetscFunctionReturn(PETSC_SUCCESS); 6011 } 6012 6013 /*@ 6014 MatZeroEntries - Zeros all entries of a matrix. For sparse matrices 6015 this routine retains the old nonzero structure. 6016 6017 Logically Collective 6018 6019 Input Parameter: 6020 . mat - the matrix 6021 6022 Level: intermediate 6023 6024 Note: 6025 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. 6026 See the Performance chapter of the users manual for information on preallocating matrices. 6027 6028 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()` 6029 @*/ 6030 PetscErrorCode MatZeroEntries(Mat mat) 6031 { 6032 PetscFunctionBegin; 6033 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6034 PetscValidType(mat, 1); 6035 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6036 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"); 6037 MatCheckPreallocated(mat, 1); 6038 6039 PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0)); 6040 PetscUseTypeMethod(mat, zeroentries); 6041 PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0)); 6042 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6043 PetscFunctionReturn(PETSC_SUCCESS); 6044 } 6045 6046 /*@ 6047 MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal) 6048 of a set of rows and columns of a matrix. 6049 6050 Collective 6051 6052 Input Parameters: 6053 + mat - the matrix 6054 . numRows - the number of rows/columns to zero 6055 . rows - the global row indices 6056 . diag - value put in the diagonal of the eliminated rows 6057 . x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call 6058 - b - optional vector of the right hand side, that will be adjusted by provided solution entries 6059 6060 Level: intermediate 6061 6062 Notes: 6063 This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6064 6065 For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`. 6066 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 6067 6068 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6069 Krylov method to take advantage of the known solution on the zeroed rows. 6070 6071 For the parallel case, all processes that share the matrix (i.e., 6072 those in the communicator used for matrix creation) MUST call this 6073 routine, regardless of whether any rows being zeroed are owned by 6074 them. 6075 6076 Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix. 6077 6078 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6079 list only rows local to itself). 6080 6081 The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine. 6082 6083 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6084 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6085 @*/ 6086 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6087 { 6088 PetscFunctionBegin; 6089 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6090 PetscValidType(mat, 1); 6091 if (numRows) PetscValidIntPointer(rows, 3); 6092 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6093 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6094 MatCheckPreallocated(mat, 1); 6095 6096 PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b); 6097 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6098 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6099 PetscFunctionReturn(PETSC_SUCCESS); 6100 } 6101 6102 /*@ 6103 MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal) 6104 of a set of rows and columns of a matrix. 6105 6106 Collective 6107 6108 Input Parameters: 6109 + mat - the matrix 6110 . is - the rows to zero 6111 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6112 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6113 - b - optional vector of right hand side, that will be adjusted by provided solution 6114 6115 Level: intermediate 6116 6117 Note: 6118 See `MatZeroRowsColumns()` for details on how this routine operates. 6119 6120 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6121 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()` 6122 @*/ 6123 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6124 { 6125 PetscInt numRows; 6126 const PetscInt *rows; 6127 6128 PetscFunctionBegin; 6129 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6130 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6131 PetscValidType(mat, 1); 6132 PetscValidType(is, 2); 6133 PetscCall(ISGetLocalSize(is, &numRows)); 6134 PetscCall(ISGetIndices(is, &rows)); 6135 PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b)); 6136 PetscCall(ISRestoreIndices(is, &rows)); 6137 PetscFunctionReturn(PETSC_SUCCESS); 6138 } 6139 6140 /*@ 6141 MatZeroRows - Zeros all entries (except possibly the main diagonal) 6142 of a set of rows of a matrix. 6143 6144 Collective 6145 6146 Input Parameters: 6147 + mat - the matrix 6148 . numRows - the number of rows to zero 6149 . rows - the global row indices 6150 . diag - value put in the diagonal of the zeroed rows 6151 . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call 6152 - b - optional vector of right hand side, that will be adjusted by provided solution entries 6153 6154 Level: intermediate 6155 6156 Notes: 6157 This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6158 6159 For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`. 6160 6161 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6162 Krylov method to take advantage of the known solution on the zeroed rows. 6163 6164 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) 6165 from the matrix. 6166 6167 Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix 6168 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 6169 formats this does not alter the nonzero structure. 6170 6171 If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure 6172 of the matrix is not changed the values are 6173 merely zeroed. 6174 6175 The user can set a value in the diagonal entry (or for the `MATAIJ` format 6176 formats can optionally remove the main diagonal entry from the 6177 nonzero structure as well, by passing 0.0 as the final argument). 6178 6179 For the parallel case, all processes that share the matrix (i.e., 6180 those in the communicator used for matrix creation) MUST call this 6181 routine, regardless of whether any rows being zeroed are owned by 6182 them. 6183 6184 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6185 list only rows local to itself). 6186 6187 You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it 6188 owns that are to be zeroed. This saves a global synchronization in the implementation. 6189 6190 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6191 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE` 6192 @*/ 6193 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6194 { 6195 PetscFunctionBegin; 6196 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6197 PetscValidType(mat, 1); 6198 if (numRows) PetscValidIntPointer(rows, 3); 6199 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6200 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6201 MatCheckPreallocated(mat, 1); 6202 6203 PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b); 6204 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6205 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6206 PetscFunctionReturn(PETSC_SUCCESS); 6207 } 6208 6209 /*@ 6210 MatZeroRowsIS - Zeros all entries (except possibly the main diagonal) 6211 of a set of rows of a matrix. 6212 6213 Collective 6214 6215 Input Parameters: 6216 + mat - the matrix 6217 . is - index set of rows to remove (if `NULL` then no row is removed) 6218 . diag - value put in all diagonals of eliminated rows 6219 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6220 - b - optional vector of right hand side, that will be adjusted by provided solution 6221 6222 Level: intermediate 6223 6224 Note: 6225 See `MatZeroRows()` for details on how this routine operates. 6226 6227 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6228 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6229 @*/ 6230 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6231 { 6232 PetscInt numRows = 0; 6233 const PetscInt *rows = NULL; 6234 6235 PetscFunctionBegin; 6236 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6237 PetscValidType(mat, 1); 6238 if (is) { 6239 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6240 PetscCall(ISGetLocalSize(is, &numRows)); 6241 PetscCall(ISGetIndices(is, &rows)); 6242 } 6243 PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b)); 6244 if (is) PetscCall(ISRestoreIndices(is, &rows)); 6245 PetscFunctionReturn(PETSC_SUCCESS); 6246 } 6247 6248 /*@ 6249 MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal) 6250 of a set of rows of a matrix. These rows must be local to the process. 6251 6252 Collective 6253 6254 Input Parameters: 6255 + mat - the matrix 6256 . numRows - the number of rows to remove 6257 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6258 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6259 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6260 - b - optional vector of right hand side, that will be adjusted by provided solution 6261 6262 Level: intermediate 6263 6264 Notes: 6265 See `MatZeroRows()` for details on how this routine operates. 6266 6267 The grid coordinates are across the entire grid, not just the local portion 6268 6269 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6270 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6271 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6272 `DM_BOUNDARY_PERIODIC` boundary type. 6273 6274 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 6275 a single value per point) you can skip filling those indices. 6276 6277 Fortran Note: 6278 `idxm` and `idxn` should be declared as 6279 $ MatStencil idxm(4, m) 6280 and the values inserted using 6281 .vb 6282 idxm(MatStencil_i, 1) = i 6283 idxm(MatStencil_j, 1) = j 6284 idxm(MatStencil_k, 1) = k 6285 idxm(MatStencil_c, 1) = c 6286 etc 6287 .ve 6288 6289 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6290 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6291 @*/ 6292 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6293 { 6294 PetscInt dim = mat->stencil.dim; 6295 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6296 PetscInt *dims = mat->stencil.dims + 1; 6297 PetscInt *starts = mat->stencil.starts; 6298 PetscInt *dxm = (PetscInt *)rows; 6299 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6300 6301 PetscFunctionBegin; 6302 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6303 PetscValidType(mat, 1); 6304 if (numRows) PetscValidPointer(rows, 3); 6305 6306 PetscCall(PetscMalloc1(numRows, &jdxm)); 6307 for (i = 0; i < numRows; ++i) { 6308 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6309 for (j = 0; j < 3 - sdim; ++j) dxm++; 6310 /* Local index in X dir */ 6311 tmp = *dxm++ - starts[0]; 6312 /* Loop over remaining dimensions */ 6313 for (j = 0; j < dim - 1; ++j) { 6314 /* If nonlocal, set index to be negative */ 6315 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6316 /* Update local index */ 6317 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6318 } 6319 /* Skip component slot if necessary */ 6320 if (mat->stencil.noc) dxm++; 6321 /* Local row number */ 6322 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6323 } 6324 PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b)); 6325 PetscCall(PetscFree(jdxm)); 6326 PetscFunctionReturn(PETSC_SUCCESS); 6327 } 6328 6329 /*@ 6330 MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal) 6331 of a set of rows and columns of a matrix. 6332 6333 Collective 6334 6335 Input Parameters: 6336 + mat - the matrix 6337 . numRows - the number of rows/columns to remove 6338 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6339 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6340 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6341 - b - optional vector of right hand side, that will be adjusted by provided solution 6342 6343 Level: intermediate 6344 6345 Notes: 6346 See `MatZeroRowsColumns()` for details on how this routine operates. 6347 6348 The grid coordinates are across the entire grid, not just the local portion 6349 6350 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6351 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6352 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6353 `DM_BOUNDARY_PERIODIC` boundary type. 6354 6355 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 6356 a single value per point) you can skip filling those indices. 6357 6358 Fortran Note: 6359 `idxm` and `idxn` should be declared as 6360 $ MatStencil idxm(4, m) 6361 and the values inserted using 6362 .vb 6363 idxm(MatStencil_i, 1) = i 6364 idxm(MatStencil_j, 1) = j 6365 idxm(MatStencil_k, 1) = k 6366 idxm(MatStencil_c, 1) = c 6367 etc 6368 .ve 6369 6370 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6371 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()` 6372 @*/ 6373 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6374 { 6375 PetscInt dim = mat->stencil.dim; 6376 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6377 PetscInt *dims = mat->stencil.dims + 1; 6378 PetscInt *starts = mat->stencil.starts; 6379 PetscInt *dxm = (PetscInt *)rows; 6380 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6381 6382 PetscFunctionBegin; 6383 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6384 PetscValidType(mat, 1); 6385 if (numRows) PetscValidPointer(rows, 3); 6386 6387 PetscCall(PetscMalloc1(numRows, &jdxm)); 6388 for (i = 0; i < numRows; ++i) { 6389 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6390 for (j = 0; j < 3 - sdim; ++j) dxm++; 6391 /* Local index in X dir */ 6392 tmp = *dxm++ - starts[0]; 6393 /* Loop over remaining dimensions */ 6394 for (j = 0; j < dim - 1; ++j) { 6395 /* If nonlocal, set index to be negative */ 6396 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6397 /* Update local index */ 6398 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6399 } 6400 /* Skip component slot if necessary */ 6401 if (mat->stencil.noc) dxm++; 6402 /* Local row number */ 6403 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6404 } 6405 PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b)); 6406 PetscCall(PetscFree(jdxm)); 6407 PetscFunctionReturn(PETSC_SUCCESS); 6408 } 6409 6410 /*@C 6411 MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal) 6412 of a set of rows of a matrix; using local numbering of rows. 6413 6414 Collective 6415 6416 Input Parameters: 6417 + mat - the matrix 6418 . numRows - the number of rows to remove 6419 . rows - the local row indices 6420 . diag - value put in all diagonals of eliminated rows 6421 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6422 - b - optional vector of right hand side, that will be adjusted by provided solution 6423 6424 Level: intermediate 6425 6426 Notes: 6427 Before calling `MatZeroRowsLocal()`, the user must first set the 6428 local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`. 6429 6430 See `MatZeroRows()` for details on how this routine operates. 6431 6432 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`, 6433 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6434 @*/ 6435 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6436 { 6437 PetscFunctionBegin; 6438 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6439 PetscValidType(mat, 1); 6440 if (numRows) PetscValidIntPointer(rows, 3); 6441 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6442 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6443 MatCheckPreallocated(mat, 1); 6444 6445 if (mat->ops->zerorowslocal) { 6446 PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b); 6447 } else { 6448 IS is, newis; 6449 const PetscInt *newRows; 6450 6451 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6452 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6453 PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis)); 6454 PetscCall(ISGetIndices(newis, &newRows)); 6455 PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b); 6456 PetscCall(ISRestoreIndices(newis, &newRows)); 6457 PetscCall(ISDestroy(&newis)); 6458 PetscCall(ISDestroy(&is)); 6459 } 6460 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6461 PetscFunctionReturn(PETSC_SUCCESS); 6462 } 6463 6464 /*@ 6465 MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal) 6466 of a set of rows of a matrix; using local numbering of rows. 6467 6468 Collective 6469 6470 Input Parameters: 6471 + mat - the matrix 6472 . is - index set of rows to remove 6473 . diag - value put in all diagonals of eliminated rows 6474 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6475 - b - optional vector of right hand side, that will be adjusted by provided solution 6476 6477 Level: intermediate 6478 6479 Notes: 6480 Before calling `MatZeroRowsLocalIS()`, the user must first set the 6481 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6482 6483 See `MatZeroRows()` for details on how this routine operates. 6484 6485 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6486 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6487 @*/ 6488 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6489 { 6490 PetscInt numRows; 6491 const PetscInt *rows; 6492 6493 PetscFunctionBegin; 6494 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6495 PetscValidType(mat, 1); 6496 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6497 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6498 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6499 MatCheckPreallocated(mat, 1); 6500 6501 PetscCall(ISGetLocalSize(is, &numRows)); 6502 PetscCall(ISGetIndices(is, &rows)); 6503 PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b)); 6504 PetscCall(ISRestoreIndices(is, &rows)); 6505 PetscFunctionReturn(PETSC_SUCCESS); 6506 } 6507 6508 /*@ 6509 MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal) 6510 of a set of rows and columns of a matrix; using local numbering of rows. 6511 6512 Collective 6513 6514 Input Parameters: 6515 + mat - the matrix 6516 . numRows - the number of rows to remove 6517 . rows - the global row indices 6518 . diag - value put in all diagonals of eliminated rows 6519 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6520 - b - optional vector of right hand side, that will be adjusted by provided solution 6521 6522 Level: intermediate 6523 6524 Notes: 6525 Before calling `MatZeroRowsColumnsLocal()`, the user must first set the 6526 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6527 6528 See `MatZeroRowsColumns()` for details on how this routine operates. 6529 6530 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6531 `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6532 @*/ 6533 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6534 { 6535 IS is, newis; 6536 const PetscInt *newRows; 6537 6538 PetscFunctionBegin; 6539 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6540 PetscValidType(mat, 1); 6541 if (numRows) PetscValidIntPointer(rows, 3); 6542 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6543 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6544 MatCheckPreallocated(mat, 1); 6545 6546 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6547 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6548 PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis)); 6549 PetscCall(ISGetIndices(newis, &newRows)); 6550 PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b); 6551 PetscCall(ISRestoreIndices(newis, &newRows)); 6552 PetscCall(ISDestroy(&newis)); 6553 PetscCall(ISDestroy(&is)); 6554 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6555 PetscFunctionReturn(PETSC_SUCCESS); 6556 } 6557 6558 /*@ 6559 MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal) 6560 of a set of rows and columns of a matrix; using local numbering of rows. 6561 6562 Collective 6563 6564 Input Parameters: 6565 + mat - the matrix 6566 . is - index set of rows to remove 6567 . diag - value put in all diagonals of eliminated rows 6568 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6569 - b - optional vector of right hand side, that will be adjusted by provided solution 6570 6571 Level: intermediate 6572 6573 Notes: 6574 Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the 6575 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6576 6577 See `MatZeroRowsColumns()` for details on how this routine operates. 6578 6579 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6580 `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6581 @*/ 6582 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6583 { 6584 PetscInt numRows; 6585 const PetscInt *rows; 6586 6587 PetscFunctionBegin; 6588 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6589 PetscValidType(mat, 1); 6590 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6591 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6592 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6593 MatCheckPreallocated(mat, 1); 6594 6595 PetscCall(ISGetLocalSize(is, &numRows)); 6596 PetscCall(ISGetIndices(is, &rows)); 6597 PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b)); 6598 PetscCall(ISRestoreIndices(is, &rows)); 6599 PetscFunctionReturn(PETSC_SUCCESS); 6600 } 6601 6602 /*@C 6603 MatGetSize - Returns the numbers of rows and columns in a matrix. 6604 6605 Not Collective 6606 6607 Input Parameter: 6608 . mat - the matrix 6609 6610 Output Parameters: 6611 + m - the number of global rows 6612 - n - the number of global columns 6613 6614 Level: beginner 6615 6616 Note: 6617 Both output parameters can be `NULL` on input. 6618 6619 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()` 6620 @*/ 6621 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n) 6622 { 6623 PetscFunctionBegin; 6624 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6625 if (m) *m = mat->rmap->N; 6626 if (n) *n = mat->cmap->N; 6627 PetscFunctionReturn(PETSC_SUCCESS); 6628 } 6629 6630 /*@C 6631 MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns 6632 of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`. 6633 6634 Not Collective 6635 6636 Input Parameter: 6637 . mat - the matrix 6638 6639 Output Parameters: 6640 + m - the number of local rows, use `NULL` to not obtain this value 6641 - n - the number of local columns, use `NULL` to not obtain this value 6642 6643 Level: beginner 6644 6645 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()` 6646 @*/ 6647 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n) 6648 { 6649 PetscFunctionBegin; 6650 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6651 if (m) PetscValidIntPointer(m, 2); 6652 if (n) PetscValidIntPointer(n, 3); 6653 if (m) *m = mat->rmap->n; 6654 if (n) *n = mat->cmap->n; 6655 PetscFunctionReturn(PETSC_SUCCESS); 6656 } 6657 6658 /*@C 6659 MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by 6660 this processor. (The columns of the "diagonal block" for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts. 6661 6662 Not Collective, unless matrix has not been allocated, then collective 6663 6664 Input Parameter: 6665 . mat - the matrix 6666 6667 Output Parameters: 6668 + m - the global index of the first local column, use `NULL` to not obtain this value 6669 - n - one more than the global index of the last local column, use `NULL` to not obtain this value 6670 6671 Level: developer 6672 6673 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout` 6674 @*/ 6675 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n) 6676 { 6677 PetscFunctionBegin; 6678 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6679 PetscValidType(mat, 1); 6680 if (m) PetscValidIntPointer(m, 2); 6681 if (n) PetscValidIntPointer(n, 3); 6682 MatCheckPreallocated(mat, 1); 6683 if (m) *m = mat->cmap->rstart; 6684 if (n) *n = mat->cmap->rend; 6685 PetscFunctionReturn(PETSC_SUCCESS); 6686 } 6687 6688 /*@C 6689 MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6690 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 6691 vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts 6692 6693 Not Collective 6694 6695 Input Parameter: 6696 . mat - the matrix 6697 6698 Output Parameters: 6699 + m - the global index of the first local row, use `NULL` to not obtain this value 6700 - n - one more than the global index of the last local row, use `NULL` to not obtain this value 6701 6702 Level: beginner 6703 6704 Note: 6705 This function requires that the matrix be preallocated. If you have not preallocated, consider using 6706 `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N) 6707 and then `MPI_Scan()` to calculate prefix sums of the local sizes. 6708 6709 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, 6710 `PetscLayout` 6711 @*/ 6712 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n) 6713 { 6714 PetscFunctionBegin; 6715 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6716 PetscValidType(mat, 1); 6717 if (m) PetscValidIntPointer(m, 2); 6718 if (n) PetscValidIntPointer(n, 3); 6719 MatCheckPreallocated(mat, 1); 6720 if (m) *m = mat->rmap->rstart; 6721 if (n) *n = mat->rmap->rend; 6722 PetscFunctionReturn(PETSC_SUCCESS); 6723 } 6724 6725 /*@C 6726 MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6727 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 6728 vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts 6729 6730 Not Collective, unless matrix has not been allocated 6731 6732 Input Parameter: 6733 . mat - the matrix 6734 6735 Output Parameter: 6736 . ranges - start of each processors portion plus one more than the total length at the end 6737 6738 Level: beginner 6739 6740 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout` 6741 @*/ 6742 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges) 6743 { 6744 PetscFunctionBegin; 6745 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6746 PetscValidType(mat, 1); 6747 MatCheckPreallocated(mat, 1); 6748 PetscCall(PetscLayoutGetRanges(mat->rmap, ranges)); 6749 PetscFunctionReturn(PETSC_SUCCESS); 6750 } 6751 6752 /*@C 6753 MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by 6754 each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts. 6755 6756 Not Collective, unless matrix has not been allocated 6757 6758 Input Parameter: 6759 . mat - the matrix 6760 6761 Output Parameter: 6762 . ranges - start of each processors portion plus one more then the total length at the end 6763 6764 Level: beginner 6765 6766 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()` 6767 @*/ 6768 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges) 6769 { 6770 PetscFunctionBegin; 6771 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6772 PetscValidType(mat, 1); 6773 MatCheckPreallocated(mat, 1); 6774 PetscCall(PetscLayoutGetRanges(mat->cmap, ranges)); 6775 PetscFunctionReturn(PETSC_SUCCESS); 6776 } 6777 6778 /*@C 6779 MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this 6780 corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership 6781 is more complicated. See :any:`<sec_matlayout>` for details on matrix layouts. 6782 6783 Not Collective 6784 6785 Input Parameter: 6786 . A - matrix 6787 6788 Output Parameters: 6789 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value 6790 - cols - columns in which this process owns elements, use `NULL` to not obtain this value 6791 6792 Level: intermediate 6793 6794 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK`` 6795 @*/ 6796 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols) 6797 { 6798 PetscErrorCode (*f)(Mat, IS *, IS *); 6799 6800 PetscFunctionBegin; 6801 MatCheckPreallocated(A, 1); 6802 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f)); 6803 if (f) { 6804 PetscCall((*f)(A, rows, cols)); 6805 } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */ 6806 if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows)); 6807 if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols)); 6808 } 6809 PetscFunctionReturn(PETSC_SUCCESS); 6810 } 6811 6812 /*@C 6813 MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()` 6814 Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()` 6815 to complete the factorization. 6816 6817 Collective 6818 6819 Input Parameters: 6820 + fact - the factorized matrix obtained with `MatGetFactor()` 6821 . mat - the matrix 6822 . row - row permutation 6823 . col - column permutation 6824 - info - structure containing 6825 .vb 6826 levels - number of levels of fill. 6827 expected fill - as ratio of original fill. 6828 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 6829 missing diagonal entries) 6830 .ve 6831 6832 Level: developer 6833 6834 Notes: 6835 See [Matrix Factorization](sec_matfactor) for additional information. 6836 6837 Most users should employ the `KSP` interface for linear solvers 6838 instead of working directly with matrix algebra routines such as this. 6839 See, e.g., `KSPCreate()`. 6840 6841 Uses the definition of level of fill as in Y. Saad, 2003 6842 6843 Developer Note: 6844 The Fortran interface is not autogenerated as the 6845 interface definition cannot be generated correctly [due to `MatFactorInfo`] 6846 6847 References: 6848 . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003 6849 6850 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 6851 `MatGetOrdering()`, `MatFactorInfo` 6852 @*/ 6853 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 6854 { 6855 PetscFunctionBegin; 6856 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 6857 PetscValidType(mat, 2); 6858 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 6859 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 6860 PetscValidPointer(info, 5); 6861 PetscValidPointer(fact, 1); 6862 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels); 6863 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 6864 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6865 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6866 MatCheckPreallocated(mat, 2); 6867 6868 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0)); 6869 PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info); 6870 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0)); 6871 PetscFunctionReturn(PETSC_SUCCESS); 6872 } 6873 6874 /*@C 6875 MatICCFactorSymbolic - Performs symbolic incomplete 6876 Cholesky factorization for a symmetric matrix. Use 6877 `MatCholeskyFactorNumeric()` to complete the factorization. 6878 6879 Collective 6880 6881 Input Parameters: 6882 + fact - the factorized matrix obtained with `MatGetFactor()` 6883 . mat - the matrix to be factored 6884 . perm - row and column permutation 6885 - info - structure containing 6886 .vb 6887 levels - number of levels of fill. 6888 expected fill - as ratio of original fill. 6889 .ve 6890 6891 Level: developer 6892 6893 Notes: 6894 Most users should employ the `KSP` interface for linear solvers 6895 instead of working directly with matrix algebra routines such as this. 6896 See, e.g., `KSPCreate()`. 6897 6898 This uses the definition of level of fill as in Y. Saad, 2003 6899 6900 Developer Note: 6901 The Fortran interface is not autogenerated as the 6902 interface definition cannot be generated correctly [due to `MatFactorInfo`] 6903 6904 References: 6905 . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003 6906 6907 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 6908 @*/ 6909 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 6910 { 6911 PetscFunctionBegin; 6912 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 6913 PetscValidType(mat, 2); 6914 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 6915 PetscValidPointer(info, 4); 6916 PetscValidPointer(fact, 1); 6917 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6918 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels); 6919 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 6920 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6921 MatCheckPreallocated(mat, 2); 6922 6923 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 6924 PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info); 6925 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 6926 PetscFunctionReturn(PETSC_SUCCESS); 6927 } 6928 6929 /*@C 6930 MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat 6931 points to an array of valid matrices, they may be reused to store the new 6932 submatrices. 6933 6934 Collective 6935 6936 Input Parameters: 6937 + mat - the matrix 6938 . n - the number of submatrixes to be extracted (on this processor, may be zero) 6939 . irow - index set of rows to extract 6940 . icol - index set of columns to extract 6941 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 6942 6943 Output Parameter: 6944 . submat - the array of submatrices 6945 6946 Level: advanced 6947 6948 Notes: 6949 `MatCreateSubMatrices()` can extract ONLY sequential submatrices 6950 (from both sequential and parallel matrices). Use `MatCreateSubMatrix()` 6951 to extract a parallel submatrix. 6952 6953 Some matrix types place restrictions on the row and column 6954 indices, such as that they be sorted or that they be equal to each other. 6955 6956 The index sets may not have duplicate entries. 6957 6958 When extracting submatrices from a parallel matrix, each processor can 6959 form a different submatrix by setting the rows and columns of its 6960 individual index sets according to the local submatrix desired. 6961 6962 When finished using the submatrices, the user should destroy 6963 them with `MatDestroySubMatrices()`. 6964 6965 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 6966 original matrix has not changed from that last call to `MatCreateSubMatrices()`. 6967 6968 This routine creates the matrices in submat; you should NOT create them before 6969 calling it. It also allocates the array of matrix pointers submat. 6970 6971 For `MATBAIJ` matrices the index sets must respect the block structure, that is if they 6972 request one row/column in a block, they must request all rows/columns that are in 6973 that block. For example, if the block size is 2 you cannot request just row 0 and 6974 column 0. 6975 6976 Fortran Note: 6977 The Fortran interface is slightly different from that given below; it 6978 requires one to pass in as `submat` a `Mat` (integer) array of size at least n+1. 6979 6980 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 6981 @*/ 6982 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 6983 { 6984 PetscInt i; 6985 PetscBool eq; 6986 6987 PetscFunctionBegin; 6988 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6989 PetscValidType(mat, 1); 6990 if (n) { 6991 PetscValidPointer(irow, 3); 6992 for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3); 6993 PetscValidPointer(icol, 4); 6994 for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4); 6995 } 6996 PetscValidPointer(submat, 6); 6997 if (n && scall == MAT_REUSE_MATRIX) { 6998 PetscValidPointer(*submat, 6); 6999 for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6); 7000 } 7001 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7002 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7003 MatCheckPreallocated(mat, 1); 7004 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7005 PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat); 7006 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7007 for (i = 0; i < n; i++) { 7008 (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */ 7009 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7010 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7011 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 7012 if (mat->boundtocpu && mat->bindingpropagates) { 7013 PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE)); 7014 PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE)); 7015 } 7016 #endif 7017 } 7018 PetscFunctionReturn(PETSC_SUCCESS); 7019 } 7020 7021 /*@C 7022 MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms). 7023 7024 Collective 7025 7026 Input Parameters: 7027 + mat - the matrix 7028 . n - the number of submatrixes to be extracted 7029 . irow - index set of rows to extract 7030 . icol - index set of columns to extract 7031 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7032 7033 Output Parameter: 7034 . submat - the array of submatrices 7035 7036 Level: advanced 7037 7038 Note: 7039 This is used by `PCGASM` 7040 7041 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7042 @*/ 7043 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7044 { 7045 PetscInt i; 7046 PetscBool eq; 7047 7048 PetscFunctionBegin; 7049 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7050 PetscValidType(mat, 1); 7051 if (n) { 7052 PetscValidPointer(irow, 3); 7053 PetscValidHeaderSpecific(*irow, IS_CLASSID, 3); 7054 PetscValidPointer(icol, 4); 7055 PetscValidHeaderSpecific(*icol, IS_CLASSID, 4); 7056 } 7057 PetscValidPointer(submat, 6); 7058 if (n && scall == MAT_REUSE_MATRIX) { 7059 PetscValidPointer(*submat, 6); 7060 PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6); 7061 } 7062 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7063 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7064 MatCheckPreallocated(mat, 1); 7065 7066 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7067 PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat); 7068 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7069 for (i = 0; i < n; i++) { 7070 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7071 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7072 } 7073 PetscFunctionReturn(PETSC_SUCCESS); 7074 } 7075 7076 /*@C 7077 MatDestroyMatrices - Destroys an array of matrices. 7078 7079 Collective 7080 7081 Input Parameters: 7082 + n - the number of local matrices 7083 - mat - the matrices (this is a pointer to the array of matrices) 7084 7085 Level: advanced 7086 7087 Note: 7088 Frees not only the matrices, but also the array that contains the matrices 7089 7090 Fortran Note: 7091 This does not free the array. 7092 7093 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()` 7094 @*/ 7095 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[]) 7096 { 7097 PetscInt i; 7098 7099 PetscFunctionBegin; 7100 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7101 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7102 PetscValidPointer(mat, 2); 7103 7104 for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i])); 7105 7106 /* memory is allocated even if n = 0 */ 7107 PetscCall(PetscFree(*mat)); 7108 PetscFunctionReturn(PETSC_SUCCESS); 7109 } 7110 7111 /*@C 7112 MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`. 7113 7114 Collective 7115 7116 Input Parameters: 7117 + n - the number of local matrices 7118 - mat - the matrices (this is a pointer to the array of matrices, just to match the calling 7119 sequence of `MatCreateSubMatrices()`) 7120 7121 Level: advanced 7122 7123 Note: 7124 Frees not only the matrices, but also the array that contains the matrices 7125 7126 Fortran Note: 7127 This does not free the array. 7128 7129 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7130 @*/ 7131 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[]) 7132 { 7133 Mat mat0; 7134 7135 PetscFunctionBegin; 7136 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7137 /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */ 7138 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7139 PetscValidPointer(mat, 2); 7140 7141 mat0 = (*mat)[0]; 7142 if (mat0 && mat0->ops->destroysubmatrices) { 7143 PetscCall((*mat0->ops->destroysubmatrices)(n, mat)); 7144 } else { 7145 PetscCall(MatDestroyMatrices(n, mat)); 7146 } 7147 PetscFunctionReturn(PETSC_SUCCESS); 7148 } 7149 7150 /*@C 7151 MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process 7152 7153 Collective 7154 7155 Input Parameter: 7156 . mat - the matrix 7157 7158 Output Parameter: 7159 . matstruct - the sequential matrix with the nonzero structure of mat 7160 7161 Level: developer 7162 7163 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7164 @*/ 7165 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct) 7166 { 7167 PetscFunctionBegin; 7168 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7169 PetscValidPointer(matstruct, 2); 7170 7171 PetscValidType(mat, 1); 7172 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7173 MatCheckPreallocated(mat, 1); 7174 7175 PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7176 PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct); 7177 PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7178 PetscFunctionReturn(PETSC_SUCCESS); 7179 } 7180 7181 /*@C 7182 MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`. 7183 7184 Collective 7185 7186 Input Parameter: 7187 . mat - the matrix (this is a pointer to the array of matrices, just to match the calling 7188 sequence of `MatGetSeqNonzeroStructure()`) 7189 7190 Level: advanced 7191 7192 Note: 7193 Frees not only the matrices, but also the array that contains the matrices 7194 7195 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()` 7196 @*/ 7197 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat) 7198 { 7199 PetscFunctionBegin; 7200 PetscValidPointer(mat, 1); 7201 PetscCall(MatDestroy(mat)); 7202 PetscFunctionReturn(PETSC_SUCCESS); 7203 } 7204 7205 /*@ 7206 MatIncreaseOverlap - Given a set of submatrices indicated by index sets, 7207 replaces the index sets by larger ones that represent submatrices with 7208 additional overlap. 7209 7210 Collective 7211 7212 Input Parameters: 7213 + mat - the matrix 7214 . n - the number of index sets 7215 . is - the array of index sets (these index sets will changed during the call) 7216 - ov - the additional overlap requested 7217 7218 Options Database Key: 7219 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7220 7221 Level: developer 7222 7223 Note: 7224 The computed overlap preserves the matrix block sizes when the blocks are square. 7225 That is: if a matrix nonzero for a given block would increase the overlap all columns associated with 7226 that block are included in the overlap regardless of whether each specific column would increase the overlap. 7227 7228 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()` 7229 @*/ 7230 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov) 7231 { 7232 PetscInt i, bs, cbs; 7233 7234 PetscFunctionBegin; 7235 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7236 PetscValidType(mat, 1); 7237 PetscValidLogicalCollectiveInt(mat, n, 2); 7238 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7239 if (n) { 7240 PetscValidPointer(is, 3); 7241 for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3); 7242 } 7243 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7244 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7245 MatCheckPreallocated(mat, 1); 7246 7247 if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS); 7248 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7249 PetscUseTypeMethod(mat, increaseoverlap, n, is, ov); 7250 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7251 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 7252 if (bs == cbs) { 7253 for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs)); 7254 } 7255 PetscFunctionReturn(PETSC_SUCCESS); 7256 } 7257 7258 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt); 7259 7260 /*@ 7261 MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across 7262 a sub communicator, replaces the index sets by larger ones that represent submatrices with 7263 additional overlap. 7264 7265 Collective 7266 7267 Input Parameters: 7268 + mat - the matrix 7269 . n - the number of index sets 7270 . is - the array of index sets (these index sets will changed during the call) 7271 - ov - the additional overlap requested 7272 7273 ` Options Database Key: 7274 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7275 7276 Level: developer 7277 7278 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()` 7279 @*/ 7280 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov) 7281 { 7282 PetscInt i; 7283 7284 PetscFunctionBegin; 7285 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7286 PetscValidType(mat, 1); 7287 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7288 if (n) { 7289 PetscValidPointer(is, 3); 7290 PetscValidHeaderSpecific(*is, IS_CLASSID, 3); 7291 } 7292 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7293 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7294 MatCheckPreallocated(mat, 1); 7295 if (!ov) PetscFunctionReturn(PETSC_SUCCESS); 7296 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7297 for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov)); 7298 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7299 PetscFunctionReturn(PETSC_SUCCESS); 7300 } 7301 7302 /*@ 7303 MatGetBlockSize - Returns the matrix block size. 7304 7305 Not Collective 7306 7307 Input Parameter: 7308 . mat - the matrix 7309 7310 Output Parameter: 7311 . bs - block size 7312 7313 Level: intermediate 7314 7315 Notes: 7316 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7317 7318 If the block size has not been set yet this routine returns 1. 7319 7320 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()` 7321 @*/ 7322 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs) 7323 { 7324 PetscFunctionBegin; 7325 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7326 PetscValidIntPointer(bs, 2); 7327 *bs = PetscAbs(mat->rmap->bs); 7328 PetscFunctionReturn(PETSC_SUCCESS); 7329 } 7330 7331 /*@ 7332 MatGetBlockSizes - Returns the matrix block row and column sizes. 7333 7334 Not Collective 7335 7336 Input Parameter: 7337 . mat - the matrix 7338 7339 Output Parameters: 7340 + rbs - row block size 7341 - cbs - column block size 7342 7343 Level: intermediate 7344 7345 Notes: 7346 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7347 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7348 7349 If a block size has not been set yet this routine returns 1. 7350 7351 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()` 7352 @*/ 7353 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs) 7354 { 7355 PetscFunctionBegin; 7356 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7357 if (rbs) PetscValidIntPointer(rbs, 2); 7358 if (cbs) PetscValidIntPointer(cbs, 3); 7359 if (rbs) *rbs = PetscAbs(mat->rmap->bs); 7360 if (cbs) *cbs = PetscAbs(mat->cmap->bs); 7361 PetscFunctionReturn(PETSC_SUCCESS); 7362 } 7363 7364 /*@ 7365 MatSetBlockSize - Sets the matrix block size. 7366 7367 Logically Collective 7368 7369 Input Parameters: 7370 + mat - the matrix 7371 - bs - block size 7372 7373 Level: intermediate 7374 7375 Notes: 7376 Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix. 7377 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7378 7379 For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size 7380 is compatible with the matrix local sizes. 7381 7382 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()` 7383 @*/ 7384 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs) 7385 { 7386 PetscFunctionBegin; 7387 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7388 PetscValidLogicalCollectiveInt(mat, bs, 2); 7389 PetscCall(MatSetBlockSizes(mat, bs, bs)); 7390 PetscFunctionReturn(PETSC_SUCCESS); 7391 } 7392 7393 typedef struct { 7394 PetscInt n; 7395 IS *is; 7396 Mat *mat; 7397 PetscObjectState nonzerostate; 7398 Mat C; 7399 } EnvelopeData; 7400 7401 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata) 7402 { 7403 for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i])); 7404 PetscCall(PetscFree(edata->is)); 7405 PetscCall(PetscFree(edata)); 7406 return PETSC_SUCCESS; 7407 } 7408 7409 /* 7410 MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores 7411 the sizes of these blocks in the matrix. An individual block may lie over several processes. 7412 7413 Collective 7414 7415 Input Parameter: 7416 . mat - the matrix 7417 7418 Notes: 7419 There can be zeros within the blocks 7420 7421 The blocks can overlap between processes, including laying on more than two processes 7422 7423 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()` 7424 */ 7425 static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat) 7426 { 7427 PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend; 7428 PetscInt *diag, *odiag, sc; 7429 VecScatter scatter; 7430 PetscScalar *seqv; 7431 const PetscScalar *parv; 7432 const PetscInt *ia, *ja; 7433 PetscBool set, flag, done; 7434 Mat AA = mat, A; 7435 MPI_Comm comm; 7436 PetscMPIInt rank, size, tag; 7437 MPI_Status status; 7438 PetscContainer container; 7439 EnvelopeData *edata; 7440 Vec seq, par; 7441 IS isglobal; 7442 7443 PetscFunctionBegin; 7444 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7445 PetscCall(MatIsSymmetricKnown(mat, &set, &flag)); 7446 if (!set || !flag) { 7447 /* TOO: only needs nonzero structure of transpose */ 7448 PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA)); 7449 PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN)); 7450 } 7451 PetscCall(MatAIJGetLocalMat(AA, &A)); 7452 PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7453 PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix"); 7454 7455 PetscCall(MatGetLocalSize(mat, &n, NULL)); 7456 PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag)); 7457 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 7458 PetscCallMPI(MPI_Comm_size(comm, &size)); 7459 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7460 7461 PetscCall(PetscMalloc2(n, &sizes, n, &starts)); 7462 7463 if (rank > 0) { 7464 PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7465 PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7466 } 7467 PetscCall(MatGetOwnershipRange(mat, &rstart, NULL)); 7468 for (i = 0; i < n; i++) { 7469 env = PetscMax(env, ja[ia[i + 1] - 1]); 7470 II = rstart + i; 7471 if (env == II) { 7472 starts[lblocks] = tbs; 7473 sizes[lblocks++] = 1 + II - tbs; 7474 tbs = 1 + II; 7475 } 7476 } 7477 if (rank < size - 1) { 7478 PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm)); 7479 PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm)); 7480 } 7481 7482 PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7483 if (!set || !flag) PetscCall(MatDestroy(&AA)); 7484 PetscCall(MatDestroy(&A)); 7485 7486 PetscCall(PetscNew(&edata)); 7487 PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate)); 7488 edata->n = lblocks; 7489 /* create IS needed for extracting blocks from the original matrix */ 7490 PetscCall(PetscMalloc1(lblocks, &edata->is)); 7491 for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i])); 7492 7493 /* Create the resulting inverse matrix structure with preallocation information */ 7494 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C)); 7495 PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 7496 PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat)); 7497 PetscCall(MatSetType(edata->C, MATAIJ)); 7498 7499 /* Communicate the start and end of each row, from each block to the correct rank */ 7500 /* TODO: Use PetscSF instead of VecScatter */ 7501 for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i]; 7502 PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq)); 7503 PetscCall(VecGetArrayWrite(seq, &seqv)); 7504 for (PetscInt i = 0; i < lblocks; i++) { 7505 for (PetscInt j = 0; j < sizes[i]; j++) { 7506 seqv[cnt] = starts[i]; 7507 seqv[cnt + 1] = starts[i] + sizes[i]; 7508 cnt += 2; 7509 } 7510 } 7511 PetscCall(VecRestoreArrayWrite(seq, &seqv)); 7512 PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 7513 sc -= cnt; 7514 PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par)); 7515 PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal)); 7516 PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter)); 7517 PetscCall(ISDestroy(&isglobal)); 7518 PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7519 PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7520 PetscCall(VecScatterDestroy(&scatter)); 7521 PetscCall(VecDestroy(&seq)); 7522 PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend)); 7523 PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag)); 7524 PetscCall(VecGetArrayRead(par, &parv)); 7525 cnt = 0; 7526 PetscCall(MatGetSize(mat, NULL, &n)); 7527 for (PetscInt i = 0; i < mat->rmap->n; i++) { 7528 PetscInt start, end, d = 0, od = 0; 7529 7530 start = (PetscInt)PetscRealPart(parv[cnt]); 7531 end = (PetscInt)PetscRealPart(parv[cnt + 1]); 7532 cnt += 2; 7533 7534 if (start < cstart) { 7535 od += cstart - start + n - cend; 7536 d += cend - cstart; 7537 } else if (start < cend) { 7538 od += n - cend; 7539 d += cend - start; 7540 } else od += n - start; 7541 if (end <= cstart) { 7542 od -= cstart - end + n - cend; 7543 d -= cend - cstart; 7544 } else if (end < cend) { 7545 od -= n - cend; 7546 d -= cend - end; 7547 } else od -= n - end; 7548 7549 odiag[i] = od; 7550 diag[i] = d; 7551 } 7552 PetscCall(VecRestoreArrayRead(par, &parv)); 7553 PetscCall(VecDestroy(&par)); 7554 PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL)); 7555 PetscCall(PetscFree2(diag, odiag)); 7556 PetscCall(PetscFree2(sizes, starts)); 7557 7558 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container)); 7559 PetscCall(PetscContainerSetPointer(container, edata)); 7560 PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy)); 7561 PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container)); 7562 PetscCall(PetscObjectDereference((PetscObject)container)); 7563 PetscFunctionReturn(PETSC_SUCCESS); 7564 } 7565 7566 /*@ 7567 MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A 7568 7569 Collective 7570 7571 Input Parameters: 7572 + A - the matrix 7573 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine 7574 7575 Output Parameter: 7576 . C - matrix with inverted block diagonal of `A` 7577 7578 Level: advanced 7579 7580 Note: 7581 For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal. 7582 7583 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()` 7584 @*/ 7585 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C) 7586 { 7587 PetscContainer container; 7588 EnvelopeData *edata; 7589 PetscObjectState nonzerostate; 7590 7591 PetscFunctionBegin; 7592 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7593 if (!container) { 7594 PetscCall(MatComputeVariableBlockEnvelope(A)); 7595 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7596 } 7597 PetscCall(PetscContainerGetPointer(container, (void **)&edata)); 7598 PetscCall(MatGetNonzeroState(A, &nonzerostate)); 7599 PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure"); 7600 PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output"); 7601 7602 PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat)); 7603 *C = edata->C; 7604 7605 for (PetscInt i = 0; i < edata->n; i++) { 7606 Mat D; 7607 PetscScalar *dvalues; 7608 7609 PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D)); 7610 PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE)); 7611 PetscCall(MatSeqDenseInvert(D)); 7612 PetscCall(MatDenseGetArray(D, &dvalues)); 7613 PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES)); 7614 PetscCall(MatDestroy(&D)); 7615 } 7616 PetscCall(MatDestroySubMatrices(edata->n, &edata->mat)); 7617 PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY)); 7618 PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY)); 7619 PetscFunctionReturn(PETSC_SUCCESS); 7620 } 7621 7622 /*@ 7623 MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size 7624 7625 Logically Collective 7626 7627 Input Parameters: 7628 + mat - the matrix 7629 . nblocks - the number of blocks on this process, each block can only exist on a single process 7630 - bsizes - the block sizes 7631 7632 Level: intermediate 7633 7634 Notes: 7635 Currently used by `PCVPBJACOBI` for `MATAIJ` matrices 7636 7637 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. 7638 7639 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, 7640 `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI` 7641 @*/ 7642 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes) 7643 { 7644 PetscInt i, ncnt = 0, nlocal; 7645 7646 PetscFunctionBegin; 7647 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7648 PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero"); 7649 PetscCall(MatGetLocalSize(mat, &nlocal, NULL)); 7650 for (i = 0; i < nblocks; i++) ncnt += bsizes[i]; 7651 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); 7652 PetscCall(PetscFree(mat->bsizes)); 7653 mat->nblocks = nblocks; 7654 PetscCall(PetscMalloc1(nblocks, &mat->bsizes)); 7655 PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks)); 7656 PetscFunctionReturn(PETSC_SUCCESS); 7657 } 7658 7659 /*@C 7660 MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size 7661 7662 Logically Collective; No Fortran Support 7663 7664 Input Parameter: 7665 . mat - the matrix 7666 7667 Output Parameters: 7668 + nblocks - the number of blocks on this process 7669 - bsizes - the block sizes 7670 7671 Level: intermediate 7672 7673 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()` 7674 @*/ 7675 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes) 7676 { 7677 PetscFunctionBegin; 7678 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7679 *nblocks = mat->nblocks; 7680 *bsizes = mat->bsizes; 7681 PetscFunctionReturn(PETSC_SUCCESS); 7682 } 7683 7684 /*@ 7685 MatSetBlockSizes - Sets the matrix block row and column sizes. 7686 7687 Logically Collective 7688 7689 Input Parameters: 7690 + mat - the matrix 7691 . rbs - row block size 7692 - cbs - column block size 7693 7694 Level: intermediate 7695 7696 Notes: 7697 Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix. 7698 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7699 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7700 7701 For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes 7702 are compatible with the matrix local sizes. 7703 7704 The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`. 7705 7706 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()` 7707 @*/ 7708 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs) 7709 { 7710 PetscFunctionBegin; 7711 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7712 PetscValidLogicalCollectiveInt(mat, rbs, 2); 7713 PetscValidLogicalCollectiveInt(mat, cbs, 3); 7714 PetscTryTypeMethod(mat, setblocksizes, rbs, cbs); 7715 if (mat->rmap->refcnt) { 7716 ISLocalToGlobalMapping l2g = NULL; 7717 PetscLayout nmap = NULL; 7718 7719 PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap)); 7720 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g)); 7721 PetscCall(PetscLayoutDestroy(&mat->rmap)); 7722 mat->rmap = nmap; 7723 mat->rmap->mapping = l2g; 7724 } 7725 if (mat->cmap->refcnt) { 7726 ISLocalToGlobalMapping l2g = NULL; 7727 PetscLayout nmap = NULL; 7728 7729 PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap)); 7730 if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g)); 7731 PetscCall(PetscLayoutDestroy(&mat->cmap)); 7732 mat->cmap = nmap; 7733 mat->cmap->mapping = l2g; 7734 } 7735 PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs)); 7736 PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs)); 7737 PetscFunctionReturn(PETSC_SUCCESS); 7738 } 7739 7740 /*@ 7741 MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices 7742 7743 Logically Collective 7744 7745 Input Parameters: 7746 + mat - the matrix 7747 . fromRow - matrix from which to copy row block size 7748 - fromCol - matrix from which to copy column block size (can be same as fromRow) 7749 7750 Level: developer 7751 7752 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()` 7753 @*/ 7754 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol) 7755 { 7756 PetscFunctionBegin; 7757 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7758 PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2); 7759 PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3); 7760 if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs)); 7761 if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs)); 7762 PetscFunctionReturn(PETSC_SUCCESS); 7763 } 7764 7765 /*@ 7766 MatResidual - Default routine to calculate the residual r = b - Ax 7767 7768 Collective 7769 7770 Input Parameters: 7771 + mat - the matrix 7772 . b - the right-hand-side 7773 - x - the approximate solution 7774 7775 Output Parameter: 7776 . r - location to store the residual 7777 7778 Level: developer 7779 7780 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()` 7781 @*/ 7782 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r) 7783 { 7784 PetscFunctionBegin; 7785 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7786 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 7787 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 7788 PetscValidHeaderSpecific(r, VEC_CLASSID, 4); 7789 PetscValidType(mat, 1); 7790 MatCheckPreallocated(mat, 1); 7791 PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0)); 7792 if (!mat->ops->residual) { 7793 PetscCall(MatMult(mat, x, r)); 7794 PetscCall(VecAYPX(r, -1.0, b)); 7795 } else { 7796 PetscUseTypeMethod(mat, residual, b, x, r); 7797 } 7798 PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0)); 7799 PetscFunctionReturn(PETSC_SUCCESS); 7800 } 7801 7802 /*MC 7803 MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix 7804 7805 Synopsis: 7806 MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 7807 7808 Not Collective 7809 7810 Input Parameters: 7811 + A - the matrix 7812 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7813 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7814 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7815 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7816 always used. 7817 7818 Output Parameters: 7819 + n - number of local rows in the (possibly compressed) matrix 7820 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 7821 . ja - the column indices 7822 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7823 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7824 7825 Level: developer 7826 7827 Note: 7828 Use `MatRestoreRowIJF90()` when you no longer need access to the data 7829 7830 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()` 7831 M*/ 7832 7833 /*MC 7834 MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()` 7835 7836 Synopsis: 7837 MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 7838 7839 Not Collective 7840 7841 Input Parameters: 7842 + A - the matrix 7843 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7844 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7845 inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7846 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7847 always used. 7848 . n - number of local rows in the (possibly compressed) matrix 7849 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 7850 . ja - the column indices 7851 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7852 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7853 7854 Level: developer 7855 7856 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()` 7857 M*/ 7858 7859 /*@C 7860 MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix 7861 7862 Collective 7863 7864 Input Parameters: 7865 + mat - the matrix 7866 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7867 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7868 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7869 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7870 always used. 7871 7872 Output Parameters: 7873 + n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed 7874 . 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 7875 . ja - the column indices, use `NULL` if not needed 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 Notes: 7882 You CANNOT change any of the ia[] or ja[] values. 7883 7884 Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values. 7885 7886 Fortran Notes: 7887 Use 7888 .vb 7889 PetscInt, pointer :: ia(:),ja(:) 7890 call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr) 7891 ! Access the ith and jth entries via ia(i) and ja(j) 7892 .ve 7893 `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()` 7894 7895 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()` 7896 @*/ 7897 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7898 { 7899 PetscFunctionBegin; 7900 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7901 PetscValidType(mat, 1); 7902 if (n) PetscValidIntPointer(n, 5); 7903 if (ia) PetscValidPointer(ia, 6); 7904 if (ja) PetscValidPointer(ja, 7); 7905 if (done) PetscValidBoolPointer(done, 8); 7906 MatCheckPreallocated(mat, 1); 7907 if (!mat->ops->getrowij && done) *done = PETSC_FALSE; 7908 else { 7909 if (done) *done = PETSC_TRUE; 7910 PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0)); 7911 PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done); 7912 PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0)); 7913 } 7914 PetscFunctionReturn(PETSC_SUCCESS); 7915 } 7916 7917 /*@C 7918 MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices. 7919 7920 Collective 7921 7922 Input Parameters: 7923 + mat - the matrix 7924 . shift - 1 or zero indicating we want the indices starting at 0 or 1 7925 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be 7926 symmetrized 7927 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7928 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7929 always used. 7930 . n - number of columns in the (possibly compressed) matrix 7931 . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix 7932 - ja - the row indices 7933 7934 Output Parameter: 7935 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned 7936 7937 Level: developer 7938 7939 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 7940 @*/ 7941 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7942 { 7943 PetscFunctionBegin; 7944 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7945 PetscValidType(mat, 1); 7946 PetscValidIntPointer(n, 5); 7947 if (ia) PetscValidPointer(ia, 6); 7948 if (ja) PetscValidPointer(ja, 7); 7949 PetscValidBoolPointer(done, 8); 7950 MatCheckPreallocated(mat, 1); 7951 if (!mat->ops->getcolumnij) *done = PETSC_FALSE; 7952 else { 7953 *done = PETSC_TRUE; 7954 PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 7955 } 7956 PetscFunctionReturn(PETSC_SUCCESS); 7957 } 7958 7959 /*@C 7960 MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`. 7961 7962 Collective 7963 7964 Input Parameters: 7965 + mat - the matrix 7966 . shift - 1 or zero indicating we want the indices starting at 0 or 1 7967 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7968 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7969 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7970 always used. 7971 . n - size of (possibly compressed) matrix 7972 . ia - the row pointers 7973 - ja - the column indices 7974 7975 Output Parameter: 7976 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 7977 7978 Level: developer 7979 7980 Note: 7981 This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental 7982 us of the array after it has been restored. If you pass `NULL`, it will 7983 not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid. 7984 7985 Fortran Note: 7986 `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()` 7987 7988 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()` 7989 @*/ 7990 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7991 { 7992 PetscFunctionBegin; 7993 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7994 PetscValidType(mat, 1); 7995 if (ia) PetscValidPointer(ia, 6); 7996 if (ja) PetscValidPointer(ja, 7); 7997 if (done) PetscValidBoolPointer(done, 8); 7998 MatCheckPreallocated(mat, 1); 7999 8000 if (!mat->ops->restorerowij && done) *done = PETSC_FALSE; 8001 else { 8002 if (done) *done = PETSC_TRUE; 8003 PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8004 if (n) *n = 0; 8005 if (ia) *ia = NULL; 8006 if (ja) *ja = NULL; 8007 } 8008 PetscFunctionReturn(PETSC_SUCCESS); 8009 } 8010 8011 /*@C 8012 MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`. 8013 8014 Collective 8015 8016 Input Parameters: 8017 + mat - the matrix 8018 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8019 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8020 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8021 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8022 always used. 8023 8024 Output Parameters: 8025 + n - size of (possibly compressed) matrix 8026 . ia - the column pointers 8027 . ja - the row indices 8028 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8029 8030 Level: developer 8031 8032 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()` 8033 @*/ 8034 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8035 { 8036 PetscFunctionBegin; 8037 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8038 PetscValidType(mat, 1); 8039 if (ia) PetscValidPointer(ia, 6); 8040 if (ja) PetscValidPointer(ja, 7); 8041 PetscValidBoolPointer(done, 8); 8042 MatCheckPreallocated(mat, 1); 8043 8044 if (!mat->ops->restorecolumnij) *done = PETSC_FALSE; 8045 else { 8046 *done = PETSC_TRUE; 8047 PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8048 if (n) *n = 0; 8049 if (ia) *ia = NULL; 8050 if (ja) *ja = NULL; 8051 } 8052 PetscFunctionReturn(PETSC_SUCCESS); 8053 } 8054 8055 /*@C 8056 MatColoringPatch -Used inside matrix coloring routines that use `MatGetRowIJ()` and/or `MatGetColumnIJ()`. 8057 8058 Collective 8059 8060 Input Parameters: 8061 + mat - the matrix 8062 . ncolors - maximum color value 8063 . n - number of entries in colorarray 8064 - colorarray - array indicating color for each column 8065 8066 Output Parameter: 8067 . iscoloring - coloring generated using colorarray information 8068 8069 Level: developer 8070 8071 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()` 8072 @*/ 8073 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring) 8074 { 8075 PetscFunctionBegin; 8076 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8077 PetscValidType(mat, 1); 8078 PetscValidIntPointer(colorarray, 4); 8079 PetscValidPointer(iscoloring, 5); 8080 MatCheckPreallocated(mat, 1); 8081 8082 if (!mat->ops->coloringpatch) { 8083 PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring)); 8084 } else { 8085 PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring); 8086 } 8087 PetscFunctionReturn(PETSC_SUCCESS); 8088 } 8089 8090 /*@ 8091 MatSetUnfactored - Resets a factored matrix to be treated as unfactored. 8092 8093 Logically Collective 8094 8095 Input Parameter: 8096 . mat - the factored matrix to be reset 8097 8098 Level: developer 8099 8100 Notes: 8101 This routine should be used only with factored matrices formed by in-place 8102 factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE` 8103 format). This option can save memory, for example, when solving nonlinear 8104 systems with a matrix-free Newton-Krylov method and a matrix-based, in-place 8105 ILU(0) preconditioner. 8106 8107 One can specify in-place ILU(0) factorization by calling 8108 .vb 8109 PCType(pc,PCILU); 8110 PCFactorSeUseInPlace(pc); 8111 .ve 8112 or by using the options -pc_type ilu -pc_factor_in_place 8113 8114 In-place factorization ILU(0) can also be used as a local 8115 solver for the blocks within the block Jacobi or additive Schwarz 8116 methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc 8117 for details on setting local solver options. 8118 8119 Most users should employ the `KSP` interface for linear solvers 8120 instead of working directly with matrix algebra routines such as this. 8121 See, e.g., `KSPCreate()`. 8122 8123 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()` 8124 @*/ 8125 PetscErrorCode MatSetUnfactored(Mat mat) 8126 { 8127 PetscFunctionBegin; 8128 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8129 PetscValidType(mat, 1); 8130 MatCheckPreallocated(mat, 1); 8131 mat->factortype = MAT_FACTOR_NONE; 8132 if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS); 8133 PetscUseTypeMethod(mat, setunfactored); 8134 PetscFunctionReturn(PETSC_SUCCESS); 8135 } 8136 8137 /*MC 8138 MatDenseGetArrayF90 - Accesses a matrix array from Fortran 8139 8140 Synopsis: 8141 MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8142 8143 Not Collective 8144 8145 Input Parameter: 8146 . x - matrix 8147 8148 Output Parameters: 8149 + xx_v - the Fortran pointer to the array 8150 - ierr - error code 8151 8152 Example of Usage: 8153 .vb 8154 PetscScalar, pointer xx_v(:,:) 8155 .... 8156 call MatDenseGetArrayF90(x,xx_v,ierr) 8157 a = xx_v(3) 8158 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8159 .ve 8160 8161 Level: advanced 8162 8163 .seealso: [](ch_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()` 8164 M*/ 8165 8166 /*MC 8167 MatDenseRestoreArrayF90 - Restores a matrix array that has been 8168 accessed with `MatDenseGetArrayF90()`. 8169 8170 Synopsis: 8171 MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8172 8173 Not Collective 8174 8175 Input Parameters: 8176 + x - matrix 8177 - xx_v - the Fortran90 pointer to the array 8178 8179 Output Parameter: 8180 . ierr - error code 8181 8182 Example of Usage: 8183 .vb 8184 PetscScalar, pointer xx_v(:,:) 8185 .... 8186 call MatDenseGetArrayF90(x,xx_v,ierr) 8187 a = xx_v(3) 8188 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8189 .ve 8190 8191 Level: advanced 8192 8193 .seealso: [](ch_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()` 8194 M*/ 8195 8196 /*MC 8197 MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran. 8198 8199 Synopsis: 8200 MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8201 8202 Not Collective 8203 8204 Input Parameter: 8205 . x - matrix 8206 8207 Output Parameters: 8208 + xx_v - the Fortran pointer to the array 8209 - ierr - error code 8210 8211 Example of Usage: 8212 .vb 8213 PetscScalar, pointer xx_v(:) 8214 .... 8215 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8216 a = xx_v(3) 8217 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8218 .ve 8219 8220 Level: advanced 8221 8222 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()` 8223 M*/ 8224 8225 /*MC 8226 MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been 8227 accessed with `MatSeqAIJGetArrayF90()`. 8228 8229 Synopsis: 8230 MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8231 8232 Not Collective 8233 8234 Input Parameters: 8235 + x - matrix 8236 - xx_v - the Fortran90 pointer to the array 8237 8238 Output Parameter: 8239 . ierr - error code 8240 8241 Example of Usage: 8242 .vb 8243 PetscScalar, pointer xx_v(:) 8244 .... 8245 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8246 a = xx_v(3) 8247 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8248 .ve 8249 8250 Level: advanced 8251 8252 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()` 8253 M*/ 8254 8255 /*@ 8256 MatCreateSubMatrix - Gets a single submatrix on the same number of processors 8257 as the original matrix. 8258 8259 Collective 8260 8261 Input Parameters: 8262 + mat - the original matrix 8263 . isrow - parallel `IS` containing the rows this processor should obtain 8264 . 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. 8265 - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 8266 8267 Output Parameter: 8268 . newmat - the new submatrix, of the same type as the original matrix 8269 8270 Level: advanced 8271 8272 Notes: 8273 The submatrix will be able to be multiplied with vectors using the same layout as `iscol`. 8274 8275 Some matrix types place restrictions on the row and column indices, such 8276 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; 8277 for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row. 8278 8279 The index sets may not have duplicate entries. 8280 8281 The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`, 8282 the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls 8283 to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX` 8284 will reuse the matrix generated the first time. You should call `MatDestroy()` on `newmat` when 8285 you are finished using it. 8286 8287 The communicator of the newly obtained matrix is ALWAYS the same as the communicator of 8288 the input matrix. 8289 8290 If `iscol` is `NULL` then all columns are obtained (not supported in Fortran). 8291 8292 Example usage: 8293 Consider the following 8x8 matrix with 34 non-zero values, that is 8294 assembled across 3 processors. Let's assume that proc0 owns 3 rows, 8295 proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 8296 as follows 8297 .vb 8298 1 2 0 | 0 3 0 | 0 4 8299 Proc0 0 5 6 | 7 0 0 | 8 0 8300 9 0 10 | 11 0 0 | 12 0 8301 ------------------------------------- 8302 13 0 14 | 15 16 17 | 0 0 8303 Proc1 0 18 0 | 19 20 21 | 0 0 8304 0 0 0 | 22 23 0 | 24 0 8305 ------------------------------------- 8306 Proc2 25 26 27 | 0 0 28 | 29 0 8307 30 0 0 | 31 32 33 | 0 34 8308 .ve 8309 8310 Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6]. The resulting submatrix is 8311 8312 .vb 8313 2 0 | 0 3 0 | 0 8314 Proc0 5 6 | 7 0 0 | 8 8315 ------------------------------- 8316 Proc1 18 0 | 19 20 21 | 0 8317 ------------------------------- 8318 Proc2 26 27 | 0 0 28 | 29 8319 0 0 | 31 32 33 | 0 8320 .ve 8321 8322 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()` 8323 @*/ 8324 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat) 8325 { 8326 PetscMPIInt size; 8327 Mat *local; 8328 IS iscoltmp; 8329 PetscBool flg; 8330 8331 PetscFunctionBegin; 8332 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8333 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 8334 if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 8335 PetscValidPointer(newmat, 5); 8336 if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5); 8337 PetscValidType(mat, 1); 8338 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8339 PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX"); 8340 8341 MatCheckPreallocated(mat, 1); 8342 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8343 8344 if (!iscol || isrow == iscol) { 8345 PetscBool stride; 8346 PetscMPIInt grabentirematrix = 0, grab; 8347 PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride)); 8348 if (stride) { 8349 PetscInt first, step, n, rstart, rend; 8350 PetscCall(ISStrideGetInfo(isrow, &first, &step)); 8351 if (step == 1) { 8352 PetscCall(MatGetOwnershipRange(mat, &rstart, &rend)); 8353 if (rstart == first) { 8354 PetscCall(ISGetLocalSize(isrow, &n)); 8355 if (n == rend - rstart) grabentirematrix = 1; 8356 } 8357 } 8358 } 8359 PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat))); 8360 if (grab) { 8361 PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n")); 8362 if (cll == MAT_INITIAL_MATRIX) { 8363 *newmat = mat; 8364 PetscCall(PetscObjectReference((PetscObject)mat)); 8365 } 8366 PetscFunctionReturn(PETSC_SUCCESS); 8367 } 8368 } 8369 8370 if (!iscol) { 8371 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp)); 8372 } else { 8373 iscoltmp = iscol; 8374 } 8375 8376 /* if original matrix is on just one processor then use submatrix generated */ 8377 if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) { 8378 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat)); 8379 goto setproperties; 8380 } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) { 8381 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local)); 8382 *newmat = *local; 8383 PetscCall(PetscFree(local)); 8384 goto setproperties; 8385 } else if (!mat->ops->createsubmatrix) { 8386 /* Create a new matrix type that implements the operation using the full matrix */ 8387 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8388 switch (cll) { 8389 case MAT_INITIAL_MATRIX: 8390 PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat)); 8391 break; 8392 case MAT_REUSE_MATRIX: 8393 PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp)); 8394 break; 8395 default: 8396 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX"); 8397 } 8398 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8399 goto setproperties; 8400 } 8401 8402 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8403 PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat); 8404 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8405 8406 setproperties: 8407 PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg)); 8408 if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat)); 8409 if (!iscol) PetscCall(ISDestroy(&iscoltmp)); 8410 if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat)); 8411 PetscFunctionReturn(PETSC_SUCCESS); 8412 } 8413 8414 /*@ 8415 MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix 8416 8417 Not Collective 8418 8419 Input Parameters: 8420 + A - the matrix we wish to propagate options from 8421 - B - the matrix we wish to propagate options to 8422 8423 Level: beginner 8424 8425 Note: 8426 Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL` 8427 8428 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, MatIsStructurallySymmetricKnown()` 8429 @*/ 8430 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B) 8431 { 8432 PetscFunctionBegin; 8433 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8434 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 8435 B->symmetry_eternal = A->symmetry_eternal; 8436 B->structural_symmetry_eternal = A->structural_symmetry_eternal; 8437 B->symmetric = A->symmetric; 8438 B->structurally_symmetric = A->structurally_symmetric; 8439 B->spd = A->spd; 8440 B->hermitian = A->hermitian; 8441 PetscFunctionReturn(PETSC_SUCCESS); 8442 } 8443 8444 /*@ 8445 MatStashSetInitialSize - sets the sizes of the matrix stash, that is 8446 used during the assembly process to store values that belong to 8447 other processors. 8448 8449 Not Collective 8450 8451 Input Parameters: 8452 + mat - the matrix 8453 . size - the initial size of the stash. 8454 - bsize - the initial size of the block-stash(if used). 8455 8456 Options Database Keys: 8457 + -matstash_initial_size <size> or <size0,size1,...sizep-1> 8458 - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1> 8459 8460 Level: intermediate 8461 8462 Notes: 8463 The block-stash is used for values set with `MatSetValuesBlocked()` while 8464 the stash is used for values set with `MatSetValues()` 8465 8466 Run with the option -info and look for output of the form 8467 MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs. 8468 to determine the appropriate value, MM, to use for size and 8469 MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs. 8470 to determine the value, BMM to use for bsize 8471 8472 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()` 8473 @*/ 8474 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize) 8475 { 8476 PetscFunctionBegin; 8477 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8478 PetscValidType(mat, 1); 8479 PetscCall(MatStashSetInitialSize_Private(&mat->stash, size)); 8480 PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize)); 8481 PetscFunctionReturn(PETSC_SUCCESS); 8482 } 8483 8484 /*@ 8485 MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of 8486 the matrix 8487 8488 Neighbor-wise Collective 8489 8490 Input Parameters: 8491 + mat - the matrix 8492 . x - the vector to be multiplied by the interpolation operator 8493 - y - the vector to be added to the result 8494 8495 Output Parameter: 8496 . w - the resulting vector 8497 8498 Level: intermediate 8499 8500 Notes: 8501 `w` may be the same vector as `y`. 8502 8503 This allows one to use either the restriction or interpolation (its transpose) 8504 matrix to do the interpolation 8505 8506 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8507 @*/ 8508 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w) 8509 { 8510 PetscInt M, N, Ny; 8511 8512 PetscFunctionBegin; 8513 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8514 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8515 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8516 PetscValidHeaderSpecific(w, VEC_CLASSID, 4); 8517 PetscCall(MatGetSize(A, &M, &N)); 8518 PetscCall(VecGetSize(y, &Ny)); 8519 if (M == Ny) { 8520 PetscCall(MatMultAdd(A, x, y, w)); 8521 } else { 8522 PetscCall(MatMultTransposeAdd(A, x, y, w)); 8523 } 8524 PetscFunctionReturn(PETSC_SUCCESS); 8525 } 8526 8527 /*@ 8528 MatInterpolate - y = A*x or A'*x depending on the shape of 8529 the matrix 8530 8531 Neighbor-wise Collective 8532 8533 Input Parameters: 8534 + mat - the matrix 8535 - x - the vector to be interpolated 8536 8537 Output Parameter: 8538 . y - the resulting vector 8539 8540 Level: intermediate 8541 8542 Note: 8543 This allows one to use either the restriction or interpolation (its transpose) 8544 matrix to do the interpolation 8545 8546 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8547 @*/ 8548 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y) 8549 { 8550 PetscInt M, N, Ny; 8551 8552 PetscFunctionBegin; 8553 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8554 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8555 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8556 PetscCall(MatGetSize(A, &M, &N)); 8557 PetscCall(VecGetSize(y, &Ny)); 8558 if (M == Ny) { 8559 PetscCall(MatMult(A, x, y)); 8560 } else { 8561 PetscCall(MatMultTranspose(A, x, y)); 8562 } 8563 PetscFunctionReturn(PETSC_SUCCESS); 8564 } 8565 8566 /*@ 8567 MatRestrict - y = A*x or A'*x 8568 8569 Neighbor-wise Collective 8570 8571 Input Parameters: 8572 + mat - the matrix 8573 - x - the vector to be restricted 8574 8575 Output Parameter: 8576 . y - the resulting vector 8577 8578 Level: intermediate 8579 8580 Note: 8581 This allows one to use either the restriction or interpolation (its transpose) 8582 matrix to do the restriction 8583 8584 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG` 8585 @*/ 8586 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y) 8587 { 8588 PetscInt M, N, Ny; 8589 8590 PetscFunctionBegin; 8591 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8592 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8593 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8594 PetscCall(MatGetSize(A, &M, &N)); 8595 PetscCall(VecGetSize(y, &Ny)); 8596 if (M == Ny) { 8597 PetscCall(MatMult(A, x, y)); 8598 } else { 8599 PetscCall(MatMultTranspose(A, x, y)); 8600 } 8601 PetscFunctionReturn(PETSC_SUCCESS); 8602 } 8603 8604 /*@ 8605 MatMatInterpolateAdd - Y = W + A*X or W + A'*X 8606 8607 Neighbor-wise Collective 8608 8609 Input Parameters: 8610 + mat - the matrix 8611 . x - the input dense matrix to be multiplied 8612 - w - the input dense matrix to be added to the result 8613 8614 Output Parameter: 8615 . y - the output dense matrix 8616 8617 Level: intermediate 8618 8619 Note: 8620 This allows one to use either the restriction or interpolation (its transpose) 8621 matrix to do the interpolation. y matrix can be reused if already created with the proper sizes, 8622 otherwise it will be recreated. y must be initialized to `NULL` if not supplied. 8623 8624 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG` 8625 @*/ 8626 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y) 8627 { 8628 PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0; 8629 PetscBool trans = PETSC_TRUE; 8630 MatReuse reuse = MAT_INITIAL_MATRIX; 8631 8632 PetscFunctionBegin; 8633 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8634 PetscValidHeaderSpecific(x, MAT_CLASSID, 2); 8635 PetscValidType(x, 2); 8636 if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3); 8637 if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4); 8638 PetscCall(MatGetSize(A, &M, &N)); 8639 PetscCall(MatGetSize(x, &Mx, &Nx)); 8640 if (N == Mx) trans = PETSC_FALSE; 8641 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); 8642 Mo = trans ? N : M; 8643 if (*y) { 8644 PetscCall(MatGetSize(*y, &My, &Ny)); 8645 if (Mo == My && Nx == Ny) { 8646 reuse = MAT_REUSE_MATRIX; 8647 } else { 8648 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); 8649 PetscCall(MatDestroy(y)); 8650 } 8651 } 8652 8653 if (w && *y == w) { /* this is to minimize changes in PCMG */ 8654 PetscBool flg; 8655 8656 PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w)); 8657 if (w) { 8658 PetscInt My, Ny, Mw, Nw; 8659 8660 PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg)); 8661 PetscCall(MatGetSize(*y, &My, &Ny)); 8662 PetscCall(MatGetSize(w, &Mw, &Nw)); 8663 if (!flg || My != Mw || Ny != Nw) w = NULL; 8664 } 8665 if (!w) { 8666 PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w)); 8667 PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w)); 8668 PetscCall(PetscObjectDereference((PetscObject)w)); 8669 } else { 8670 PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN)); 8671 } 8672 } 8673 if (!trans) { 8674 PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8675 } else { 8676 PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8677 } 8678 if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN)); 8679 PetscFunctionReturn(PETSC_SUCCESS); 8680 } 8681 8682 /*@ 8683 MatMatInterpolate - Y = A*X or A'*X 8684 8685 Neighbor-wise Collective 8686 8687 Input Parameters: 8688 + mat - the matrix 8689 - x - the input dense matrix 8690 8691 Output Parameter: 8692 . y - the output dense matrix 8693 8694 Level: intermediate 8695 8696 Note: 8697 This allows one to use either the restriction or interpolation (its transpose) 8698 matrix to do the interpolation. y matrix can be reused if already created with the proper sizes, 8699 otherwise it will be recreated. y must be initialized to `NULL` if not supplied. 8700 8701 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG` 8702 @*/ 8703 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y) 8704 { 8705 PetscFunctionBegin; 8706 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8707 PetscFunctionReturn(PETSC_SUCCESS); 8708 } 8709 8710 /*@ 8711 MatMatRestrict - Y = A*X or A'*X 8712 8713 Neighbor-wise Collective 8714 8715 Input Parameters: 8716 + mat - the matrix 8717 - x - the input dense matrix 8718 8719 Output Parameter: 8720 . y - the output dense matrix 8721 8722 Level: intermediate 8723 8724 Note: 8725 This allows one to use either the restriction or interpolation (its transpose) 8726 matrix to do the restriction. y matrix can be reused if already created with the proper sizes, 8727 otherwise it will be recreated. y must be initialized to `NULL` if not supplied. 8728 8729 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG` 8730 @*/ 8731 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y) 8732 { 8733 PetscFunctionBegin; 8734 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8735 PetscFunctionReturn(PETSC_SUCCESS); 8736 } 8737 8738 /*@ 8739 MatGetNullSpace - retrieves the null space of a matrix. 8740 8741 Logically Collective 8742 8743 Input Parameters: 8744 + mat - the matrix 8745 - nullsp - the null space object 8746 8747 Level: developer 8748 8749 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace` 8750 @*/ 8751 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp) 8752 { 8753 PetscFunctionBegin; 8754 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8755 PetscValidPointer(nullsp, 2); 8756 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp; 8757 PetscFunctionReturn(PETSC_SUCCESS); 8758 } 8759 8760 /*@ 8761 MatSetNullSpace - attaches a null space to a matrix. 8762 8763 Logically Collective 8764 8765 Input Parameters: 8766 + mat - the matrix 8767 - nullsp - the null space object 8768 8769 Level: advanced 8770 8771 Notes: 8772 This null space is used by the `KSP` linear solvers to solve singular systems. 8773 8774 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` 8775 8776 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 8777 to zero but the linear system will still be solved in a least squares sense. 8778 8779 The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that 8780 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). 8781 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 8782 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 8783 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). 8784 This \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix. 8785 8786 If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called 8787 `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this 8788 routine also automatically calls `MatSetTransposeNullSpace()`. 8789 8790 The user should call `MatNullSpaceDestroy()`. 8791 8792 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, 8793 `KSPSetPCSide()` 8794 @*/ 8795 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp) 8796 { 8797 PetscFunctionBegin; 8798 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8799 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8800 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8801 PetscCall(MatNullSpaceDestroy(&mat->nullsp)); 8802 mat->nullsp = nullsp; 8803 if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp)); 8804 PetscFunctionReturn(PETSC_SUCCESS); 8805 } 8806 8807 /*@ 8808 MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix. 8809 8810 Logically Collective 8811 8812 Input Parameters: 8813 + mat - the matrix 8814 - nullsp - the null space object 8815 8816 Level: developer 8817 8818 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()` 8819 @*/ 8820 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp) 8821 { 8822 PetscFunctionBegin; 8823 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8824 PetscValidType(mat, 1); 8825 PetscValidPointer(nullsp, 2); 8826 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp; 8827 PetscFunctionReturn(PETSC_SUCCESS); 8828 } 8829 8830 /*@ 8831 MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix 8832 8833 Logically Collective 8834 8835 Input Parameters: 8836 + mat - the matrix 8837 - nullsp - the null space object 8838 8839 Level: advanced 8840 8841 Notes: 8842 This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning. 8843 8844 See `MatSetNullSpace()` 8845 8846 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()` 8847 @*/ 8848 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp) 8849 { 8850 PetscFunctionBegin; 8851 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8852 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8853 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8854 PetscCall(MatNullSpaceDestroy(&mat->transnullsp)); 8855 mat->transnullsp = nullsp; 8856 PetscFunctionReturn(PETSC_SUCCESS); 8857 } 8858 8859 /*@ 8860 MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions 8861 This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix. 8862 8863 Logically Collective 8864 8865 Input Parameters: 8866 + mat - the matrix 8867 - nullsp - the null space object 8868 8869 Level: advanced 8870 8871 Notes: 8872 Overwrites any previous near null space that may have been attached 8873 8874 You can remove the null space by calling this routine with an nullsp of `NULL` 8875 8876 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()` 8877 @*/ 8878 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp) 8879 { 8880 PetscFunctionBegin; 8881 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8882 PetscValidType(mat, 1); 8883 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8884 MatCheckPreallocated(mat, 1); 8885 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8886 PetscCall(MatNullSpaceDestroy(&mat->nearnullsp)); 8887 mat->nearnullsp = nullsp; 8888 PetscFunctionReturn(PETSC_SUCCESS); 8889 } 8890 8891 /*@ 8892 MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()` 8893 8894 Not Collective 8895 8896 Input Parameter: 8897 . mat - the matrix 8898 8899 Output Parameter: 8900 . nullsp - the null space object, `NULL` if not set 8901 8902 Level: advanced 8903 8904 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()` 8905 @*/ 8906 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp) 8907 { 8908 PetscFunctionBegin; 8909 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8910 PetscValidType(mat, 1); 8911 PetscValidPointer(nullsp, 2); 8912 MatCheckPreallocated(mat, 1); 8913 *nullsp = mat->nearnullsp; 8914 PetscFunctionReturn(PETSC_SUCCESS); 8915 } 8916 8917 /*@C 8918 MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix. 8919 8920 Collective 8921 8922 Input Parameters: 8923 + mat - the matrix 8924 . row - row/column permutation 8925 - info - information on desired factorization process 8926 8927 Level: developer 8928 8929 Notes: 8930 Probably really in-place only when level of fill is zero, otherwise allocates 8931 new space to store factored matrix and deletes previous memory. 8932 8933 Most users should employ the `KSP` interface for linear solvers 8934 instead of working directly with matrix algebra routines such as this. 8935 See, e.g., `KSPCreate()`. 8936 8937 Developer Note: 8938 The Fortran interface is not autogenerated as the 8939 interface definition cannot be generated correctly [due to `MatFactorInfo`] 8940 8941 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 8942 @*/ 8943 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info) 8944 { 8945 PetscFunctionBegin; 8946 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8947 PetscValidType(mat, 1); 8948 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 8949 PetscValidPointer(info, 3); 8950 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 8951 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 8952 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8953 MatCheckPreallocated(mat, 1); 8954 PetscUseTypeMethod(mat, iccfactor, row, info); 8955 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 8956 PetscFunctionReturn(PETSC_SUCCESS); 8957 } 8958 8959 /*@ 8960 MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the 8961 ghosted ones. 8962 8963 Not Collective 8964 8965 Input Parameters: 8966 + mat - the matrix 8967 - diag - the diagonal values, including ghost ones 8968 8969 Level: developer 8970 8971 Notes: 8972 Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices 8973 8974 This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()` 8975 8976 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 8977 @*/ 8978 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag) 8979 { 8980 PetscMPIInt size; 8981 8982 PetscFunctionBegin; 8983 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8984 PetscValidHeaderSpecific(diag, VEC_CLASSID, 2); 8985 PetscValidType(mat, 1); 8986 8987 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled"); 8988 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 8989 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8990 if (size == 1) { 8991 PetscInt n, m; 8992 PetscCall(VecGetSize(diag, &n)); 8993 PetscCall(MatGetSize(mat, NULL, &m)); 8994 PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions"); 8995 PetscCall(MatDiagonalScale(mat, NULL, diag)); 8996 } else { 8997 PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag)); 8998 } 8999 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 9000 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9001 PetscFunctionReturn(PETSC_SUCCESS); 9002 } 9003 9004 /*@ 9005 MatGetInertia - Gets the inertia from a factored matrix 9006 9007 Collective 9008 9009 Input Parameter: 9010 . mat - the matrix 9011 9012 Output Parameters: 9013 + nneg - number of negative eigenvalues 9014 . nzero - number of zero eigenvalues 9015 - npos - number of positive eigenvalues 9016 9017 Level: advanced 9018 9019 Note: 9020 Matrix must have been factored by `MatCholeskyFactor()` 9021 9022 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()` 9023 @*/ 9024 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos) 9025 { 9026 PetscFunctionBegin; 9027 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9028 PetscValidType(mat, 1); 9029 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9030 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled"); 9031 PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos); 9032 PetscFunctionReturn(PETSC_SUCCESS); 9033 } 9034 9035 /*@C 9036 MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors 9037 9038 Neighbor-wise Collective 9039 9040 Input Parameters: 9041 + mat - the factored matrix obtained with `MatGetFactor()` 9042 - b - the right-hand-side vectors 9043 9044 Output Parameter: 9045 . x - the result vectors 9046 9047 Level: developer 9048 9049 Note: 9050 The vectors `b` and `x` cannot be the same. I.e., one cannot 9051 call `MatSolves`(A,x,x). 9052 9053 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()` 9054 @*/ 9055 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x) 9056 { 9057 PetscFunctionBegin; 9058 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9059 PetscValidType(mat, 1); 9060 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 9061 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9062 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 9063 9064 MatCheckPreallocated(mat, 1); 9065 PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0)); 9066 PetscUseTypeMethod(mat, solves, b, x); 9067 PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0)); 9068 PetscFunctionReturn(PETSC_SUCCESS); 9069 } 9070 9071 /*@ 9072 MatIsSymmetric - Test whether a matrix is symmetric 9073 9074 Collective 9075 9076 Input Parameters: 9077 + A - the matrix to test 9078 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose) 9079 9080 Output Parameter: 9081 . flg - the result 9082 9083 Level: intermediate 9084 9085 Notes: 9086 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9087 9088 If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()` 9089 9090 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9091 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9092 9093 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`, 9094 `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()` 9095 @*/ 9096 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg) 9097 { 9098 PetscFunctionBegin; 9099 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9100 PetscValidBoolPointer(flg, 3); 9101 9102 if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE; 9103 else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE; 9104 else { 9105 PetscUseTypeMethod(A, issymmetric, tol, flg); 9106 if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg)); 9107 } 9108 PetscFunctionReturn(PETSC_SUCCESS); 9109 } 9110 9111 /*@ 9112 MatIsHermitian - Test whether a matrix is Hermitian 9113 9114 Collective 9115 9116 Input Parameters: 9117 + A - the matrix to test 9118 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian) 9119 9120 Output Parameter: 9121 . flg - the result 9122 9123 Level: intermediate 9124 9125 Notes: 9126 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9127 9128 If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()` 9129 9130 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9131 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`) 9132 9133 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, 9134 `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()` 9135 @*/ 9136 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg) 9137 { 9138 PetscFunctionBegin; 9139 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9140 PetscValidBoolPointer(flg, 3); 9141 9142 if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE; 9143 else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE; 9144 else { 9145 PetscUseTypeMethod(A, ishermitian, tol, flg); 9146 if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg)); 9147 } 9148 PetscFunctionReturn(PETSC_SUCCESS); 9149 } 9150 9151 /*@ 9152 MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state 9153 9154 Not Collective 9155 9156 Input Parameter: 9157 . A - the matrix to check 9158 9159 Output Parameters: 9160 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid) 9161 - flg - the result (only valid if set is `PETSC_TRUE`) 9162 9163 Level: advanced 9164 9165 Notes: 9166 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()` 9167 if you want it explicitly checked 9168 9169 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9170 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9171 9172 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9173 @*/ 9174 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9175 { 9176 PetscFunctionBegin; 9177 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9178 PetscValidBoolPointer(set, 2); 9179 PetscValidBoolPointer(flg, 3); 9180 if (A->symmetric != PETSC_BOOL3_UNKNOWN) { 9181 *set = PETSC_TRUE; 9182 *flg = PetscBool3ToBool(A->symmetric); 9183 } else { 9184 *set = PETSC_FALSE; 9185 } 9186 PetscFunctionReturn(PETSC_SUCCESS); 9187 } 9188 9189 /*@ 9190 MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state 9191 9192 Not Collective 9193 9194 Input Parameter: 9195 . A - the matrix to check 9196 9197 Output Parameters: 9198 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid) 9199 - flg - the result (only valid if set is `PETSC_TRUE`) 9200 9201 Level: advanced 9202 9203 Notes: 9204 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). 9205 9206 One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD 9207 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`) 9208 9209 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9210 @*/ 9211 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg) 9212 { 9213 PetscFunctionBegin; 9214 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9215 PetscValidBoolPointer(set, 2); 9216 PetscValidBoolPointer(flg, 3); 9217 if (A->spd != PETSC_BOOL3_UNKNOWN) { 9218 *set = PETSC_TRUE; 9219 *flg = PetscBool3ToBool(A->spd); 9220 } else { 9221 *set = PETSC_FALSE; 9222 } 9223 PetscFunctionReturn(PETSC_SUCCESS); 9224 } 9225 9226 /*@ 9227 MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state 9228 9229 Not Collective 9230 9231 Input Parameter: 9232 . A - the matrix to check 9233 9234 Output Parameters: 9235 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid) 9236 - flg - the result (only valid if set is `PETSC_TRUE`) 9237 9238 Level: advanced 9239 9240 Notes: 9241 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()` 9242 if you want it explicitly checked 9243 9244 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9245 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9246 9247 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()` 9248 @*/ 9249 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg) 9250 { 9251 PetscFunctionBegin; 9252 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9253 PetscValidBoolPointer(set, 2); 9254 PetscValidBoolPointer(flg, 3); 9255 if (A->hermitian != PETSC_BOOL3_UNKNOWN) { 9256 *set = PETSC_TRUE; 9257 *flg = PetscBool3ToBool(A->hermitian); 9258 } else { 9259 *set = PETSC_FALSE; 9260 } 9261 PetscFunctionReturn(PETSC_SUCCESS); 9262 } 9263 9264 /*@ 9265 MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric 9266 9267 Collective 9268 9269 Input Parameter: 9270 . A - the matrix to test 9271 9272 Output Parameter: 9273 . flg - the result 9274 9275 Level: intermediate 9276 9277 Notes: 9278 If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()` 9279 9280 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 9281 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9282 9283 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()` 9284 @*/ 9285 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg) 9286 { 9287 PetscFunctionBegin; 9288 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9289 PetscValidBoolPointer(flg, 2); 9290 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9291 *flg = PetscBool3ToBool(A->structurally_symmetric); 9292 } else { 9293 PetscUseTypeMethod(A, isstructurallysymmetric, flg); 9294 PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg)); 9295 } 9296 PetscFunctionReturn(PETSC_SUCCESS); 9297 } 9298 9299 /*@ 9300 MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state 9301 9302 Not Collective 9303 9304 Input Parameter: 9305 . A - the matrix to check 9306 9307 Output Parameters: 9308 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid) 9309 - flg - the result (only valid if set is PETSC_TRUE) 9310 9311 Level: advanced 9312 9313 Notes: 9314 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 9315 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9316 9317 Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation) 9318 9319 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9320 @*/ 9321 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9322 { 9323 PetscFunctionBegin; 9324 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9325 PetscValidBoolPointer(set, 2); 9326 PetscValidBoolPointer(flg, 3); 9327 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9328 *set = PETSC_TRUE; 9329 *flg = PetscBool3ToBool(A->structurally_symmetric); 9330 } else { 9331 *set = PETSC_FALSE; 9332 } 9333 PetscFunctionReturn(PETSC_SUCCESS); 9334 } 9335 9336 /*@ 9337 MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need 9338 to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process 9339 9340 Not Collective 9341 9342 Input Parameter: 9343 . mat - the matrix 9344 9345 Output Parameters: 9346 + nstash - the size of the stash 9347 . reallocs - the number of additional mallocs incurred. 9348 . bnstash - the size of the block stash 9349 - breallocs - the number of additional mallocs incurred.in the block stash 9350 9351 Level: advanced 9352 9353 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()` 9354 @*/ 9355 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs) 9356 { 9357 PetscFunctionBegin; 9358 PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs)); 9359 PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs)); 9360 PetscFunctionReturn(PETSC_SUCCESS); 9361 } 9362 9363 /*@C 9364 MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same 9365 parallel layout, `PetscLayout` for rows and columns 9366 9367 Collective 9368 9369 Input Parameter: 9370 . mat - the matrix 9371 9372 Output Parameters: 9373 + right - (optional) vector that the matrix can be multiplied against 9374 - left - (optional) vector that the matrix vector product can be stored in 9375 9376 Level: advanced 9377 9378 Notes: 9379 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()`. 9380 9381 These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed 9382 9383 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()` 9384 @*/ 9385 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left) 9386 { 9387 PetscFunctionBegin; 9388 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9389 PetscValidType(mat, 1); 9390 if (mat->ops->getvecs) { 9391 PetscUseTypeMethod(mat, getvecs, right, left); 9392 } else { 9393 PetscInt rbs, cbs; 9394 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 9395 if (right) { 9396 PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup"); 9397 PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), right)); 9398 PetscCall(VecSetSizes(*right, mat->cmap->n, PETSC_DETERMINE)); 9399 PetscCall(VecSetBlockSize(*right, cbs)); 9400 PetscCall(VecSetType(*right, mat->defaultvectype)); 9401 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9402 if (mat->boundtocpu && mat->bindingpropagates) { 9403 PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE)); 9404 PetscCall(VecBindToCPU(*right, PETSC_TRUE)); 9405 } 9406 #endif 9407 PetscCall(PetscLayoutReference(mat->cmap, &(*right)->map)); 9408 } 9409 if (left) { 9410 PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup"); 9411 PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), left)); 9412 PetscCall(VecSetSizes(*left, mat->rmap->n, PETSC_DETERMINE)); 9413 PetscCall(VecSetBlockSize(*left, rbs)); 9414 PetscCall(VecSetType(*left, mat->defaultvectype)); 9415 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9416 if (mat->boundtocpu && mat->bindingpropagates) { 9417 PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE)); 9418 PetscCall(VecBindToCPU(*left, PETSC_TRUE)); 9419 } 9420 #endif 9421 PetscCall(PetscLayoutReference(mat->rmap, &(*left)->map)); 9422 } 9423 } 9424 PetscFunctionReturn(PETSC_SUCCESS); 9425 } 9426 9427 /*@C 9428 MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure 9429 with default values. 9430 9431 Not Collective 9432 9433 Input Parameter: 9434 . info - the `MatFactorInfo` data structure 9435 9436 Level: developer 9437 9438 Notes: 9439 The solvers are generally used through the `KSP` and `PC` objects, for example 9440 `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC` 9441 9442 Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed 9443 9444 Developer Note: 9445 The Fortran interface is not autogenerated as the 9446 interface definition cannot be generated correctly [due to `MatFactorInfo`] 9447 9448 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo` 9449 @*/ 9450 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info) 9451 { 9452 PetscFunctionBegin; 9453 PetscCall(PetscMemzero(info, sizeof(MatFactorInfo))); 9454 PetscFunctionReturn(PETSC_SUCCESS); 9455 } 9456 9457 /*@ 9458 MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed 9459 9460 Collective 9461 9462 Input Parameters: 9463 + mat - the factored matrix 9464 - is - the index set defining the Schur indices (0-based) 9465 9466 Level: advanced 9467 9468 Notes: 9469 Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system. 9470 9471 You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call. 9472 9473 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9474 9475 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`, 9476 `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9477 @*/ 9478 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is) 9479 { 9480 PetscErrorCode (*f)(Mat, IS); 9481 9482 PetscFunctionBegin; 9483 PetscValidType(mat, 1); 9484 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9485 PetscValidType(is, 2); 9486 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 9487 PetscCheckSameComm(mat, 1, is, 2); 9488 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 9489 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f)); 9490 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO"); 9491 PetscCall(MatDestroy(&mat->schur)); 9492 PetscCall((*f)(mat, is)); 9493 PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created"); 9494 PetscFunctionReturn(PETSC_SUCCESS); 9495 } 9496 9497 /*@ 9498 MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step 9499 9500 Logically Collective 9501 9502 Input Parameters: 9503 + F - the factored matrix obtained by calling `MatGetFactor()` 9504 . S - location where to return the Schur complement, can be `NULL` 9505 - status - the status of the Schur complement matrix, can be `NULL` 9506 9507 Level: advanced 9508 9509 Notes: 9510 You must call `MatFactorSetSchurIS()` before calling this routine. 9511 9512 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9513 9514 The routine provides a copy of the Schur matrix stored within the solver data structures. 9515 The caller must destroy the object when it is no longer needed. 9516 If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse. 9517 9518 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) 9519 9520 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9521 9522 Developer Note: 9523 The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc 9524 matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix. 9525 9526 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9527 @*/ 9528 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9529 { 9530 PetscFunctionBegin; 9531 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9532 if (S) PetscValidPointer(S, 2); 9533 if (status) PetscValidPointer(status, 3); 9534 if (S) { 9535 PetscErrorCode (*f)(Mat, Mat *); 9536 9537 PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f)); 9538 if (f) { 9539 PetscCall((*f)(F, S)); 9540 } else { 9541 PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S)); 9542 } 9543 } 9544 if (status) *status = F->schur_status; 9545 PetscFunctionReturn(PETSC_SUCCESS); 9546 } 9547 9548 /*@ 9549 MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix 9550 9551 Logically Collective 9552 9553 Input Parameters: 9554 + F - the factored matrix obtained by calling `MatGetFactor()` 9555 . *S - location where to return the Schur complement, can be `NULL` 9556 - status - the status of the Schur complement matrix, can be `NULL` 9557 9558 Level: advanced 9559 9560 Notes: 9561 You must call `MatFactorSetSchurIS()` before calling this routine. 9562 9563 Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS` 9564 9565 The routine returns a the Schur Complement stored within the data structures of the solver. 9566 9567 If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement. 9568 9569 The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed. 9570 9571 Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix 9572 9573 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9574 9575 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9576 @*/ 9577 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9578 { 9579 PetscFunctionBegin; 9580 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9581 if (S) PetscValidPointer(S, 2); 9582 if (status) PetscValidPointer(status, 3); 9583 if (S) *S = F->schur; 9584 if (status) *status = F->schur_status; 9585 PetscFunctionReturn(PETSC_SUCCESS); 9586 } 9587 9588 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F) 9589 { 9590 Mat S = F->schur; 9591 9592 PetscFunctionBegin; 9593 switch (F->schur_status) { 9594 case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through 9595 case MAT_FACTOR_SCHUR_INVERTED: 9596 if (S) { 9597 S->ops->solve = NULL; 9598 S->ops->matsolve = NULL; 9599 S->ops->solvetranspose = NULL; 9600 S->ops->matsolvetranspose = NULL; 9601 S->ops->solveadd = NULL; 9602 S->ops->solvetransposeadd = NULL; 9603 S->factortype = MAT_FACTOR_NONE; 9604 PetscCall(PetscFree(S->solvertype)); 9605 } 9606 case MAT_FACTOR_SCHUR_FACTORED: // fall-through 9607 break; 9608 default: 9609 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9610 } 9611 PetscFunctionReturn(PETSC_SUCCESS); 9612 } 9613 9614 /*@ 9615 MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()` 9616 9617 Logically Collective 9618 9619 Input Parameters: 9620 + F - the factored matrix obtained by calling `MatGetFactor()` 9621 . *S - location where the Schur complement is stored 9622 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`) 9623 9624 Level: advanced 9625 9626 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9627 @*/ 9628 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status) 9629 { 9630 PetscFunctionBegin; 9631 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9632 if (S) { 9633 PetscValidHeaderSpecific(*S, MAT_CLASSID, 2); 9634 *S = NULL; 9635 } 9636 F->schur_status = status; 9637 PetscCall(MatFactorUpdateSchurStatus_Private(F)); 9638 PetscFunctionReturn(PETSC_SUCCESS); 9639 } 9640 9641 /*@ 9642 MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step 9643 9644 Logically Collective 9645 9646 Input Parameters: 9647 + F - the factored matrix obtained by calling `MatGetFactor()` 9648 . rhs - location where the right hand side of the Schur complement system is stored 9649 - sol - location where the solution of the Schur complement system has to be returned 9650 9651 Level: advanced 9652 9653 Notes: 9654 The sizes of the vectors should match the size of the Schur complement 9655 9656 Must be called after `MatFactorSetSchurIS()` 9657 9658 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()` 9659 @*/ 9660 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol) 9661 { 9662 PetscFunctionBegin; 9663 PetscValidType(F, 1); 9664 PetscValidType(rhs, 2); 9665 PetscValidType(sol, 3); 9666 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9667 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9668 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9669 PetscCheckSameComm(F, 1, rhs, 2); 9670 PetscCheckSameComm(F, 1, sol, 3); 9671 PetscCall(MatFactorFactorizeSchurComplement(F)); 9672 switch (F->schur_status) { 9673 case MAT_FACTOR_SCHUR_FACTORED: 9674 PetscCall(MatSolveTranspose(F->schur, rhs, sol)); 9675 break; 9676 case MAT_FACTOR_SCHUR_INVERTED: 9677 PetscCall(MatMultTranspose(F->schur, rhs, sol)); 9678 break; 9679 default: 9680 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9681 } 9682 PetscFunctionReturn(PETSC_SUCCESS); 9683 } 9684 9685 /*@ 9686 MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step 9687 9688 Logically Collective 9689 9690 Input Parameters: 9691 + F - the factored matrix obtained by calling `MatGetFactor()` 9692 . rhs - location where the right hand side of the Schur complement system is stored 9693 - sol - location where the solution of the Schur complement system has to be returned 9694 9695 Level: advanced 9696 9697 Notes: 9698 The sizes of the vectors should match the size of the Schur complement 9699 9700 Must be called after `MatFactorSetSchurIS()` 9701 9702 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()` 9703 @*/ 9704 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol) 9705 { 9706 PetscFunctionBegin; 9707 PetscValidType(F, 1); 9708 PetscValidType(rhs, 2); 9709 PetscValidType(sol, 3); 9710 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9711 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9712 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9713 PetscCheckSameComm(F, 1, rhs, 2); 9714 PetscCheckSameComm(F, 1, sol, 3); 9715 PetscCall(MatFactorFactorizeSchurComplement(F)); 9716 switch (F->schur_status) { 9717 case MAT_FACTOR_SCHUR_FACTORED: 9718 PetscCall(MatSolve(F->schur, rhs, sol)); 9719 break; 9720 case MAT_FACTOR_SCHUR_INVERTED: 9721 PetscCall(MatMult(F->schur, rhs, sol)); 9722 break; 9723 default: 9724 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9725 } 9726 PetscFunctionReturn(PETSC_SUCCESS); 9727 } 9728 9729 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat); 9730 #if PetscDefined(HAVE_CUDA) 9731 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat); 9732 #endif 9733 9734 /* Schur status updated in the interface */ 9735 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F) 9736 { 9737 Mat S = F->schur; 9738 9739 PetscFunctionBegin; 9740 if (S) { 9741 PetscMPIInt size; 9742 PetscBool isdense, isdensecuda; 9743 9744 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size)); 9745 PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented"); 9746 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense)); 9747 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda)); 9748 PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name); 9749 PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0)); 9750 if (isdense) { 9751 PetscCall(MatSeqDenseInvertFactors_Private(S)); 9752 } else if (isdensecuda) { 9753 #if defined(PETSC_HAVE_CUDA) 9754 PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S)); 9755 #endif 9756 } 9757 // HIP?????????????? 9758 PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0)); 9759 } 9760 PetscFunctionReturn(PETSC_SUCCESS); 9761 } 9762 9763 /*@ 9764 MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step 9765 9766 Logically Collective 9767 9768 Input Parameter: 9769 . F - the factored matrix obtained by calling `MatGetFactor()` 9770 9771 Level: advanced 9772 9773 Notes: 9774 Must be called after `MatFactorSetSchurIS()`. 9775 9776 Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it. 9777 9778 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()` 9779 @*/ 9780 PetscErrorCode MatFactorInvertSchurComplement(Mat F) 9781 { 9782 PetscFunctionBegin; 9783 PetscValidType(F, 1); 9784 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9785 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS); 9786 PetscCall(MatFactorFactorizeSchurComplement(F)); 9787 PetscCall(MatFactorInvertSchurComplement_Private(F)); 9788 F->schur_status = MAT_FACTOR_SCHUR_INVERTED; 9789 PetscFunctionReturn(PETSC_SUCCESS); 9790 } 9791 9792 /*@ 9793 MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step 9794 9795 Logically Collective 9796 9797 Input Parameter: 9798 . F - the factored matrix obtained by calling `MatGetFactor()` 9799 9800 Level: advanced 9801 9802 Note: 9803 Must be called after `MatFactorSetSchurIS()` 9804 9805 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()` 9806 @*/ 9807 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F) 9808 { 9809 MatFactorInfo info; 9810 9811 PetscFunctionBegin; 9812 PetscValidType(F, 1); 9813 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9814 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS); 9815 PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0)); 9816 PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo))); 9817 if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */ 9818 PetscCall(MatCholeskyFactor(F->schur, NULL, &info)); 9819 } else { 9820 PetscCall(MatLUFactor(F->schur, NULL, NULL, &info)); 9821 } 9822 PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0)); 9823 F->schur_status = MAT_FACTOR_SCHUR_FACTORED; 9824 PetscFunctionReturn(PETSC_SUCCESS); 9825 } 9826 9827 /*@ 9828 MatPtAP - Creates the matrix product C = P^T * A * P 9829 9830 Neighbor-wise Collective 9831 9832 Input Parameters: 9833 + A - the matrix 9834 . P - the projection matrix 9835 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9836 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate 9837 if the result is a dense matrix this is irrelevant 9838 9839 Output Parameter: 9840 . C - the product matrix 9841 9842 Level: intermediate 9843 9844 Notes: 9845 C will be created and must be destroyed by the user with `MatDestroy()`. 9846 9847 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9848 9849 Developer Note: 9850 For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`. 9851 9852 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()` 9853 @*/ 9854 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C) 9855 { 9856 PetscFunctionBegin; 9857 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 9858 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9859 9860 if (scall == MAT_INITIAL_MATRIX) { 9861 PetscCall(MatProductCreate(A, P, NULL, C)); 9862 PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP)); 9863 PetscCall(MatProductSetAlgorithm(*C, "default")); 9864 PetscCall(MatProductSetFill(*C, fill)); 9865 9866 (*C)->product->api_user = PETSC_TRUE; 9867 PetscCall(MatProductSetFromOptions(*C)); 9868 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); 9869 PetscCall(MatProductSymbolic(*C)); 9870 } else { /* scall == MAT_REUSE_MATRIX */ 9871 PetscCall(MatProductReplaceMats(A, P, NULL, *C)); 9872 } 9873 9874 PetscCall(MatProductNumeric(*C)); 9875 (*C)->symmetric = A->symmetric; 9876 (*C)->spd = A->spd; 9877 PetscFunctionReturn(PETSC_SUCCESS); 9878 } 9879 9880 /*@ 9881 MatRARt - Creates the matrix product C = R * A * R^T 9882 9883 Neighbor-wise Collective 9884 9885 Input Parameters: 9886 + A - the matrix 9887 . R - the projection matrix 9888 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9889 - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate 9890 if the result is a dense matrix this is irrelevant 9891 9892 Output Parameter: 9893 . C - the product matrix 9894 9895 Level: intermediate 9896 9897 Notes: 9898 C will be created and must be destroyed by the user with `MatDestroy()`. 9899 9900 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9901 9902 This routine is currently only implemented for pairs of `MATAIJ` matrices and classes 9903 which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes, 9904 parallel MatRARt is implemented via explicit transpose of R, which could be very expensive. 9905 We recommend using MatPtAP(). 9906 9907 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()` 9908 @*/ 9909 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C) 9910 { 9911 PetscFunctionBegin; 9912 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 9913 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9914 9915 if (scall == MAT_INITIAL_MATRIX) { 9916 PetscCall(MatProductCreate(A, R, NULL, C)); 9917 PetscCall(MatProductSetType(*C, MATPRODUCT_RARt)); 9918 PetscCall(MatProductSetAlgorithm(*C, "default")); 9919 PetscCall(MatProductSetFill(*C, fill)); 9920 9921 (*C)->product->api_user = PETSC_TRUE; 9922 PetscCall(MatProductSetFromOptions(*C)); 9923 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); 9924 PetscCall(MatProductSymbolic(*C)); 9925 } else { /* scall == MAT_REUSE_MATRIX */ 9926 PetscCall(MatProductReplaceMats(A, R, NULL, *C)); 9927 } 9928 9929 PetscCall(MatProductNumeric(*C)); 9930 if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 9931 PetscFunctionReturn(PETSC_SUCCESS); 9932 } 9933 9934 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C) 9935 { 9936 PetscFunctionBegin; 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(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype])); 9941 PetscCall(MatProductCreate(A, B, NULL, C)); 9942 PetscCall(MatProductSetType(*C, ptype)); 9943 PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT)); 9944 PetscCall(MatProductSetFill(*C, fill)); 9945 9946 (*C)->product->api_user = PETSC_TRUE; 9947 PetscCall(MatProductSetFromOptions(*C)); 9948 PetscCall(MatProductSymbolic(*C)); 9949 } else { /* scall == MAT_REUSE_MATRIX */ 9950 Mat_Product *product = (*C)->product; 9951 PetscBool isdense; 9952 9953 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, "")); 9954 if (isdense && product && product->type != ptype) { 9955 PetscCall(MatProductClear(*C)); 9956 product = NULL; 9957 } 9958 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype])); 9959 if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */ 9960 PetscCheck(isdense, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first"); 9961 PetscCall(MatProductCreate_Private(A, B, NULL, *C)); 9962 product = (*C)->product; 9963 product->fill = fill; 9964 product->api_user = PETSC_TRUE; 9965 product->clear = PETSC_TRUE; 9966 9967 PetscCall(MatProductSetType(*C, ptype)); 9968 PetscCall(MatProductSetFromOptions(*C)); 9969 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); 9970 PetscCall(MatProductSymbolic(*C)); 9971 } else { /* user may change input matrices A or B when REUSE */ 9972 PetscCall(MatProductReplaceMats(A, B, NULL, *C)); 9973 } 9974 } 9975 PetscCall(MatProductNumeric(*C)); 9976 PetscFunctionReturn(PETSC_SUCCESS); 9977 } 9978 9979 /*@ 9980 MatMatMult - Performs matrix-matrix multiplication C=A*B. 9981 9982 Neighbor-wise Collective 9983 9984 Input Parameters: 9985 + A - the left matrix 9986 . B - the right matrix 9987 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9988 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate 9989 if the result is a dense matrix this is irrelevant 9990 9991 Output Parameter: 9992 . C - the product matrix 9993 9994 Notes: 9995 Unless scall is `MAT_REUSE_MATRIX` C will be created. 9996 9997 `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 9998 call to this function with `MAT_INITIAL_MATRIX`. 9999 10000 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed. 10001 10002 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`, 10003 rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse. 10004 10005 Example of Usage: 10006 .vb 10007 MatProductCreate(A,B,NULL,&C); 10008 MatProductSetType(C,MATPRODUCT_AB); 10009 MatProductSymbolic(C); 10010 MatProductNumeric(C); // compute C=A * B 10011 MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1 10012 MatProductNumeric(C); 10013 MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1 10014 MatProductNumeric(C); 10015 .ve 10016 10017 Level: intermediate 10018 10019 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()` 10020 @*/ 10021 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10022 { 10023 PetscFunctionBegin; 10024 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C)); 10025 PetscFunctionReturn(PETSC_SUCCESS); 10026 } 10027 10028 /*@ 10029 MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T. 10030 10031 Neighbor-wise Collective 10032 10033 Input Parameters: 10034 + A - the left matrix 10035 . B - the right matrix 10036 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10037 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 10038 10039 Output Parameter: 10040 . C - the product matrix 10041 10042 Level: intermediate 10043 10044 Notes: 10045 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10046 10047 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call 10048 10049 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10050 actually needed. 10051 10052 This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class, 10053 and for pairs of `MATMPIDENSE` matrices. 10054 10055 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt` 10056 10057 Options Database Keys: 10058 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the 10059 first redundantly copies the transposed B matrix on each process and requiers O(log P) communication complexity; 10060 the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity. 10061 10062 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductCreate()`, `MatProductAlgorithm`, `MatProductType`, `MATPRODUCT_ABt` 10063 @*/ 10064 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10065 { 10066 PetscFunctionBegin; 10067 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C)); 10068 if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10069 PetscFunctionReturn(PETSC_SUCCESS); 10070 } 10071 10072 /*@ 10073 MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B. 10074 10075 Neighbor-wise Collective 10076 10077 Input Parameters: 10078 + A - the left matrix 10079 . B - the right matrix 10080 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10081 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 10082 10083 Output Parameter: 10084 . C - the product matrix 10085 10086 Level: intermediate 10087 10088 Notes: 10089 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10090 10091 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call. 10092 10093 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB` 10094 10095 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10096 actually needed. 10097 10098 This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes 10099 which inherit from `MATSEQAIJ`. C will be of the same type as the input matrices. 10100 10101 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()` 10102 @*/ 10103 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10104 { 10105 PetscFunctionBegin; 10106 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C)); 10107 PetscFunctionReturn(PETSC_SUCCESS); 10108 } 10109 10110 /*@ 10111 MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C. 10112 10113 Neighbor-wise Collective 10114 10115 Input Parameters: 10116 + A - the left matrix 10117 . B - the middle matrix 10118 . C - the right matrix 10119 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10120 - 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 10121 if the result is a dense matrix this is irrelevant 10122 10123 Output Parameter: 10124 . D - the product matrix 10125 10126 Level: intermediate 10127 10128 Notes: 10129 Unless scall is `MAT_REUSE_MATRIX` D will be created. 10130 10131 `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call 10132 10133 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC` 10134 10135 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10136 actually needed. 10137 10138 If you have many matrices with the same non-zero structure to multiply, you 10139 should use `MAT_REUSE_MATRIX` in all calls but the first 10140 10141 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()` 10142 @*/ 10143 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D) 10144 { 10145 PetscFunctionBegin; 10146 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6); 10147 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10148 10149 if (scall == MAT_INITIAL_MATRIX) { 10150 PetscCall(MatProductCreate(A, B, C, D)); 10151 PetscCall(MatProductSetType(*D, MATPRODUCT_ABC)); 10152 PetscCall(MatProductSetAlgorithm(*D, "default")); 10153 PetscCall(MatProductSetFill(*D, fill)); 10154 10155 (*D)->product->api_user = PETSC_TRUE; 10156 PetscCall(MatProductSetFromOptions(*D)); 10157 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, 10158 ((PetscObject)C)->type_name); 10159 PetscCall(MatProductSymbolic(*D)); 10160 } else { /* user may change input matrices when REUSE */ 10161 PetscCall(MatProductReplaceMats(A, B, C, *D)); 10162 } 10163 PetscCall(MatProductNumeric(*D)); 10164 PetscFunctionReturn(PETSC_SUCCESS); 10165 } 10166 10167 /*@ 10168 MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators. 10169 10170 Collective 10171 10172 Input Parameters: 10173 + mat - the matrix 10174 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices) 10175 . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used) 10176 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10177 10178 Output Parameter: 10179 . matredundant - redundant matrix 10180 10181 Level: advanced 10182 10183 Notes: 10184 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 10185 original matrix has not changed from that last call to MatCreateRedundantMatrix(). 10186 10187 This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before 10188 calling it. 10189 10190 `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be. 10191 10192 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubComm` 10193 @*/ 10194 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant) 10195 { 10196 MPI_Comm comm; 10197 PetscMPIInt size; 10198 PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs; 10199 Mat_Redundant *redund = NULL; 10200 PetscSubcomm psubcomm = NULL; 10201 MPI_Comm subcomm_in = subcomm; 10202 Mat *matseq; 10203 IS isrow, iscol; 10204 PetscBool newsubcomm = PETSC_FALSE; 10205 10206 PetscFunctionBegin; 10207 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10208 if (nsubcomm && reuse == MAT_REUSE_MATRIX) { 10209 PetscValidPointer(*matredundant, 5); 10210 PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5); 10211 } 10212 10213 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10214 if (size == 1 || nsubcomm == 1) { 10215 if (reuse == MAT_INITIAL_MATRIX) { 10216 PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant)); 10217 } else { 10218 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"); 10219 PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN)); 10220 } 10221 PetscFunctionReturn(PETSC_SUCCESS); 10222 } 10223 10224 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10225 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10226 MatCheckPreallocated(mat, 1); 10227 10228 PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0)); 10229 if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */ 10230 /* create psubcomm, then get subcomm */ 10231 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10232 PetscCallMPI(MPI_Comm_size(comm, &size)); 10233 PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size); 10234 10235 PetscCall(PetscSubcommCreate(comm, &psubcomm)); 10236 PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm)); 10237 PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS)); 10238 PetscCall(PetscSubcommSetFromOptions(psubcomm)); 10239 PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL)); 10240 newsubcomm = PETSC_TRUE; 10241 PetscCall(PetscSubcommDestroy(&psubcomm)); 10242 } 10243 10244 /* get isrow, iscol and a local sequential matrix matseq[0] */ 10245 if (reuse == MAT_INITIAL_MATRIX) { 10246 mloc_sub = PETSC_DECIDE; 10247 nloc_sub = PETSC_DECIDE; 10248 if (bs < 1) { 10249 PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M)); 10250 PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N)); 10251 } else { 10252 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M)); 10253 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N)); 10254 } 10255 PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm)); 10256 rstart = rend - mloc_sub; 10257 PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow)); 10258 PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol)); 10259 } else { /* reuse == MAT_REUSE_MATRIX */ 10260 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"); 10261 /* retrieve subcomm */ 10262 PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm)); 10263 redund = (*matredundant)->redundant; 10264 isrow = redund->isrow; 10265 iscol = redund->iscol; 10266 matseq = redund->matseq; 10267 } 10268 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq)); 10269 10270 /* get matredundant over subcomm */ 10271 if (reuse == MAT_INITIAL_MATRIX) { 10272 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant)); 10273 10274 /* create a supporting struct and attach it to C for reuse */ 10275 PetscCall(PetscNew(&redund)); 10276 (*matredundant)->redundant = redund; 10277 redund->isrow = isrow; 10278 redund->iscol = iscol; 10279 redund->matseq = matseq; 10280 if (newsubcomm) { 10281 redund->subcomm = subcomm; 10282 } else { 10283 redund->subcomm = MPI_COMM_NULL; 10284 } 10285 } else { 10286 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant)); 10287 } 10288 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 10289 if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) { 10290 PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE)); 10291 PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE)); 10292 } 10293 #endif 10294 PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0)); 10295 PetscFunctionReturn(PETSC_SUCCESS); 10296 } 10297 10298 /*@C 10299 MatGetMultiProcBlock - Create multiple 'parallel submatrices' from 10300 a given `Mat`. Each submatrix can span multiple procs. 10301 10302 Collective 10303 10304 Input Parameters: 10305 + mat - the matrix 10306 . subcomm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))` 10307 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10308 10309 Output Parameter: 10310 . subMat - parallel sub-matrices each spanning a given `subcomm` 10311 10312 Level: advanced 10313 10314 Notes: 10315 The submatrix partition across processors is dictated by `subComm` a 10316 communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm` 10317 is not restricted to be grouped with consecutive original ranks. 10318 10319 Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices 10320 map directly to the layout of the original matrix [wrt the local 10321 row,col partitioning]. So the original 'DiagonalMat' naturally maps 10322 into the 'DiagonalMat' of the `subMat`, hence it is used directly from 10323 the `subMat`. However the offDiagMat looses some columns - and this is 10324 reconstructed with `MatSetValues()` 10325 10326 This is used by `PCBJACOBI` when a single block spans multiple MPI ranks 10327 10328 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI` 10329 @*/ 10330 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) 10331 { 10332 PetscMPIInt commsize, subCommSize; 10333 10334 PetscFunctionBegin; 10335 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize)); 10336 PetscCallMPI(MPI_Comm_size(subComm, &subCommSize)); 10337 PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize); 10338 10339 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"); 10340 PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10341 PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat); 10342 PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10343 PetscFunctionReturn(PETSC_SUCCESS); 10344 } 10345 10346 /*@ 10347 MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering 10348 10349 Not Collective 10350 10351 Input Parameters: 10352 + mat - matrix to extract local submatrix from 10353 . isrow - local row indices for submatrix 10354 - iscol - local column indices for submatrix 10355 10356 Output Parameter: 10357 . submat - the submatrix 10358 10359 Level: intermediate 10360 10361 Notes: 10362 `submat` should be disposed of with `MatRestoreLocalSubMatrix()`. 10363 10364 Depending on the format of `mat`, the returned submat may not implement `MatMult()`. Its communicator may be 10365 the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of `mat`'s. 10366 10367 `submat` always implements `MatSetValuesLocal()`. If `isrow` and `iscol` have the same block size, then 10368 `MatSetValuesBlockedLocal()` will also be implemented. 10369 10370 `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`. 10371 Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided. 10372 10373 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()` 10374 @*/ 10375 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10376 { 10377 PetscFunctionBegin; 10378 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10379 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10380 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10381 PetscCheckSameComm(isrow, 2, iscol, 3); 10382 PetscValidPointer(submat, 4); 10383 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call"); 10384 10385 if (mat->ops->getlocalsubmatrix) { 10386 PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat); 10387 } else { 10388 PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat)); 10389 } 10390 PetscFunctionReturn(PETSC_SUCCESS); 10391 } 10392 10393 /*@ 10394 MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()` 10395 10396 Not Collective 10397 10398 Input Parameters: 10399 + mat - matrix to extract local submatrix from 10400 . isrow - local row indices for submatrix 10401 . iscol - local column indices for submatrix 10402 - submat - the submatrix 10403 10404 Level: intermediate 10405 10406 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()` 10407 @*/ 10408 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10409 { 10410 PetscFunctionBegin; 10411 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10412 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10413 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10414 PetscCheckSameComm(isrow, 2, iscol, 3); 10415 PetscValidPointer(submat, 4); 10416 if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4); 10417 10418 if (mat->ops->restorelocalsubmatrix) { 10419 PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat); 10420 } else { 10421 PetscCall(MatDestroy(submat)); 10422 } 10423 *submat = NULL; 10424 PetscFunctionReturn(PETSC_SUCCESS); 10425 } 10426 10427 /*@ 10428 MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix 10429 10430 Collective 10431 10432 Input Parameter: 10433 . mat - the matrix 10434 10435 Output Parameter: 10436 . is - if any rows have zero diagonals this contains the list of them 10437 10438 Level: developer 10439 10440 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10441 @*/ 10442 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is) 10443 { 10444 PetscFunctionBegin; 10445 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10446 PetscValidType(mat, 1); 10447 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10448 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10449 10450 if (!mat->ops->findzerodiagonals) { 10451 Vec diag; 10452 const PetscScalar *a; 10453 PetscInt *rows; 10454 PetscInt rStart, rEnd, r, nrow = 0; 10455 10456 PetscCall(MatCreateVecs(mat, &diag, NULL)); 10457 PetscCall(MatGetDiagonal(mat, diag)); 10458 PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd)); 10459 PetscCall(VecGetArrayRead(diag, &a)); 10460 for (r = 0; r < rEnd - rStart; ++r) 10461 if (a[r] == 0.0) ++nrow; 10462 PetscCall(PetscMalloc1(nrow, &rows)); 10463 nrow = 0; 10464 for (r = 0; r < rEnd - rStart; ++r) 10465 if (a[r] == 0.0) rows[nrow++] = r + rStart; 10466 PetscCall(VecRestoreArrayRead(diag, &a)); 10467 PetscCall(VecDestroy(&diag)); 10468 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is)); 10469 } else { 10470 PetscUseTypeMethod(mat, findzerodiagonals, is); 10471 } 10472 PetscFunctionReturn(PETSC_SUCCESS); 10473 } 10474 10475 /*@ 10476 MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size) 10477 10478 Collective 10479 10480 Input Parameter: 10481 . mat - the matrix 10482 10483 Output Parameter: 10484 . is - contains the list of rows with off block diagonal entries 10485 10486 Level: developer 10487 10488 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10489 @*/ 10490 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is) 10491 { 10492 PetscFunctionBegin; 10493 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10494 PetscValidType(mat, 1); 10495 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10496 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10497 10498 PetscUseTypeMethod(mat, findoffblockdiagonalentries, is); 10499 PetscFunctionReturn(PETSC_SUCCESS); 10500 } 10501 10502 /*@C 10503 MatInvertBlockDiagonal - Inverts the block diagonal entries. 10504 10505 Collective; No Fortran Support 10506 10507 Input Parameter: 10508 . mat - the matrix 10509 10510 Output Parameter: 10511 . values - the block inverses in column major order (FORTRAN-like) 10512 10513 Level: advanced 10514 10515 Notes: 10516 The size of the blocks is determined by the block size of the matrix. 10517 10518 The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case 10519 10520 The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size 10521 10522 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()` 10523 @*/ 10524 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values) 10525 { 10526 PetscFunctionBegin; 10527 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10528 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10529 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10530 PetscUseTypeMethod(mat, invertblockdiagonal, values); 10531 PetscFunctionReturn(PETSC_SUCCESS); 10532 } 10533 10534 /*@C 10535 MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries. 10536 10537 Collective; No Fortran Support 10538 10539 Input Parameters: 10540 + mat - the matrix 10541 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()` 10542 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()` 10543 10544 Output Parameter: 10545 . values - the block inverses in column major order (FORTRAN-like) 10546 10547 Level: advanced 10548 10549 Notes: 10550 Use `MatInvertBlockDiagonal()` if all blocks have the same size 10551 10552 The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case 10553 10554 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()` 10555 @*/ 10556 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values) 10557 { 10558 PetscFunctionBegin; 10559 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10560 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10561 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10562 PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values); 10563 PetscFunctionReturn(PETSC_SUCCESS); 10564 } 10565 10566 /*@ 10567 MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A 10568 10569 Collective 10570 10571 Input Parameters: 10572 + A - the matrix 10573 - C - matrix with inverted block diagonal of `A`. This matrix should be created and may have its type set. 10574 10575 Level: advanced 10576 10577 Note: 10578 The blocksize of the matrix is used to determine the blocks on the diagonal of `C` 10579 10580 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()` 10581 @*/ 10582 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C) 10583 { 10584 const PetscScalar *vals; 10585 PetscInt *dnnz; 10586 PetscInt m, rstart, rend, bs, i, j; 10587 10588 PetscFunctionBegin; 10589 PetscCall(MatInvertBlockDiagonal(A, &vals)); 10590 PetscCall(MatGetBlockSize(A, &bs)); 10591 PetscCall(MatGetLocalSize(A, &m, NULL)); 10592 PetscCall(MatSetLayouts(C, A->rmap, A->cmap)); 10593 PetscCall(PetscMalloc1(m / bs, &dnnz)); 10594 for (j = 0; j < m / bs; j++) dnnz[j] = 1; 10595 PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL)); 10596 PetscCall(PetscFree(dnnz)); 10597 PetscCall(MatGetOwnershipRange(C, &rstart, &rend)); 10598 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE)); 10599 for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES)); 10600 PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 10601 PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 10602 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE)); 10603 PetscFunctionReturn(PETSC_SUCCESS); 10604 } 10605 10606 /*@C 10607 MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created 10608 via `MatTransposeColoringCreate()`. 10609 10610 Collective 10611 10612 Input Parameter: 10613 . c - coloring context 10614 10615 Level: intermediate 10616 10617 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()` 10618 @*/ 10619 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c) 10620 { 10621 MatTransposeColoring matcolor = *c; 10622 10623 PetscFunctionBegin; 10624 if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS); 10625 if (--((PetscObject)matcolor)->refct > 0) { 10626 matcolor = NULL; 10627 PetscFunctionReturn(PETSC_SUCCESS); 10628 } 10629 10630 PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow)); 10631 PetscCall(PetscFree(matcolor->rows)); 10632 PetscCall(PetscFree(matcolor->den2sp)); 10633 PetscCall(PetscFree(matcolor->colorforcol)); 10634 PetscCall(PetscFree(matcolor->columns)); 10635 if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart)); 10636 PetscCall(PetscHeaderDestroy(c)); 10637 PetscFunctionReturn(PETSC_SUCCESS); 10638 } 10639 10640 /*@C 10641 MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which 10642 a `MatTransposeColoring` context has been created, computes a dense B^T by applying 10643 `MatTransposeColoring` to sparse B. 10644 10645 Collective 10646 10647 Input Parameters: 10648 + coloring - coloring context created with `MatTransposeColoringCreate()` 10649 - B - sparse matrix 10650 10651 Output Parameter: 10652 . Btdense - dense matrix B^T 10653 10654 Level: developer 10655 10656 Note: 10657 These are used internally for some implementations of `MatRARt()` 10658 10659 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()` 10660 @*/ 10661 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense) 10662 { 10663 PetscFunctionBegin; 10664 PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10665 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 10666 PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3); 10667 10668 PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense)); 10669 PetscFunctionReturn(PETSC_SUCCESS); 10670 } 10671 10672 /*@C 10673 MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which 10674 a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense 10675 in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix 10676 `Csp` from `Cden`. 10677 10678 Collective 10679 10680 Input Parameters: 10681 + matcoloring - coloring context created with `MatTransposeColoringCreate()` 10682 - Cden - matrix product of a sparse matrix and a dense matrix Btdense 10683 10684 Output Parameter: 10685 . Csp - sparse matrix 10686 10687 Level: developer 10688 10689 Note: 10690 These are used internally for some implementations of `MatRARt()` 10691 10692 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()` 10693 @*/ 10694 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp) 10695 { 10696 PetscFunctionBegin; 10697 PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10698 PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2); 10699 PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3); 10700 10701 PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp)); 10702 PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY)); 10703 PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY)); 10704 PetscFunctionReturn(PETSC_SUCCESS); 10705 } 10706 10707 /*@C 10708 MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T. 10709 10710 Collective 10711 10712 Input Parameters: 10713 + mat - the matrix product C 10714 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()` 10715 10716 Output Parameter: 10717 . color - the new coloring context 10718 10719 Level: intermediate 10720 10721 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`, 10722 `MatTransColoringApplyDenToSp()` 10723 @*/ 10724 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color) 10725 { 10726 MatTransposeColoring c; 10727 MPI_Comm comm; 10728 10729 PetscFunctionBegin; 10730 PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10731 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10732 PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL)); 10733 10734 c->ctype = iscoloring->ctype; 10735 PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c); 10736 10737 *color = c; 10738 PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10739 PetscFunctionReturn(PETSC_SUCCESS); 10740 } 10741 10742 /*@ 10743 MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the 10744 matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the 10745 same, otherwise it will be larger 10746 10747 Not Collective 10748 10749 Input Parameter: 10750 . A - the matrix 10751 10752 Output Parameter: 10753 . state - the current state 10754 10755 Level: intermediate 10756 10757 Notes: 10758 You can only compare states from two different calls to the SAME matrix, you cannot compare calls between 10759 different matrices 10760 10761 Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix 10762 10763 Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers. 10764 10765 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()` 10766 @*/ 10767 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state) 10768 { 10769 PetscFunctionBegin; 10770 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10771 *state = mat->nonzerostate; 10772 PetscFunctionReturn(PETSC_SUCCESS); 10773 } 10774 10775 /*@ 10776 MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential 10777 matrices from each processor 10778 10779 Collective 10780 10781 Input Parameters: 10782 + comm - the communicators the parallel matrix will live on 10783 . seqmat - the input sequential matrices 10784 . n - number of local columns (or `PETSC_DECIDE`) 10785 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10786 10787 Output Parameter: 10788 . mpimat - the parallel matrix generated 10789 10790 Level: developer 10791 10792 Note: 10793 The number of columns of the matrix in EACH processor MUST be the same. 10794 10795 .seealso: [](ch_matrices), `Mat` 10796 @*/ 10797 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat) 10798 { 10799 PetscMPIInt size; 10800 10801 PetscFunctionBegin; 10802 PetscCallMPI(MPI_Comm_size(comm, &size)); 10803 if (size == 1) { 10804 if (reuse == MAT_INITIAL_MATRIX) { 10805 PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat)); 10806 } else { 10807 PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN)); 10808 } 10809 PetscFunctionReturn(PETSC_SUCCESS); 10810 } 10811 10812 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"); 10813 10814 PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0)); 10815 PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat)); 10816 PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0)); 10817 PetscFunctionReturn(PETSC_SUCCESS); 10818 } 10819 10820 /*@ 10821 MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent ranks' ownership ranges. 10822 10823 Collective 10824 10825 Input Parameters: 10826 + A - the matrix to create subdomains from 10827 - N - requested number of subdomains 10828 10829 Output Parameters: 10830 + n - number of subdomains resulting on this rank 10831 - iss - `IS` list with indices of subdomains on this rank 10832 10833 Level: advanced 10834 10835 Note: 10836 The number of subdomains must be smaller than the communicator size 10837 10838 .seealso: [](ch_matrices), `Mat`, `IS` 10839 @*/ 10840 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[]) 10841 { 10842 MPI_Comm comm, subcomm; 10843 PetscMPIInt size, rank, color; 10844 PetscInt rstart, rend, k; 10845 10846 PetscFunctionBegin; 10847 PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 10848 PetscCallMPI(MPI_Comm_size(comm, &size)); 10849 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 10850 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); 10851 *n = 1; 10852 k = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */ 10853 color = rank / k; 10854 PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm)); 10855 PetscCall(PetscMalloc1(1, iss)); 10856 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 10857 PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0])); 10858 PetscCallMPI(MPI_Comm_free(&subcomm)); 10859 PetscFunctionReturn(PETSC_SUCCESS); 10860 } 10861 10862 /*@ 10863 MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection. 10864 10865 If the interpolation and restriction operators are the same, uses `MatPtAP()`. 10866 If they are not the same, uses `MatMatMatMult()`. 10867 10868 Once the coarse grid problem is constructed, correct for interpolation operators 10869 that are not of full rank, which can legitimately happen in the case of non-nested 10870 geometric multigrid. 10871 10872 Input Parameters: 10873 + restrct - restriction operator 10874 . dA - fine grid matrix 10875 . interpolate - interpolation operator 10876 . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10877 - fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate 10878 10879 Output Parameter: 10880 . A - the Galerkin coarse matrix 10881 10882 Options Database Key: 10883 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used 10884 10885 Level: developer 10886 10887 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()` 10888 @*/ 10889 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A) 10890 { 10891 IS zerorows; 10892 Vec diag; 10893 10894 PetscFunctionBegin; 10895 PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10896 /* Construct the coarse grid matrix */ 10897 if (interpolate == restrct) { 10898 PetscCall(MatPtAP(dA, interpolate, reuse, fill, A)); 10899 } else { 10900 PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A)); 10901 } 10902 10903 /* If the interpolation matrix is not of full rank, A will have zero rows. 10904 This can legitimately happen in the case of non-nested geometric multigrid. 10905 In that event, we set the rows of the matrix to the rows of the identity, 10906 ignoring the equations (as the RHS will also be zero). */ 10907 10908 PetscCall(MatFindZeroRows(*A, &zerorows)); 10909 10910 if (zerorows != NULL) { /* if there are any zero rows */ 10911 PetscCall(MatCreateVecs(*A, &diag, NULL)); 10912 PetscCall(MatGetDiagonal(*A, diag)); 10913 PetscCall(VecISSet(diag, zerorows, 1.0)); 10914 PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES)); 10915 PetscCall(VecDestroy(&diag)); 10916 PetscCall(ISDestroy(&zerorows)); 10917 } 10918 PetscFunctionReturn(PETSC_SUCCESS); 10919 } 10920 10921 /*@C 10922 MatSetOperation - Allows user to set a matrix operation for any matrix type 10923 10924 Logically Collective 10925 10926 Input Parameters: 10927 + mat - the matrix 10928 . op - the name of the operation 10929 - f - the function that provides the operation 10930 10931 Level: developer 10932 10933 Usage: 10934 .vb 10935 extern PetscErrorCode usermult(Mat, Vec, Vec); 10936 10937 PetscCall(MatCreateXXX(comm, ..., &A)); 10938 PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFunction)usermult)); 10939 .ve 10940 10941 Notes: 10942 See the file `include/petscmat.h` for a complete list of matrix 10943 operations, which all have the form MATOP_<OPERATION>, where 10944 <OPERATION> is the name (in all capital letters) of the 10945 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 10946 10947 All user-provided functions (except for `MATOP_DESTROY`) should have the same calling 10948 sequence as the usual matrix interface routines, since they 10949 are intended to be accessed via the usual matrix interface 10950 routines, e.g., 10951 .vb 10952 MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec) 10953 .ve 10954 10955 In particular each function MUST return `PETSC_SUCCESS` on success and 10956 nonzero on failure. 10957 10958 This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type. 10959 10960 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()` 10961 @*/ 10962 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void)) 10963 { 10964 PetscFunctionBegin; 10965 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10966 if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view; 10967 (((void (**)(void))mat->ops)[op]) = f; 10968 PetscFunctionReturn(PETSC_SUCCESS); 10969 } 10970 10971 /*@C 10972 MatGetOperation - Gets a matrix operation for any matrix type. 10973 10974 Not Collective 10975 10976 Input Parameters: 10977 + mat - the matrix 10978 - op - the name of the operation 10979 10980 Output Parameter: 10981 . f - the function that provides the operation 10982 10983 Level: developer 10984 10985 Usage: 10986 .vb 10987 PetscErrorCode (*usermult)(Mat, Vec, Vec); 10988 MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult); 10989 .ve 10990 10991 Notes: 10992 See the file include/petscmat.h for a complete list of matrix 10993 operations, which all have the form MATOP_<OPERATION>, where 10994 <OPERATION> is the name (in all capital letters) of the 10995 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 10996 10997 This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type. 10998 10999 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()` 11000 @*/ 11001 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void)) 11002 { 11003 PetscFunctionBegin; 11004 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11005 *f = (((void (**)(void))mat->ops)[op]); 11006 PetscFunctionReturn(PETSC_SUCCESS); 11007 } 11008 11009 /*@ 11010 MatHasOperation - Determines whether the given matrix supports the particular operation. 11011 11012 Not Collective 11013 11014 Input Parameters: 11015 + mat - the matrix 11016 - op - the operation, for example, `MATOP_GET_DIAGONAL` 11017 11018 Output Parameter: 11019 . has - either `PETSC_TRUE` or `PETSC_FALSE` 11020 11021 Level: advanced 11022 11023 Note: 11024 See `MatSetOperation()` for additional discussion on naming convention and usage of `op`. 11025 11026 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()` 11027 @*/ 11028 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has) 11029 { 11030 PetscFunctionBegin; 11031 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11032 PetscValidBoolPointer(has, 3); 11033 if (mat->ops->hasoperation) { 11034 PetscUseTypeMethod(mat, hasoperation, op, has); 11035 } else { 11036 if (((void **)mat->ops)[op]) *has = PETSC_TRUE; 11037 else { 11038 *has = PETSC_FALSE; 11039 if (op == MATOP_CREATE_SUBMATRIX) { 11040 PetscMPIInt size; 11041 11042 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 11043 if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has)); 11044 } 11045 } 11046 } 11047 PetscFunctionReturn(PETSC_SUCCESS); 11048 } 11049 11050 /*@ 11051 MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent 11052 11053 Collective 11054 11055 Input Parameter: 11056 . mat - the matrix 11057 11058 Output Parameter: 11059 . cong - either `PETSC_TRUE` or `PETSC_FALSE` 11060 11061 Level: beginner 11062 11063 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout` 11064 @*/ 11065 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong) 11066 { 11067 PetscFunctionBegin; 11068 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11069 PetscValidType(mat, 1); 11070 PetscValidBoolPointer(cong, 2); 11071 if (!mat->rmap || !mat->cmap) { 11072 *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE; 11073 PetscFunctionReturn(PETSC_SUCCESS); 11074 } 11075 if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */ 11076 PetscCall(PetscLayoutSetUp(mat->rmap)); 11077 PetscCall(PetscLayoutSetUp(mat->cmap)); 11078 PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong)); 11079 if (*cong) mat->congruentlayouts = 1; 11080 else mat->congruentlayouts = 0; 11081 } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE; 11082 PetscFunctionReturn(PETSC_SUCCESS); 11083 } 11084 11085 PetscErrorCode MatSetInf(Mat A) 11086 { 11087 PetscFunctionBegin; 11088 PetscUseTypeMethod(A, setinf); 11089 PetscFunctionReturn(PETSC_SUCCESS); 11090 } 11091 11092 /*@C 11093 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 11094 and possibly removes small values from the graph structure. 11095 11096 Collective 11097 11098 Input Parameters: 11099 + A - the matrix 11100 . sym - `PETSC_TRUE` indicates that the graph should be symmetrized 11101 . scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry 11102 - filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value 11103 11104 Output Parameter: 11105 . graph - the resulting graph 11106 11107 Level: advanced 11108 11109 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG` 11110 @*/ 11111 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph) 11112 { 11113 PetscFunctionBegin; 11114 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11115 PetscValidType(A, 1); 11116 PetscValidLogicalCollectiveBool(A, scale, 3); 11117 PetscValidPointer(graph, 5); 11118 PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph); 11119 PetscFunctionReturn(PETSC_SUCCESS); 11120 } 11121 11122 /*@ 11123 MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place, 11124 meaning the same memory is used for the matrix, and no new memory is allocated. 11125 11126 Collective 11127 11128 Input Parameter: 11129 . A - the matrix 11130 11131 Level: intermediate 11132 11133 Developer Note: 11134 The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end 11135 of the arrays in the data structure are unneeded. 11136 11137 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatChop()` 11138 @*/ 11139 PetscErrorCode MatEliminateZeros(Mat A) 11140 { 11141 PetscFunctionBegin; 11142 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11143 PetscUseTypeMethod(A, eliminatezeros); 11144 PetscFunctionReturn(PETSC_SUCCESS); 11145 } 11146