1 /* 2 This is where the abstract matrix operations are defined 3 Portions of this code are under: 4 Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved. 5 */ 6 7 #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/ 8 #include <petsc/private/isimpl.h> 9 #include <petsc/private/vecimpl.h> 10 11 /* Logging support */ 12 PetscClassId MAT_CLASSID; 13 PetscClassId MAT_COLORING_CLASSID; 14 PetscClassId MAT_FDCOLORING_CLASSID; 15 PetscClassId MAT_TRANSPOSECOLORING_CLASSID; 16 17 PetscLogEvent MAT_Mult, MAT_Mults, MAT_MultAdd, MAT_MultTranspose; 18 PetscLogEvent MAT_MultTransposeAdd, MAT_Solve, MAT_Solves, MAT_SolveAdd, MAT_SolveTranspose, MAT_MatSolve, MAT_MatTrSolve; 19 PetscLogEvent MAT_SolveTransposeAdd, MAT_SOR, MAT_ForwardSolve, MAT_BackwardSolve, MAT_LUFactor, MAT_LUFactorSymbolic; 20 PetscLogEvent MAT_LUFactorNumeric, MAT_CholeskyFactor, MAT_CholeskyFactorSymbolic, MAT_CholeskyFactorNumeric, MAT_ILUFactor; 21 PetscLogEvent MAT_ILUFactorSymbolic, MAT_ICCFactorSymbolic, MAT_Copy, MAT_Convert, MAT_Scale, MAT_AssemblyBegin; 22 PetscLogEvent MAT_QRFactorNumeric, MAT_QRFactorSymbolic, MAT_QRFactor; 23 PetscLogEvent MAT_AssemblyEnd, MAT_SetValues, MAT_GetValues, MAT_GetRow, MAT_GetRowIJ, MAT_CreateSubMats, MAT_GetOrdering, MAT_RedundantMat, MAT_GetSeqNonzeroStructure; 24 PetscLogEvent MAT_IncreaseOverlap, MAT_Partitioning, MAT_PartitioningND, MAT_Coarsen, MAT_ZeroEntries, MAT_Load, MAT_View, MAT_AXPY, MAT_FDColoringCreate; 25 PetscLogEvent MAT_FDColoringSetUp, MAT_FDColoringApply, MAT_Transpose, MAT_FDColoringFunction, MAT_CreateSubMat; 26 PetscLogEvent MAT_TransposeColoringCreate; 27 PetscLogEvent MAT_MatMult, MAT_MatMultSymbolic, MAT_MatMultNumeric; 28 PetscLogEvent MAT_PtAP, MAT_PtAPSymbolic, MAT_PtAPNumeric, MAT_RARt, MAT_RARtSymbolic, MAT_RARtNumeric; 29 PetscLogEvent MAT_MatTransposeMult, MAT_MatTransposeMultSymbolic, MAT_MatTransposeMultNumeric; 30 PetscLogEvent MAT_TransposeMatMult, MAT_TransposeMatMultSymbolic, MAT_TransposeMatMultNumeric; 31 PetscLogEvent MAT_MatMatMult, MAT_MatMatMultSymbolic, MAT_MatMatMultNumeric; 32 PetscLogEvent MAT_MultHermitianTranspose, MAT_MultHermitianTransposeAdd; 33 PetscLogEvent MAT_Getsymtranspose, MAT_Getsymtransreduced, MAT_GetBrowsOfAcols; 34 PetscLogEvent MAT_GetBrowsOfAocols, MAT_Getlocalmat, MAT_Getlocalmatcondensed, MAT_Seqstompi, MAT_Seqstompinum, MAT_Seqstompisym; 35 PetscLogEvent MAT_Applypapt, MAT_Applypapt_numeric, MAT_Applypapt_symbolic, MAT_GetSequentialNonzeroStructure; 36 PetscLogEvent MAT_GetMultiProcBlock; 37 PetscLogEvent MAT_CUSPARSECopyToGPU, MAT_CUSPARSECopyFromGPU, MAT_CUSPARSEGenerateTranspose, MAT_CUSPARSESolveAnalysis; 38 PetscLogEvent MAT_HIPSPARSECopyToGPU, MAT_HIPSPARSECopyFromGPU, MAT_HIPSPARSEGenerateTranspose, MAT_HIPSPARSESolveAnalysis; 39 PetscLogEvent MAT_PreallCOO, MAT_SetVCOO; 40 PetscLogEvent MAT_SetValuesBatch; 41 PetscLogEvent MAT_ViennaCLCopyToGPU; 42 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU; 43 PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom; 44 PetscLogEvent MAT_FactorFactS, MAT_FactorInvS; 45 PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights; 46 PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR; 47 48 const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL}; 49 50 /*@ 51 MatSetRandom - Sets all components of a matrix to random numbers. For sparse matrices that have been preallocated but not been assembled it randomly selects appropriate locations, 52 for sparse matrices that already have locations it fills the locations with random numbers 53 54 Logically Collective 55 56 Input Parameters: 57 + x - the matrix 58 - rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or NULL and 59 it will create one internally. 60 61 Output Parameter: 62 . x - the matrix 63 64 Example of Usage: 65 .vb 66 PetscRandomCreate(PETSC_COMM_WORLD,&rctx); 67 MatSetRandom(x,rctx); 68 PetscRandomDestroy(rctx); 69 .ve 70 71 Level: intermediate 72 73 .seealso: `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomCreate()`, `PetscRandomDestroy()` 74 @*/ 75 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx) 76 { 77 PetscRandom randObj = NULL; 78 79 PetscFunctionBegin; 80 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 81 if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2); 82 PetscValidType(x, 1); 83 MatCheckPreallocated(x, 1); 84 85 if (!rctx) { 86 MPI_Comm comm; 87 PetscCall(PetscObjectGetComm((PetscObject)x, &comm)); 88 PetscCall(PetscRandomCreate(comm, &randObj)); 89 PetscCall(PetscRandomSetType(randObj, x->defaultrandtype)); 90 PetscCall(PetscRandomSetFromOptions(randObj)); 91 rctx = randObj; 92 } 93 PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0)); 94 PetscUseTypeMethod(x, setrandom, rctx); 95 PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0)); 96 97 PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY)); 98 PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY)); 99 PetscCall(PetscRandomDestroy(&randObj)); 100 PetscFunctionReturn(PETSC_SUCCESS); 101 } 102 103 /*@ 104 MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in 105 106 Logically Collective 107 108 Input Parameter: 109 . mat - the factored matrix 110 111 Output Parameters: 112 + pivot - the pivot value computed 113 - row - the row that the zero pivot occurred. Note that this row must be interpreted carefully due to row reorderings and which processes 114 the share the matrix 115 116 Level: advanced 117 118 Notes: 119 This routine does not work for factorizations done with external packages. 120 121 This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT` 122 123 This can be called on non-factored matrices that come from, for example, matrices used in SOR. 124 125 .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, 126 `MAT_FACTOR_NUMERIC_ZEROPIVOT` 127 @*/ 128 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row) 129 { 130 PetscFunctionBegin; 131 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 132 PetscValidRealPointer(pivot, 2); 133 PetscValidIntPointer(row, 3); 134 *pivot = mat->factorerror_zeropivot_value; 135 *row = mat->factorerror_zeropivot_row; 136 PetscFunctionReturn(PETSC_SUCCESS); 137 } 138 139 /*@ 140 MatFactorGetError - gets the error code from a factorization 141 142 Logically Collective 143 144 Input Parameters: 145 . mat - the factored matrix 146 147 Output Parameter: 148 . err - the error code 149 150 Level: advanced 151 152 Note: 153 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 154 155 .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, 156 `MatFactorError` 157 @*/ 158 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err) 159 { 160 PetscFunctionBegin; 161 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 162 PetscValidPointer(err, 2); 163 *err = mat->factorerrortype; 164 PetscFunctionReturn(PETSC_SUCCESS); 165 } 166 167 /*@ 168 MatFactorClearError - clears the error code in a factorization 169 170 Logically Collective 171 172 Input Parameter: 173 . mat - the factored matrix 174 175 Level: developer 176 177 Note: 178 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 179 180 .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`, 181 `MatGetErrorCode()`, `MatFactorError` 182 @*/ 183 PetscErrorCode MatFactorClearError(Mat mat) 184 { 185 PetscFunctionBegin; 186 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 187 mat->factorerrortype = MAT_FACTOR_NOERROR; 188 mat->factorerror_zeropivot_value = 0.0; 189 mat->factorerror_zeropivot_row = 0; 190 PetscFunctionReturn(PETSC_SUCCESS); 191 } 192 193 PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero) 194 { 195 Vec r, l; 196 const PetscScalar *al; 197 PetscInt i, nz, gnz, N, n; 198 199 PetscFunctionBegin; 200 PetscCall(MatCreateVecs(mat, &r, &l)); 201 if (!cols) { /* nonzero rows */ 202 PetscCall(MatGetSize(mat, &N, NULL)); 203 PetscCall(MatGetLocalSize(mat, &n, NULL)); 204 PetscCall(VecSet(l, 0.0)); 205 PetscCall(VecSetRandom(r, NULL)); 206 PetscCall(MatMult(mat, r, l)); 207 PetscCall(VecGetArrayRead(l, &al)); 208 } else { /* nonzero columns */ 209 PetscCall(MatGetSize(mat, NULL, &N)); 210 PetscCall(MatGetLocalSize(mat, NULL, &n)); 211 PetscCall(VecSet(r, 0.0)); 212 PetscCall(VecSetRandom(l, NULL)); 213 PetscCall(MatMultTranspose(mat, l, r)); 214 PetscCall(VecGetArrayRead(r, &al)); 215 } 216 if (tol <= 0.0) { 217 for (i = 0, nz = 0; i < n; i++) 218 if (al[i] != 0.0) nz++; 219 } else { 220 for (i = 0, nz = 0; i < n; i++) 221 if (PetscAbsScalar(al[i]) > tol) nz++; 222 } 223 PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 224 if (gnz != N) { 225 PetscInt *nzr; 226 PetscCall(PetscMalloc1(nz, &nzr)); 227 if (nz) { 228 if (tol < 0) { 229 for (i = 0, nz = 0; i < n; i++) 230 if (al[i] != 0.0) nzr[nz++] = i; 231 } else { 232 for (i = 0, nz = 0; i < n; i++) 233 if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i; 234 } 235 } 236 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero)); 237 } else *nonzero = NULL; 238 if (!cols) { /* nonzero rows */ 239 PetscCall(VecRestoreArrayRead(l, &al)); 240 } else { 241 PetscCall(VecRestoreArrayRead(r, &al)); 242 } 243 PetscCall(VecDestroy(&l)); 244 PetscCall(VecDestroy(&r)); 245 PetscFunctionReturn(PETSC_SUCCESS); 246 } 247 248 /*@ 249 MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix 250 251 Input Parameter: 252 . A - the matrix 253 254 Output Parameter: 255 . keptrows - the rows that are not completely zero 256 257 Note: 258 keptrows is set to NULL if all rows are nonzero. 259 260 Level: intermediate 261 262 .seealso: `Mat`, `MatFindZeroRows()` 263 @*/ 264 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows) 265 { 266 PetscFunctionBegin; 267 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 268 PetscValidType(mat, 1); 269 PetscValidPointer(keptrows, 2); 270 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 271 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 272 if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows); 273 else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows)); 274 PetscFunctionReturn(PETSC_SUCCESS); 275 } 276 277 /*@ 278 MatFindZeroRows - Locate all rows that are completely zero in the matrix 279 280 Input Parameter: 281 . A - the matrix 282 283 Output Parameter: 284 . zerorows - the rows that are completely zero 285 286 Note: 287 zerorows is set to NULL if no rows are zero. 288 289 Level: intermediate 290 291 .seealso: `Mat`, `MatFindNonzeroRows()` 292 @*/ 293 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows) 294 { 295 IS keptrows; 296 PetscInt m, n; 297 298 PetscFunctionBegin; 299 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 300 PetscValidType(mat, 1); 301 PetscValidPointer(zerorows, 2); 302 PetscCall(MatFindNonzeroRows(mat, &keptrows)); 303 /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows. 304 In keeping with this convention, we set zerorows to NULL if there are no zero 305 rows. */ 306 if (keptrows == NULL) { 307 *zerorows = NULL; 308 } else { 309 PetscCall(MatGetOwnershipRange(mat, &m, &n)); 310 PetscCall(ISComplement(keptrows, m, n, zerorows)); 311 PetscCall(ISDestroy(&keptrows)); 312 } 313 PetscFunctionReturn(PETSC_SUCCESS); 314 } 315 316 /*@ 317 MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling 318 319 Not Collective 320 321 Input Parameters: 322 . A - the matrix 323 324 Output Parameters: 325 . a - the diagonal part (which is a SEQUENTIAL matrix) 326 327 Notes: 328 See the manual page for `MatCreateAIJ()` for more information on the "diagonal part" of the matrix. 329 330 Use caution, as the reference count on the returned matrix is not incremented and it is used as part of the containing MPI Mat's normal operation. 331 332 Level: advanced 333 334 .seelaso: `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ` 335 @*/ 336 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a) 337 { 338 PetscFunctionBegin; 339 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 340 PetscValidType(A, 1); 341 PetscValidPointer(a, 2); 342 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 343 if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a); 344 else { 345 PetscMPIInt size; 346 347 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 348 PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name); 349 *a = A; 350 } 351 PetscFunctionReturn(PETSC_SUCCESS); 352 } 353 354 /*@ 355 MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries. 356 357 Collective 358 359 Input Parameters: 360 . mat - the matrix 361 362 Output Parameter: 363 . trace - the sum of the diagonal entries 364 365 Level: advanced 366 367 .seealso: `Mat` 368 @*/ 369 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace) 370 { 371 Vec diag; 372 373 PetscFunctionBegin; 374 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 375 PetscValidScalarPointer(trace, 2); 376 PetscCall(MatCreateVecs(mat, &diag, NULL)); 377 PetscCall(MatGetDiagonal(mat, diag)); 378 PetscCall(VecSum(diag, trace)); 379 PetscCall(VecDestroy(&diag)); 380 PetscFunctionReturn(PETSC_SUCCESS); 381 } 382 383 /*@ 384 MatRealPart - Zeros out the imaginary part of the matrix 385 386 Logically Collective 387 388 Input Parameters: 389 . mat - the matrix 390 391 Level: advanced 392 393 .seealso: `MatImaginaryPart()` 394 @*/ 395 PetscErrorCode MatRealPart(Mat mat) 396 { 397 PetscFunctionBegin; 398 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 399 PetscValidType(mat, 1); 400 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 401 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 402 MatCheckPreallocated(mat, 1); 403 PetscUseTypeMethod(mat, realpart); 404 PetscFunctionReturn(PETSC_SUCCESS); 405 } 406 407 /*@C 408 MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix 409 410 Collective 411 412 Input Parameter: 413 . mat - the matrix 414 415 Output Parameters: 416 + nghosts - number of ghosts (note for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each block) 417 - ghosts - the global indices of the ghost points 418 419 Note: 420 the nghosts and ghosts are suitable to pass into `VecCreateGhost()` 421 422 Level: advanced 423 424 .seealso: `Mat`, `VecCreateGhost()` 425 @*/ 426 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[]) 427 { 428 PetscFunctionBegin; 429 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 430 PetscValidType(mat, 1); 431 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 432 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 433 if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts); 434 else { 435 if (nghosts) *nghosts = 0; 436 if (ghosts) *ghosts = NULL; 437 } 438 PetscFunctionReturn(PETSC_SUCCESS); 439 } 440 441 /*@ 442 MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part 443 444 Logically Collective 445 446 Input Parameters: 447 . mat - the matrix 448 449 Level: advanced 450 451 .seealso: `MatRealPart()` 452 @*/ 453 PetscErrorCode MatImaginaryPart(Mat mat) 454 { 455 PetscFunctionBegin; 456 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 457 PetscValidType(mat, 1); 458 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 459 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 460 MatCheckPreallocated(mat, 1); 461 PetscUseTypeMethod(mat, imaginarypart); 462 PetscFunctionReturn(PETSC_SUCCESS); 463 } 464 465 /*@ 466 MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices) 467 468 Not Collective 469 470 Input Parameter: 471 . mat - the matrix 472 473 Output Parameters: 474 + missing - is any diagonal missing 475 - dd - first diagonal entry that is missing (optional) on this process 476 477 Level: advanced 478 479 .seealso: `Mat` 480 @*/ 481 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd) 482 { 483 PetscFunctionBegin; 484 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 485 PetscValidType(mat, 1); 486 PetscValidBoolPointer(missing, 2); 487 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name); 488 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 489 PetscUseTypeMethod(mat, missingdiagonal, missing, dd); 490 PetscFunctionReturn(PETSC_SUCCESS); 491 } 492 493 /*@C 494 MatGetRow - Gets a row of a matrix. You MUST call `MatRestoreRow()` 495 for each row that you get to ensure that your application does 496 not bleed memory. 497 498 Not Collective 499 500 Input Parameters: 501 + mat - the matrix 502 - row - the row to get 503 504 Output Parameters: 505 + ncols - if not NULL, the number of nonzeros in the row 506 . cols - if not NULL, the column numbers 507 - vals - if not NULL, the values 508 509 Notes: 510 This routine is provided for people who need to have direct access 511 to the structure of a matrix. We hope that we provide enough 512 high-level matrix routines that few users will need it. 513 514 `MatGetRow()` always returns 0-based column indices, regardless of 515 whether the internal representation is 0-based (default) or 1-based. 516 517 For better efficiency, set cols and/or vals to NULL if you do 518 not wish to extract these quantities. 519 520 The user can only examine the values extracted with `MatGetRow()`; 521 the values cannot be altered. To change the matrix entries, one 522 must use `MatSetValues()`. 523 524 You can only have one call to `MatGetRow()` outstanding for a particular 525 matrix at a time, per processor. `MatGetRow()` can only obtain rows 526 associated with the given processor, it cannot get rows from the 527 other processors; for that we suggest using `MatCreateSubMatrices()`, then 528 MatGetRow() on the submatrix. The row index passed to `MatGetRow()` 529 is in the global number of rows. 530 531 Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix. 532 533 Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly. 534 535 Fortran Note: 536 The calling sequence from Fortran is 537 .vb 538 MatGetRow(matrix,row,ncols,cols,values,ierr) 539 Mat matrix (input) 540 integer row (input) 541 integer ncols (output) 542 integer cols(maxcols) (output) 543 double precision (or double complex) values(maxcols) output 544 .ve 545 where maxcols >= maximum nonzeros in any row of the matrix. 546 547 Caution: 548 Do not try to change the contents of the output arrays (cols and vals). 549 In some cases, this may corrupt the matrix. 550 551 Level: advanced 552 553 .seealso: `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()` 554 @*/ 555 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 556 { 557 PetscInt incols; 558 559 PetscFunctionBegin; 560 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 561 PetscValidType(mat, 1); 562 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 563 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 564 MatCheckPreallocated(mat, 1); 565 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); 566 PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0)); 567 PetscCall((*mat->ops->getrow)(mat, row, &incols, (PetscInt **)cols, (PetscScalar **)vals)); 568 if (ncols) *ncols = incols; 569 PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0)); 570 PetscFunctionReturn(PETSC_SUCCESS); 571 } 572 573 /*@ 574 MatConjugate - replaces the matrix values with their complex conjugates 575 576 Logically Collective 577 578 Input Parameters: 579 . mat - the matrix 580 581 Level: advanced 582 583 .seealso: `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()` 584 @*/ 585 PetscErrorCode MatConjugate(Mat mat) 586 { 587 PetscFunctionBegin; 588 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 589 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 590 if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) { 591 PetscUseTypeMethod(mat, conjugate); 592 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 593 } 594 PetscFunctionReturn(PETSC_SUCCESS); 595 } 596 597 /*@C 598 MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`. 599 600 Not Collective 601 602 Input Parameters: 603 + mat - the matrix 604 . row - the row to get 605 . ncols, cols - the number of nonzeros and their columns 606 - vals - if nonzero the column values 607 608 Notes: 609 This routine should be called after you have finished examining the entries. 610 611 This routine zeros out ncols, cols, and vals. This is to prevent accidental 612 us of the array after it has been restored. If you pass NULL, it will 613 not zero the pointers. Use of cols or vals after `MatRestoreRow()` is invalid. 614 615 Fortran Notes: 616 The calling sequence from Fortran is 617 .vb 618 MatRestoreRow(matrix,row,ncols,cols,values,ierr) 619 Mat matrix (input) 620 integer row (input) 621 integer ncols (output) 622 integer cols(maxcols) (output) 623 double precision (or double complex) values(maxcols) output 624 .ve 625 Where maxcols >= maximum nonzeros in any row of the matrix. 626 627 In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()` 628 before another call to `MatGetRow()` can be made. 629 630 Level: advanced 631 632 .seealso: `MatGetRow()` 633 @*/ 634 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 635 { 636 PetscFunctionBegin; 637 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 638 if (ncols) PetscValidIntPointer(ncols, 3); 639 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 640 if (!mat->ops->restorerow) PetscFunctionReturn(PETSC_SUCCESS); 641 PetscCall((*mat->ops->restorerow)(mat, row, ncols, (PetscInt **)cols, (PetscScalar **)vals)); 642 if (ncols) *ncols = 0; 643 if (cols) *cols = NULL; 644 if (vals) *vals = NULL; 645 PetscFunctionReturn(PETSC_SUCCESS); 646 } 647 648 /*@ 649 MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 650 You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag. 651 652 Not Collective 653 654 Input Parameters: 655 . mat - the matrix 656 657 Note: 658 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. 659 660 Level: advanced 661 662 .seealso: `MATSBAIJ`, `MatRestoreRowUpperTriangular()` 663 @*/ 664 PetscErrorCode MatGetRowUpperTriangular(Mat mat) 665 { 666 PetscFunctionBegin; 667 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 668 PetscValidType(mat, 1); 669 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 670 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 671 MatCheckPreallocated(mat, 1); 672 if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS); 673 PetscUseTypeMethod(mat, getrowuppertriangular); 674 PetscFunctionReturn(PETSC_SUCCESS); 675 } 676 677 /*@ 678 MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 679 680 Not Collective 681 682 Input Parameters: 683 . mat - the matrix 684 685 Note: 686 This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`. 687 688 Level: advanced 689 690 .seealso: `MATSBAIJ`, `MatGetRowUpperTriangular()` 691 @*/ 692 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat) 693 { 694 PetscFunctionBegin; 695 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 696 PetscValidType(mat, 1); 697 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 698 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 699 MatCheckPreallocated(mat, 1); 700 if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS); 701 PetscUseTypeMethod(mat, restorerowuppertriangular); 702 PetscFunctionReturn(PETSC_SUCCESS); 703 } 704 705 /*@C 706 MatSetOptionsPrefix - Sets the prefix used for searching for all 707 `Mat` options in the database. 708 709 Logically Collective on A 710 711 Input Parameters: 712 + A - the matrix 713 - prefix - the prefix to prepend to all option names 714 715 Notes: 716 A hyphen (-) must NOT be given at the beginning of the prefix name. 717 The first character of all runtime options is AUTOMATICALLY the hyphen. 718 719 This is NOT used for options for the factorization of the matrix. Normally the 720 prefix is automatically passed in from the PC calling the factorization. To set 721 it directly use `MatSetOptionsPrefixFactor()` 722 723 Level: advanced 724 725 .seealso: `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()` 726 @*/ 727 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[]) 728 { 729 PetscFunctionBegin; 730 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 731 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix)); 732 PetscFunctionReturn(PETSC_SUCCESS); 733 } 734 735 /*@C 736 MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for 737 for matrices created with `MatGetFactor()` 738 739 Logically Collective on A 740 741 Input Parameters: 742 + A - the matrix 743 - prefix - the prefix to prepend to all option names for the factored matrix 744 745 Notes: 746 A hyphen (-) must NOT be given at the beginning of the prefix name. 747 The first character of all runtime options is AUTOMATICALLY the hyphen. 748 749 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 750 it directly when not using `KSP`/`PC` use `MatSetOptionsPrefixFactor()` 751 752 Level: developer 753 754 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()` 755 @*/ 756 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[]) 757 { 758 PetscFunctionBegin; 759 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 760 if (prefix) { 761 PetscValidCharPointer(prefix, 2); 762 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 763 if (prefix != A->factorprefix) { 764 PetscCall(PetscFree(A->factorprefix)); 765 PetscCall(PetscStrallocpy(prefix, &A->factorprefix)); 766 } 767 } else PetscCall(PetscFree(A->factorprefix)); 768 PetscFunctionReturn(PETSC_SUCCESS); 769 } 770 771 /*@C 772 MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for 773 for matrices created with `MatGetFactor()` 774 775 Logically Collective on A 776 777 Input Parameters: 778 + A - the matrix 779 - prefix - the prefix to prepend to all option names for the factored matrix 780 781 Notes: 782 A hyphen (-) must NOT be given at the beginning of the prefix name. 783 The first character of all runtime options is AUTOMATICALLY the hyphen. 784 785 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 786 it directly when not using `KSP`/`PC` use `MatAppendOptionsPrefixFactor()` 787 788 Level: developer 789 790 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`, 791 `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`, 792 `MatSetOptionsPrefix()` 793 @*/ 794 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[]) 795 { 796 char *buf = A->factorprefix; 797 size_t len1, len2; 798 799 PetscFunctionBegin; 800 PetscValidHeader(A, 1); 801 if (!prefix) PetscFunctionReturn(PETSC_SUCCESS); 802 if (!buf) { 803 PetscCall(MatSetOptionsPrefixFactor(A, prefix)); 804 PetscFunctionReturn(PETSC_SUCCESS); 805 } 806 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 807 808 PetscCall(PetscStrlen(prefix, &len1)); 809 PetscCall(PetscStrlen(buf, &len2)); 810 PetscCall(PetscMalloc1(1 + len1 + len2, &A->factorprefix)); 811 PetscCall(PetscStrcpy(A->factorprefix, buf)); 812 PetscCall(PetscStrcat(A->factorprefix, prefix)); 813 PetscCall(PetscFree(buf)); 814 PetscFunctionReturn(PETSC_SUCCESS); 815 } 816 817 /*@C 818 MatAppendOptionsPrefix - Appends to the prefix used for searching for all 819 matrix options in the database. 820 821 Logically Collective on A 822 823 Input Parameters: 824 + A - the matrix 825 - prefix - the prefix to prepend to all option names 826 827 Note: 828 A hyphen (-) must NOT be given at the beginning of the prefix name. 829 The first character of all runtime options is AUTOMATICALLY the hyphen. 830 831 Level: advanced 832 833 .seealso: `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()` 834 @*/ 835 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[]) 836 { 837 PetscFunctionBegin; 838 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 839 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix)); 840 PetscFunctionReturn(PETSC_SUCCESS); 841 } 842 843 /*@C 844 MatGetOptionsPrefix - Gets the prefix used for searching for all 845 matrix options in the database. 846 847 Not Collective 848 849 Input Parameter: 850 . A - the matrix 851 852 Output Parameter: 853 . prefix - pointer to the prefix string used 854 855 Level: advanced 856 857 Fortran Note: 858 On the fortran side, the user should pass in a string 'prefix' of 859 sufficient length to hold the prefix. 860 861 .seealso: `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()` 862 @*/ 863 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[]) 864 { 865 PetscFunctionBegin; 866 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 867 PetscValidPointer(prefix, 2); 868 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix)); 869 PetscFunctionReturn(PETSC_SUCCESS); 870 } 871 872 /*@ 873 MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by users. 874 875 Collective on A 876 877 Input Parameters: 878 . A - the matrix 879 880 Notes: 881 The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`. 882 883 Users can reset the preallocation to access the original memory. 884 885 Currently only supported for `MATMPIAIJ` and `MATSEQAIJ` matrices. 886 887 Level: beginner 888 889 .seealso: `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()` 890 @*/ 891 PetscErrorCode MatResetPreallocation(Mat A) 892 { 893 PetscFunctionBegin; 894 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 895 PetscValidType(A, 1); 896 PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A)); 897 PetscFunctionReturn(PETSC_SUCCESS); 898 } 899 900 /*@ 901 MatSetUp - Sets up the internal matrix data structures for later use. 902 903 Collective on A 904 905 Input Parameters: 906 . A - the matrix 907 908 Notes: 909 If the user has not set preallocation for this matrix then a default preallocation that is likely to be inefficient is used. 910 911 If a suitable preallocation routine is used, this function does not need to be called. 912 913 See the Performance chapter of the PETSc users manual for how to preallocate matrices 914 915 This routine is called internally by other matrix functions when needed so rarely needs to be called by users 916 917 Level: intermediate 918 919 .seealso: `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()` 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 && A->ops->setup) { 932 PetscCall(PetscInfo(A, "Warning not preallocating matrix storage\n")); 933 PetscUseTypeMethod(A, setup); 934 } 935 PetscCall(PetscLayoutSetUp(A->rmap)); 936 PetscCall(PetscLayoutSetUp(A->cmap)); 937 A->preallocated = PETSC_TRUE; 938 PetscFunctionReturn(PETSC_SUCCESS); 939 } 940 941 #if defined(PETSC_HAVE_SAWS) 942 #include <petscviewersaws.h> 943 #endif 944 945 /*@C 946 MatViewFromOptions - View properties of the matrix from the options database 947 948 Collective on A 949 950 Input Parameters: 951 + A - the matrix 952 . obj - optional additional object that provides the options prefix to use 953 - name - command line option 954 955 Options Database Key: 956 . -mat_view [viewertype]:... - the viewer and its options 957 958 Notes: 959 .vb 960 If no value is provided ascii:stdout is used 961 ascii[:[filename][:[format][:append]]] defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab, 962 for example ascii::ascii_info prints just the information about the object not all details 963 unless :append is given filename opens in write mode, overwriting what was already there 964 binary[:[filename][:[format][:append]]] defaults to the file binaryoutput 965 draw[:drawtype[:filename]] for example, draw:tikz, draw:tikz:figure.tex or draw:x 966 socket[:port] defaults to the standard output port 967 saws[:communicatorname] publishes object to the Scientific Application Webserver (SAWs) 968 .ve 969 970 Level: intermediate 971 972 .seealso: `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()` 973 @*/ 974 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[]) 975 { 976 PetscFunctionBegin; 977 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 978 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 979 PetscFunctionReturn(PETSC_SUCCESS); 980 } 981 982 /*@C 983 MatView - display information about a matrix in a variety ways 984 985 Collective 986 987 Input Parameters: 988 + mat - the matrix 989 - viewer - visualization context 990 991 Notes: 992 The available visualization contexts include 993 + `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices 994 . `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD` 995 . `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm 996 - `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure 997 998 The user can open alternative visualization contexts with 999 + `PetscViewerASCIIOpen()` - Outputs matrix to a specified file 1000 . `PetscViewerBinaryOpen()` - Outputs matrix in binary to a 1001 specified file; corresponding input uses MatLoad() 1002 . `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to 1003 an X window display 1004 - `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer. 1005 Currently only the sequential dense and AIJ 1006 matrix types support the Socket viewer. 1007 1008 The user can call `PetscViewerPushFormat()` to specify the output 1009 format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`, 1010 `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`). Available formats include 1011 + `PETSC_VIEWER_DEFAULT` - default, prints matrix contents 1012 . `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in Matlab format 1013 . `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros 1014 . `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse 1015 format common among all matrix types 1016 . `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific 1017 format (which is in many cases the same as the default) 1018 . `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix 1019 size and structure (not the matrix entries) 1020 - `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about 1021 the matrix structure 1022 1023 Options Database Keys: 1024 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 1025 . -mat_view ::ascii_info_detail - Prints more detailed info 1026 . -mat_view - Prints matrix in ASCII format 1027 . -mat_view ::ascii_matlab - Prints matrix in Matlab format 1028 . -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 1029 . -display <name> - Sets display name (default is host) 1030 . -draw_pause <sec> - Sets number of seconds to pause after display 1031 . -mat_view socket - Sends matrix to socket, can be accessed from Matlab (see Users-Manual: ch_matlab for details) 1032 . -viewer_socket_machine <machine> - 1033 . -viewer_socket_port <port> - 1034 . -mat_view binary - save matrix to file in binary format 1035 - -viewer_binary_filename <name> - 1036 1037 Level: beginner 1038 1039 Notes: 1040 The ASCII viewers are only recommended for small matrices on at most a moderate number of processes, 1041 the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format. 1042 1043 In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer). 1044 1045 See the manual page for `MatLoad()` for the exact format of the binary file when the binary 1046 viewer is used. 1047 1048 See share/petsc/matlab/PetscBinaryRead.m for a Matlab code that can read in the binary file when the binary 1049 viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python. 1050 1051 One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure, 1052 and then use the following mouse functions. 1053 .vb 1054 left mouse: zoom in 1055 middle mouse: zoom out 1056 right mouse: continue with the simulation 1057 .ve 1058 1059 .seealso: `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`, `Mat`, 1060 `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()` 1061 @*/ 1062 PetscErrorCode MatView(Mat mat, PetscViewer viewer) 1063 { 1064 PetscInt rows, cols, rbs, cbs; 1065 PetscBool isascii, isstring, issaws; 1066 PetscViewerFormat format; 1067 PetscMPIInt size; 1068 1069 PetscFunctionBegin; 1070 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1071 PetscValidType(mat, 1); 1072 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer)); 1073 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1074 PetscCheckSameComm(mat, 1, viewer, 2); 1075 1076 PetscCall(PetscViewerGetFormat(viewer, &format)); 1077 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 1078 if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS); 1079 1080 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 1081 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 1082 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws)); 1083 PetscCheck((isascii && (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL)) || !mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "No viewers for factored matrix except ASCII, info, or info_detail"); 1084 1085 PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0)); 1086 if (isascii) { 1087 if (!mat->preallocated) { 1088 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n")); 1089 PetscFunctionReturn(PETSC_SUCCESS); 1090 } 1091 if (!mat->assembled) { 1092 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n")); 1093 PetscFunctionReturn(PETSC_SUCCESS); 1094 } 1095 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer)); 1096 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1097 MatNullSpace nullsp, transnullsp; 1098 1099 PetscCall(PetscViewerASCIIPushTab(viewer)); 1100 PetscCall(MatGetSize(mat, &rows, &cols)); 1101 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1102 if (rbs != 1 || cbs != 1) { 1103 if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs)); 1104 else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs)); 1105 } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols)); 1106 if (mat->factortype) { 1107 MatSolverType solver; 1108 PetscCall(MatFactorGetSolverType(mat, &solver)); 1109 PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver)); 1110 } 1111 if (mat->ops->getinfo) { 1112 MatInfo info; 1113 PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info)); 1114 PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated)); 1115 if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs)); 1116 } 1117 PetscCall(MatGetNullSpace(mat, &nullsp)); 1118 PetscCall(MatGetTransposeNullSpace(mat, &transnullsp)); 1119 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached null space\n")); 1120 if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached transposed null space\n")); 1121 PetscCall(MatGetNearNullSpace(mat, &nullsp)); 1122 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached near null space\n")); 1123 PetscCall(PetscViewerASCIIPushTab(viewer)); 1124 PetscCall(MatProductView(mat, viewer)); 1125 PetscCall(PetscViewerASCIIPopTab(viewer)); 1126 } 1127 } else if (issaws) { 1128 #if defined(PETSC_HAVE_SAWS) 1129 PetscMPIInt rank; 1130 1131 PetscCall(PetscObjectName((PetscObject)mat)); 1132 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 1133 if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer)); 1134 #endif 1135 } else if (isstring) { 1136 const char *type; 1137 PetscCall(MatGetType(mat, &type)); 1138 PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type)); 1139 PetscTryTypeMethod(mat, view, viewer); 1140 } 1141 if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) { 1142 PetscCall(PetscViewerASCIIPushTab(viewer)); 1143 PetscUseTypeMethod(mat, viewnative, viewer); 1144 PetscCall(PetscViewerASCIIPopTab(viewer)); 1145 } else if (mat->ops->view) { 1146 PetscCall(PetscViewerASCIIPushTab(viewer)); 1147 PetscUseTypeMethod(mat, view, viewer); 1148 PetscCall(PetscViewerASCIIPopTab(viewer)); 1149 } 1150 if (isascii) { 1151 PetscCall(PetscViewerGetFormat(viewer, &format)); 1152 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer)); 1153 } 1154 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1155 PetscFunctionReturn(PETSC_SUCCESS); 1156 } 1157 1158 #if defined(PETSC_USE_DEBUG) 1159 #include <../src/sys/totalview/tv_data_display.h> 1160 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat) 1161 { 1162 TV_add_row("Local rows", "int", &mat->rmap->n); 1163 TV_add_row("Local columns", "int", &mat->cmap->n); 1164 TV_add_row("Global rows", "int", &mat->rmap->N); 1165 TV_add_row("Global columns", "int", &mat->cmap->N); 1166 TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name); 1167 return TV_format_OK; 1168 } 1169 #endif 1170 1171 /*@C 1172 MatLoad - Loads a matrix that has been stored in binary/HDF5 format 1173 with `MatView()`. The matrix format is determined from the options database. 1174 Generates a parallel MPI matrix if the communicator has more than one 1175 processor. The default matrix type is `MATAIJ`. 1176 1177 Collective 1178 1179 Input Parameters: 1180 + mat - the newly loaded matrix, this needs to have been created with `MatCreate()` 1181 or some related function before a call to `MatLoad()` 1182 - viewer - binary/HDF5 file viewer 1183 1184 Options Database Keys: 1185 Used with block matrix formats (`MATSEQBAIJ`, ...) to specify 1186 block size 1187 . -matload_block_size <bs> - set block size 1188 1189 Level: beginner 1190 1191 Notes: 1192 If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the 1193 `Mat` before calling this routine if you wish to set it from the options database. 1194 1195 `MatLoad()` automatically loads into the options database any options 1196 given in the file filename.info where filename is the name of the file 1197 that was passed to the `PetscViewerBinaryOpen()`. The options in the info 1198 file will be ignored if you use the -viewer_binary_skip_info option. 1199 1200 If the type or size of mat is not set before a call to `MatLoad()`, PETSc 1201 sets the default matrix type AIJ and sets the local and global sizes. 1202 If type and/or size is already set, then the same are used. 1203 1204 In parallel, each processor can load a subset of rows (or the 1205 entire matrix). This routine is especially useful when a large 1206 matrix is stored on disk and only part of it is desired on each 1207 processor. For example, a parallel solver may access only some of 1208 the rows from each processor. The algorithm used here reads 1209 relatively small blocks of data rather than reading the entire 1210 matrix and then subsetting it. 1211 1212 Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`. 1213 Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`, 1214 or the sequence like 1215 .vb 1216 `PetscViewer` v; 1217 `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v); 1218 `PetscViewerSetType`(v,`PETSCVIEWERBINARY`); 1219 `PetscViewerSetFromOptions`(v); 1220 `PetscViewerFileSetMode`(v,`FILE_MODE_READ`); 1221 `PetscViewerFileSetName`(v,"datafile"); 1222 .ve 1223 The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option 1224 $ -viewer_type {binary,hdf5} 1225 1226 See the example src/ksp/ksp/tutorials/ex27.c with the first approach, 1227 and src/mat/tutorials/ex10.c with the second approach. 1228 1229 Notes about the PETSc binary format: 1230 In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks 1231 is read onto rank 0 and then shipped to its destination rank, one after another. 1232 Multiple objects, both matrices and vectors, can be stored within the same file. 1233 Their PetscObject name is ignored; they are loaded in the order of their storage. 1234 1235 Most users should not need to know the details of the binary storage 1236 format, since `MatLoad()` and `MatView()` completely hide these details. 1237 But for anyone who's interested, the standard binary matrix storage 1238 format is 1239 1240 $ PetscInt MAT_FILE_CLASSID 1241 $ PetscInt number of rows 1242 $ PetscInt number of columns 1243 $ PetscInt total number of nonzeros 1244 $ PetscInt *number nonzeros in each row 1245 $ PetscInt *column indices of all nonzeros (starting index is zero) 1246 $ PetscScalar *values of all nonzeros 1247 1248 PETSc automatically does the byte swapping for 1249 machines that store the bytes reversed, e.g. DEC alpha, freebsd, 1250 Linux, Microsoft Windows and the Intel Paragon; thus if you write your own binary 1251 read/write routines you have to swap the bytes; see `PetscBinaryRead()` 1252 and `PetscBinaryWrite()` to see how this may be done. 1253 1254 Notes about the HDF5 (MATLAB MAT-File Version 7.3) format: 1255 In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used. 1256 Each processor's chunk is loaded independently by its owning rank. 1257 Multiple objects, both matrices and vectors, can be stored within the same file. 1258 They are looked up by their PetscObject name. 1259 1260 As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use 1261 by default the same structure and naming of the AIJ arrays and column count 1262 within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g. 1263 $ save example.mat A b -v7.3 1264 can be directly read by this routine (see Reference 1 for details). 1265 Note that depending on your MATLAB version, this format might be a default, 1266 otherwise you can set it as default in Preferences. 1267 1268 Unless -nocompression flag is used to save the file in MATLAB, 1269 PETSc must be configured with ZLIB package. 1270 1271 See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c 1272 1273 Current HDF5 (MAT-File) limitations: 1274 This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices. 1275 1276 Corresponding `MatView()` is not yet implemented. 1277 1278 The loaded matrix is actually a transpose of the original one in MATLAB, 1279 unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above). 1280 With this format, matrix is automatically transposed by PETSc, 1281 unless the matrix is marked as SPD or symmetric 1282 (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`). 1283 1284 References: 1285 . * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version 1286 1287 .seealso: `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()` 1288 @*/ 1289 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer) 1290 { 1291 PetscBool flg; 1292 1293 PetscFunctionBegin; 1294 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1295 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1296 1297 if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ)); 1298 1299 flg = PETSC_FALSE; 1300 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL)); 1301 if (flg) { 1302 PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE)); 1303 PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE)); 1304 } 1305 flg = PETSC_FALSE; 1306 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL)); 1307 if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE)); 1308 1309 PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0)); 1310 PetscUseTypeMethod(mat, load, viewer); 1311 PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0)); 1312 PetscFunctionReturn(PETSC_SUCCESS); 1313 } 1314 1315 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant) 1316 { 1317 Mat_Redundant *redund = *redundant; 1318 1319 PetscFunctionBegin; 1320 if (redund) { 1321 if (redund->matseq) { /* via MatCreateSubMatrices() */ 1322 PetscCall(ISDestroy(&redund->isrow)); 1323 PetscCall(ISDestroy(&redund->iscol)); 1324 PetscCall(MatDestroySubMatrices(1, &redund->matseq)); 1325 } else { 1326 PetscCall(PetscFree2(redund->send_rank, redund->recv_rank)); 1327 PetscCall(PetscFree(redund->sbuf_j)); 1328 PetscCall(PetscFree(redund->sbuf_a)); 1329 for (PetscInt i = 0; i < redund->nrecvs; i++) { 1330 PetscCall(PetscFree(redund->rbuf_j[i])); 1331 PetscCall(PetscFree(redund->rbuf_a[i])); 1332 } 1333 PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a)); 1334 } 1335 1336 if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm)); 1337 PetscCall(PetscFree(redund)); 1338 } 1339 PetscFunctionReturn(PETSC_SUCCESS); 1340 } 1341 1342 /*@C 1343 MatDestroy - Frees space taken by a matrix. 1344 1345 Collective on A 1346 1347 Input Parameter: 1348 . A - the matrix 1349 1350 Level: beginner 1351 1352 Developer Note: 1353 Some special arrays of matrices are not destroyed in this routine but instead by the routines called by 1354 `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines. 1355 `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes 1356 if changes are needed here. 1357 1358 .seealso: `Mat`, `MatCreate()` 1359 @*/ 1360 PetscErrorCode MatDestroy(Mat *A) 1361 { 1362 PetscFunctionBegin; 1363 if (!*A) PetscFunctionReturn(PETSC_SUCCESS); 1364 PetscValidHeaderSpecific(*A, MAT_CLASSID, 1); 1365 if (--((PetscObject)(*A))->refct > 0) { 1366 *A = NULL; 1367 PetscFunctionReturn(PETSC_SUCCESS); 1368 } 1369 1370 /* if memory was published with SAWs then destroy it */ 1371 PetscCall(PetscObjectSAWsViewOff((PetscObject)*A)); 1372 PetscTryTypeMethod((*A), destroy); 1373 1374 PetscCall(PetscFree((*A)->factorprefix)); 1375 PetscCall(PetscFree((*A)->defaultvectype)); 1376 PetscCall(PetscFree((*A)->defaultrandtype)); 1377 PetscCall(PetscFree((*A)->bsizes)); 1378 PetscCall(PetscFree((*A)->solvertype)); 1379 for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i])); 1380 if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL; 1381 PetscCall(MatDestroy_Redundant(&(*A)->redundant)); 1382 PetscCall(MatProductClear(*A)); 1383 PetscCall(MatNullSpaceDestroy(&(*A)->nullsp)); 1384 PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp)); 1385 PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp)); 1386 PetscCall(MatDestroy(&(*A)->schur)); 1387 PetscCall(PetscLayoutDestroy(&(*A)->rmap)); 1388 PetscCall(PetscLayoutDestroy(&(*A)->cmap)); 1389 PetscCall(PetscHeaderDestroy(A)); 1390 PetscFunctionReturn(PETSC_SUCCESS); 1391 } 1392 1393 /*@C 1394 MatSetValues - Inserts or adds a block of values into a matrix. 1395 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1396 MUST be called after all calls to `MatSetValues()` have been completed. 1397 1398 Not Collective 1399 1400 Input Parameters: 1401 + mat - the matrix 1402 . v - a logically two-dimensional array of values 1403 . m, idxm - the number of rows and their global indices 1404 . n, idxn - the number of columns and their global indices 1405 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1406 1407 Notes: 1408 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 1409 `MatSetUp()` before using this routine 1410 1411 By default the values, v, are row-oriented. See `MatSetOption()` for other options. 1412 1413 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1414 options cannot be mixed without intervening calls to the assembly 1415 routines. 1416 1417 `MatSetValues()` uses 0-based row and column numbers in Fortran 1418 as well as in C. 1419 1420 Negative indices may be passed in idxm and idxn, these rows and columns are 1421 simply ignored. This allows easily inserting element stiffness matrices 1422 with homogeneous Dirchlet boundary conditions that you don't want represented 1423 in the matrix. 1424 1425 Efficiency Alert: 1426 The routine `MatSetValuesBlocked()` may offer much better efficiency 1427 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1428 1429 Level: beginner 1430 1431 Developer Note: 1432 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1433 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1434 1435 .seealso: `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1436 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1437 @*/ 1438 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1439 { 1440 PetscFunctionBeginHot; 1441 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1442 PetscValidType(mat, 1); 1443 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1444 PetscValidIntPointer(idxm, 3); 1445 PetscValidIntPointer(idxn, 5); 1446 MatCheckPreallocated(mat, 1); 1447 1448 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1449 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1450 1451 if (PetscDefined(USE_DEBUG)) { 1452 PetscInt i, j; 1453 1454 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1455 for (i = 0; i < m; i++) { 1456 for (j = 0; j < n; j++) { 1457 if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j])) 1458 #if defined(PETSC_USE_COMPLEX) 1459 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Inserting %g+i%g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")", (double)PetscRealPart(v[i * n + j]), (double)PetscImaginaryPart(v[i * n + j]), idxm[i], idxn[j]); 1460 #else 1461 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Inserting %g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")", (double)v[i * n + j], idxm[i], idxn[j]); 1462 #endif 1463 } 1464 } 1465 for (i = 0; i < m; i++) PetscCheck(idxm[i] < mat->rmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot insert in row %" PetscInt_FMT ", maximum is %" PetscInt_FMT, idxm[i], mat->rmap->N - 1); 1466 for (i = 0; i < n; i++) PetscCheck(idxn[i] < mat->cmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot insert in column %" PetscInt_FMT ", maximum is %" PetscInt_FMT, idxn[i], mat->cmap->N - 1); 1467 } 1468 1469 if (mat->assembled) { 1470 mat->was_assembled = PETSC_TRUE; 1471 mat->assembled = PETSC_FALSE; 1472 } 1473 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1474 PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv); 1475 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1476 PetscFunctionReturn(PETSC_SUCCESS); 1477 } 1478 1479 /*@C 1480 MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns 1481 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1482 MUST be called after all calls to `MatSetValues()` have been completed. 1483 1484 Not Collective 1485 1486 Input Parameters: 1487 + mat - the matrix 1488 . v - a logically two-dimensional array of values 1489 . ism - the rows to provide 1490 . isn - the columns to provide 1491 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1492 1493 Level: beginner 1494 1495 Notes: 1496 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 1497 `MatSetUp()` before using this routine 1498 1499 By default the values, v, are row-oriented. See `MatSetOption()` for other options. 1500 1501 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1502 options cannot be mixed without intervening calls to the assembly 1503 routines. 1504 1505 `MatSetValues()` uses 0-based row and column numbers in Fortran 1506 as well as in C. 1507 1508 Negative indices may be passed in ism and isn, these rows and columns are 1509 simply ignored. This allows easily inserting element stiffness matrices 1510 with homogeneous Dirchlet boundary conditions that you don't want represented 1511 in the matrix. 1512 1513 Efficiency Alert: 1514 The routine `MatSetValuesBlocked()` may offer much better efficiency 1515 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1516 1517 This is currently not optimized for any particular `ISType` 1518 1519 Developer Notes: 1520 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1521 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1522 1523 .seealso: `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1524 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()` 1525 @*/ 1526 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv) 1527 { 1528 PetscInt m, n; 1529 const PetscInt *rows, *cols; 1530 1531 PetscFunctionBeginHot; 1532 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1533 PetscCall(ISGetIndices(ism, &rows)); 1534 PetscCall(ISGetIndices(isn, &cols)); 1535 PetscCall(ISGetLocalSize(ism, &m)); 1536 PetscCall(ISGetLocalSize(isn, &n)); 1537 PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv)); 1538 PetscCall(ISRestoreIndices(ism, &rows)); 1539 PetscCall(ISRestoreIndices(isn, &cols)); 1540 PetscFunctionReturn(PETSC_SUCCESS); 1541 } 1542 1543 /*@ 1544 MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1545 values into a matrix 1546 1547 Not Collective 1548 1549 Input Parameters: 1550 + mat - the matrix 1551 . row - the (block) row to set 1552 - v - a logically two-dimensional array of values 1553 1554 Notes: 1555 By the values, v, are column-oriented (for the block version) and sorted 1556 1557 All the nonzeros in the row must be provided 1558 1559 The matrix must have previously had its column indices set 1560 1561 The row must belong to this process 1562 1563 Level: intermediate 1564 1565 .seealso: `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1566 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()` 1567 @*/ 1568 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[]) 1569 { 1570 PetscInt globalrow; 1571 1572 PetscFunctionBegin; 1573 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1574 PetscValidType(mat, 1); 1575 PetscValidScalarPointer(v, 3); 1576 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow)); 1577 PetscCall(MatSetValuesRow(mat, globalrow, v)); 1578 PetscFunctionReturn(PETSC_SUCCESS); 1579 } 1580 1581 /*@ 1582 MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1583 values into a matrix 1584 1585 Not Collective 1586 1587 Input Parameters: 1588 + mat - the matrix 1589 . row - the (block) row to set 1590 - 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 1591 1592 Notes: 1593 The values, v, are column-oriented for the block version. 1594 1595 All the nonzeros in the row must be provided 1596 1597 THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used. 1598 1599 The row must belong to this process 1600 1601 Level: advanced 1602 1603 .seealso: `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1604 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()` 1605 @*/ 1606 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[]) 1607 { 1608 PetscFunctionBeginHot; 1609 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1610 PetscValidType(mat, 1); 1611 MatCheckPreallocated(mat, 1); 1612 PetscValidScalarPointer(v, 3); 1613 PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values"); 1614 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1615 mat->insertmode = INSERT_VALUES; 1616 1617 if (mat->assembled) { 1618 mat->was_assembled = PETSC_TRUE; 1619 mat->assembled = PETSC_FALSE; 1620 } 1621 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1622 PetscUseTypeMethod(mat, setvaluesrow, row, v); 1623 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1624 PetscFunctionReturn(PETSC_SUCCESS); 1625 } 1626 1627 /*@ 1628 MatSetValuesStencil - Inserts or adds a block of values into a matrix. 1629 Using structured grid indexing 1630 1631 Not Collective 1632 1633 Input Parameters: 1634 + mat - the matrix 1635 . m - number of rows being entered 1636 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered 1637 . n - number of columns being entered 1638 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered 1639 . v - a logically two-dimensional array of values 1640 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values 1641 1642 Level: beginner 1643 1644 Notes: 1645 By default the values, v, are row-oriented. See `MatSetOption()` for other options. 1646 1647 Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1648 options cannot be mixed without intervening calls to the assembly 1649 routines. 1650 1651 The grid coordinates are across the entire grid, not just the local portion 1652 1653 `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran 1654 as well as in C. 1655 1656 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1657 1658 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1659 or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1660 1661 The columns and rows in the stencil passed in MUST be contained within the 1662 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1663 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1664 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1665 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1666 1667 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 1668 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 1669 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 1670 `DM_BOUNDARY_PERIODIC` boundary type. 1671 1672 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 1673 a single value per point) you can skip filling those indices. 1674 1675 Inspired by the structured grid interface to the HYPRE package 1676 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1677 1678 Efficiency Alert: 1679 The routine `MatSetValuesBlockedStencil()` may offer much better efficiency 1680 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1681 1682 Fortran Note: 1683 In Fortran idxm and idxn should be declared as 1684 $ MatStencil idxm(4,m),idxn(4,n) 1685 and the values inserted using 1686 .vb 1687 idxm(MatStencil_i,1) = i 1688 idxm(MatStencil_j,1) = j 1689 idxm(MatStencil_k,1) = k 1690 idxm(MatStencil_c,1) = c 1691 etc 1692 .ve 1693 1694 .seealso: `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1695 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil` 1696 @*/ 1697 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1698 { 1699 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1700 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1701 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1702 1703 PetscFunctionBegin; 1704 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1705 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1706 PetscValidType(mat, 1); 1707 PetscValidPointer(idxm, 3); 1708 PetscValidPointer(idxn, 5); 1709 1710 if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 1711 jdxm = buf; 1712 jdxn = buf + m; 1713 } else { 1714 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1715 jdxm = bufm; 1716 jdxn = bufn; 1717 } 1718 for (i = 0; i < m; i++) { 1719 for (j = 0; j < 3 - sdim; j++) dxm++; 1720 tmp = *dxm++ - starts[0]; 1721 for (j = 0; j < dim - 1; j++) { 1722 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1723 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1724 } 1725 if (mat->stencil.noc) dxm++; 1726 jdxm[i] = tmp; 1727 } 1728 for (i = 0; i < n; i++) { 1729 for (j = 0; j < 3 - sdim; j++) dxn++; 1730 tmp = *dxn++ - starts[0]; 1731 for (j = 0; j < dim - 1; j++) { 1732 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1733 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1734 } 1735 if (mat->stencil.noc) dxn++; 1736 jdxn[i] = tmp; 1737 } 1738 PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv)); 1739 PetscCall(PetscFree2(bufm, bufn)); 1740 PetscFunctionReturn(PETSC_SUCCESS); 1741 } 1742 1743 /*@ 1744 MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix. 1745 Using structured grid indexing 1746 1747 Not Collective 1748 1749 Input Parameters: 1750 + mat - the matrix 1751 . m - number of rows being entered 1752 . idxm - grid coordinates for matrix rows being entered 1753 . n - number of columns being entered 1754 . idxn - grid coordinates for matrix columns being entered 1755 . v - a logically two-dimensional array of values 1756 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values 1757 1758 Level: beginner 1759 1760 Notes: 1761 By default the values, v, are row-oriented and unsorted. 1762 See `MatSetOption()` for other options. 1763 1764 Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1765 options cannot be mixed without intervening calls to the assembly 1766 routines. 1767 1768 The grid coordinates are across the entire grid, not just the local portion 1769 1770 `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran 1771 as well as in C. 1772 1773 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1774 1775 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1776 or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1777 1778 The columns and rows in the stencil passed in MUST be contained within the 1779 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1780 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1781 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1782 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1783 1784 Negative indices may be passed in idxm and idxn, these rows and columns are 1785 simply ignored. This allows easily inserting element stiffness matrices 1786 with homogeneous Dirchlet boundary conditions that you don't want represented 1787 in the matrix. 1788 1789 Inspired by the structured grid interface to the HYPRE package 1790 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1791 1792 Fortran Note: 1793 In Fortran idxm and idxn should be declared as 1794 $ MatStencil idxm(4,m),idxn(4,n) 1795 and the values inserted using 1796 .vb 1797 idxm(MatStencil_i,1) = i 1798 idxm(MatStencil_j,1) = j 1799 idxm(MatStencil_k,1) = k 1800 etc 1801 .ve 1802 1803 .seealso: `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1804 `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`, 1805 `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` 1806 @*/ 1807 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1808 { 1809 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1810 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1811 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1812 1813 PetscFunctionBegin; 1814 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1815 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1816 PetscValidType(mat, 1); 1817 PetscValidPointer(idxm, 3); 1818 PetscValidPointer(idxn, 5); 1819 PetscValidScalarPointer(v, 6); 1820 1821 if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 1822 jdxm = buf; 1823 jdxn = buf + m; 1824 } else { 1825 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1826 jdxm = bufm; 1827 jdxn = bufn; 1828 } 1829 for (i = 0; i < m; i++) { 1830 for (j = 0; j < 3 - sdim; j++) dxm++; 1831 tmp = *dxm++ - starts[0]; 1832 for (j = 0; j < sdim - 1; j++) { 1833 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1834 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1835 } 1836 dxm++; 1837 jdxm[i] = tmp; 1838 } 1839 for (i = 0; i < n; i++) { 1840 for (j = 0; j < 3 - sdim; j++) dxn++; 1841 tmp = *dxn++ - starts[0]; 1842 for (j = 0; j < sdim - 1; j++) { 1843 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1844 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1845 } 1846 dxn++; 1847 jdxn[i] = tmp; 1848 } 1849 PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv)); 1850 PetscCall(PetscFree2(bufm, bufn)); 1851 PetscFunctionReturn(PETSC_SUCCESS); 1852 } 1853 1854 /*@ 1855 MatSetStencil - Sets the grid information for setting values into a matrix via 1856 `MatSetValuesStencil()` 1857 1858 Not Collective 1859 1860 Input Parameters: 1861 + mat - the matrix 1862 . dim - dimension of the grid 1, 2, or 3 1863 . dims - number of grid points in x, y, and z direction, including ghost points on your processor 1864 . starts - starting point of ghost nodes on your processor in x, y, and z direction 1865 - dof - number of degrees of freedom per node 1866 1867 Notes: 1868 Inspired by the structured grid interface to the HYPRE package 1869 (www.llnl.gov/CASC/hyper) 1870 1871 For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the 1872 user. 1873 1874 Level: beginner 1875 1876 .seealso: `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1877 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()` 1878 @*/ 1879 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof) 1880 { 1881 PetscFunctionBegin; 1882 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1883 PetscValidIntPointer(dims, 3); 1884 PetscValidIntPointer(starts, 4); 1885 1886 mat->stencil.dim = dim + (dof > 1); 1887 for (PetscInt i = 0; i < dim; i++) { 1888 mat->stencil.dims[i] = dims[dim - i - 1]; /* copy the values in backwards */ 1889 mat->stencil.starts[i] = starts[dim - i - 1]; 1890 } 1891 mat->stencil.dims[dim] = dof; 1892 mat->stencil.starts[dim] = 0; 1893 mat->stencil.noc = (PetscBool)(dof == 1); 1894 PetscFunctionReturn(PETSC_SUCCESS); 1895 } 1896 1897 /*@C 1898 MatSetValuesBlocked - Inserts or adds a block of values into a matrix. 1899 1900 Not Collective 1901 1902 Input Parameters: 1903 + mat - the matrix 1904 . v - a logically two-dimensional array of values 1905 . m, idxm - the number of block rows and their global block indices 1906 . n, idxn - the number of block columns and their global block indices 1907 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values 1908 1909 Level: intermediate 1910 1911 Notes: 1912 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call 1913 MatXXXXSetPreallocation() or `MatSetUp()` before using this routine. 1914 1915 The m and n count the NUMBER of blocks in the row direction and column direction, 1916 NOT the total number of rows/columns; for example, if the block size is 2 and 1917 you are passing in values for rows 2,3,4,5 then m would be 2 (not 4). 1918 The values in idxm would be 1 2; that is the first index for each block divided by 1919 the block size. 1920 1921 Note that you must call `MatSetBlockSize()` when constructing this matrix (before 1922 preallocating it). 1923 1924 By default the values, v, are row-oriented, so the layout of 1925 v is the same as for `MatSetValues()`. See `MatSetOption()` for other options. 1926 1927 Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES` 1928 options cannot be mixed without intervening calls to the assembly 1929 routines. 1930 1931 `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran 1932 as well as in C. 1933 1934 Negative indices may be passed in idxm and idxn, these rows and columns are 1935 simply ignored. This allows easily inserting element stiffness matrices 1936 with homogeneous Dirchlet boundary conditions that you don't want represented 1937 in the matrix. 1938 1939 Each time an entry is set within a sparse matrix via `MatSetValues()`, 1940 internal searching must be done to determine where to place the 1941 data in the matrix storage space. By instead inserting blocks of 1942 entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is 1943 reduced. 1944 1945 Example: 1946 .vb 1947 Suppose m=n=2 and block size(bs) = 2 The array is 1948 1949 1 2 | 3 4 1950 5 6 | 7 8 1951 - - - | - - - 1952 9 10 | 11 12 1953 13 14 | 15 16 1954 1955 v[] should be passed in like 1956 v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] 1957 1958 If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then 1959 v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16] 1960 .ve 1961 1962 .seealso: `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()` 1963 @*/ 1964 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1965 { 1966 PetscFunctionBeginHot; 1967 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1968 PetscValidType(mat, 1); 1969 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1970 PetscValidIntPointer(idxm, 3); 1971 PetscValidIntPointer(idxn, 5); 1972 MatCheckPreallocated(mat, 1); 1973 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1974 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1975 if (PetscDefined(USE_DEBUG)) { 1976 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1977 PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 1978 } 1979 if (PetscDefined(USE_DEBUG)) { 1980 PetscInt rbs, cbs, M, N, i; 1981 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1982 PetscCall(MatGetSize(mat, &M, &N)); 1983 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); 1984 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); 1985 } 1986 if (mat->assembled) { 1987 mat->was_assembled = PETSC_TRUE; 1988 mat->assembled = PETSC_FALSE; 1989 } 1990 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1991 if (mat->ops->setvaluesblocked) { 1992 PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv); 1993 } else { 1994 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn; 1995 PetscInt i, j, bs, cbs; 1996 1997 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 1998 if (m * bs + n * cbs <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 1999 iidxm = buf; 2000 iidxn = buf + m * bs; 2001 } else { 2002 PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc)); 2003 iidxm = bufr; 2004 iidxn = bufc; 2005 } 2006 for (i = 0; i < m; i++) { 2007 for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j; 2008 } 2009 if (m != n || bs != cbs || idxm != idxn) { 2010 for (i = 0; i < n; i++) { 2011 for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j; 2012 } 2013 } else iidxn = iidxm; 2014 PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv)); 2015 PetscCall(PetscFree2(bufr, bufc)); 2016 } 2017 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2018 PetscFunctionReturn(PETSC_SUCCESS); 2019 } 2020 2021 /*@C 2022 MatGetValues - Gets a block of local values from a matrix. 2023 2024 Not Collective; can only return values that are owned by the give process 2025 2026 Input Parameters: 2027 + mat - the matrix 2028 . v - a logically two-dimensional array for storing the values 2029 . m, idxm - the number of rows and their global indices 2030 - n, idxn - the number of columns and their global indices 2031 2032 Notes: 2033 The user must allocate space (m*n `PetscScalar`s) for the values, v. 2034 The values, v, are then returned in a row-oriented format, 2035 analogous to that used by default in `MatSetValues()`. 2036 2037 `MatGetValues()` uses 0-based row and column numbers in 2038 Fortran as well as in C. 2039 2040 `MatGetValues()` requires that the matrix has been assembled 2041 with `MatAssemblyBegin()`/`MatAssemblyEnd()`. Thus, calls to 2042 `MatSetValues()` and `MatGetValues()` CANNOT be made in succession 2043 without intermediate matrix assembly. 2044 2045 Negative row or column indices will be ignored and those locations in v[] will be 2046 left unchanged. 2047 2048 For the standard row-based matrix formats, idxm[] can only contain rows owned by the requesting MPI rank. 2049 That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable 2050 from `MatGetOwnershipRange`(mat,&rstart,&rend). 2051 2052 Level: advanced 2053 2054 .seealso: `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()` 2055 @*/ 2056 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) 2057 { 2058 PetscFunctionBegin; 2059 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2060 PetscValidType(mat, 1); 2061 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); 2062 PetscValidIntPointer(idxm, 3); 2063 PetscValidIntPointer(idxn, 5); 2064 PetscValidScalarPointer(v, 6); 2065 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2066 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2067 MatCheckPreallocated(mat, 1); 2068 2069 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2070 PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v); 2071 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2072 PetscFunctionReturn(PETSC_SUCCESS); 2073 } 2074 2075 /*@C 2076 MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices 2077 defined previously by `MatSetLocalToGlobalMapping()` 2078 2079 Not Collective 2080 2081 Input Parameters: 2082 + mat - the matrix 2083 . nrow, irow - number of rows and their local indices 2084 - ncol, icol - number of columns and their local indices 2085 2086 Output Parameter: 2087 . y - a logically two-dimensional array of values 2088 2089 Level: advanced 2090 2091 Notes: 2092 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine. 2093 2094 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, 2095 are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can 2096 determine if the resulting global row associated with the local row r is owned by the requesting MPI rank by applying the `ISLocalToGlobalMapping` set 2097 with `MatSetLocalToGlobalMapping()`. 2098 2099 Developer Note: 2100 This is labelled with C so does not automatically generate Fortran stubs and interfaces 2101 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2102 2103 .seealso: `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2104 `MatSetValuesLocal()`, `MatGetValues()` 2105 @*/ 2106 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[]) 2107 { 2108 PetscFunctionBeginHot; 2109 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2110 PetscValidType(mat, 1); 2111 MatCheckPreallocated(mat, 1); 2112 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */ 2113 PetscValidIntPointer(irow, 3); 2114 PetscValidIntPointer(icol, 5); 2115 if (PetscDefined(USE_DEBUG)) { 2116 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2117 PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2118 } 2119 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2120 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2121 if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y); 2122 else { 2123 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm; 2124 if ((nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2125 irowm = buf; 2126 icolm = buf + nrow; 2127 } else { 2128 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2129 irowm = bufr; 2130 icolm = bufc; 2131 } 2132 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping())."); 2133 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping())."); 2134 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm)); 2135 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm)); 2136 PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y)); 2137 PetscCall(PetscFree2(bufr, bufc)); 2138 } 2139 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2140 PetscFunctionReturn(PETSC_SUCCESS); 2141 } 2142 2143 /*@ 2144 MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and 2145 the same size. Currently, this can only be called once and creates the given matrix. 2146 2147 Not Collective 2148 2149 Input Parameters: 2150 + mat - the matrix 2151 . nb - the number of blocks 2152 . bs - the number of rows (and columns) in each block 2153 . rows - a concatenation of the rows for each block 2154 - v - a concatenation of logically two-dimensional arrays of values 2155 2156 Note: 2157 `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values 2158 2159 In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix. 2160 2161 Level: advanced 2162 2163 .seealso: `Mat`, `Mat`MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 2164 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()` 2165 @*/ 2166 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[]) 2167 { 2168 PetscFunctionBegin; 2169 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2170 PetscValidType(mat, 1); 2171 PetscValidIntPointer(rows, 4); 2172 PetscValidScalarPointer(v, 5); 2173 PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2174 2175 PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0)); 2176 if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v); 2177 else { 2178 for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES)); 2179 } 2180 PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0)); 2181 PetscFunctionReturn(PETSC_SUCCESS); 2182 } 2183 2184 /*@ 2185 MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by 2186 the routine `MatSetValuesLocal()` to allow users to insert matrix entries 2187 using a local (per-processor) numbering. 2188 2189 Not Collective 2190 2191 Input Parameters: 2192 + x - the matrix 2193 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()` 2194 - cmapping - column mapping 2195 2196 Level: intermediate 2197 2198 Note: 2199 If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix 2200 2201 .seealso: `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()` 2202 @*/ 2203 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping) 2204 { 2205 PetscFunctionBegin; 2206 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 2207 PetscValidType(x, 1); 2208 if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2); 2209 if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3); 2210 if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping); 2211 else { 2212 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping)); 2213 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping)); 2214 } 2215 PetscFunctionReturn(PETSC_SUCCESS); 2216 } 2217 2218 /*@ 2219 MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()` 2220 2221 Not Collective 2222 2223 Input Parameter: 2224 . A - the matrix 2225 2226 Output Parameters: 2227 + rmapping - row mapping 2228 - cmapping - column mapping 2229 2230 Level: advanced 2231 2232 .seealso: `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()` 2233 @*/ 2234 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping) 2235 { 2236 PetscFunctionBegin; 2237 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2238 PetscValidType(A, 1); 2239 if (rmapping) { 2240 PetscValidPointer(rmapping, 2); 2241 *rmapping = A->rmap->mapping; 2242 } 2243 if (cmapping) { 2244 PetscValidPointer(cmapping, 3); 2245 *cmapping = A->cmap->mapping; 2246 } 2247 PetscFunctionReturn(PETSC_SUCCESS); 2248 } 2249 2250 /*@ 2251 MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix 2252 2253 Logically Collective on A 2254 2255 Input Parameters: 2256 + A - the matrix 2257 . rmap - row layout 2258 - cmap - column layout 2259 2260 Level: advanced 2261 2262 Note: 2263 The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called. 2264 2265 .seealso: `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()` 2266 @*/ 2267 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap) 2268 { 2269 PetscFunctionBegin; 2270 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2271 PetscCall(PetscLayoutReference(rmap, &A->rmap)); 2272 PetscCall(PetscLayoutReference(cmap, &A->cmap)); 2273 PetscFunctionReturn(PETSC_SUCCESS); 2274 } 2275 2276 /*@ 2277 MatGetLayouts - Gets the `PetscLayout` objects for rows and columns 2278 2279 Not Collective 2280 2281 Input Parameter: 2282 . A - the matrix 2283 2284 Output Parameters: 2285 + rmap - row layout 2286 - cmap - column layout 2287 2288 Level: advanced 2289 2290 .seealso: [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()` 2291 @*/ 2292 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap) 2293 { 2294 PetscFunctionBegin; 2295 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2296 PetscValidType(A, 1); 2297 if (rmap) { 2298 PetscValidPointer(rmap, 2); 2299 *rmap = A->rmap; 2300 } 2301 if (cmap) { 2302 PetscValidPointer(cmap, 3); 2303 *cmap = A->cmap; 2304 } 2305 PetscFunctionReturn(PETSC_SUCCESS); 2306 } 2307 2308 /*@C 2309 MatSetValuesLocal - Inserts or adds values into certain locations of a matrix, 2310 using a local numbering of the nodes. 2311 2312 Not Collective 2313 2314 Input Parameters: 2315 + mat - the matrix 2316 . nrow, irow - number of rows and their local indices 2317 . ncol, icol - number of columns and their local indices 2318 . y - a logically two-dimensional array of values 2319 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2320 2321 Notes: 2322 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 2323 `MatSetUp()` before using this routine 2324 2325 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine 2326 2327 Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2328 options cannot be mixed without intervening calls to the assembly 2329 routines. 2330 2331 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2332 MUST be called after all calls to `MatSetValuesLocal()` have been completed. 2333 2334 Level: intermediate 2335 2336 Developer Note: 2337 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2338 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2339 2340 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2341 `MatGetValuesLocal()` 2342 @*/ 2343 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2344 { 2345 PetscFunctionBeginHot; 2346 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2347 PetscValidType(mat, 1); 2348 MatCheckPreallocated(mat, 1); 2349 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2350 PetscValidIntPointer(irow, 3); 2351 PetscValidIntPointer(icol, 5); 2352 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2353 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2354 if (PetscDefined(USE_DEBUG)) { 2355 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2356 PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2357 } 2358 2359 if (mat->assembled) { 2360 mat->was_assembled = PETSC_TRUE; 2361 mat->assembled = PETSC_FALSE; 2362 } 2363 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2364 if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv); 2365 else { 2366 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2367 const PetscInt *irowm, *icolm; 2368 2369 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2370 bufr = buf; 2371 bufc = buf + nrow; 2372 irowm = bufr; 2373 icolm = bufc; 2374 } else { 2375 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2376 irowm = bufr; 2377 icolm = bufc; 2378 } 2379 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr)); 2380 else irowm = irow; 2381 if (mat->cmap->mapping) { 2382 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2383 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc)); 2384 } else icolm = irowm; 2385 } else icolm = icol; 2386 PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv)); 2387 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2388 } 2389 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2390 PetscFunctionReturn(PETSC_SUCCESS); 2391 } 2392 2393 /*@C 2394 MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix, 2395 using a local ordering of the nodes a block at a time. 2396 2397 Not Collective 2398 2399 Input Parameters: 2400 + x - the matrix 2401 . nrow, irow - number of rows and their local indices 2402 . ncol, icol - number of columns and their local indices 2403 . y - a logically two-dimensional array of values 2404 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2405 2406 Notes: 2407 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 2408 `MatSetUp()` before using this routine 2409 2410 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()` 2411 before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the 2412 2413 Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2414 options cannot be mixed without intervening calls to the assembly 2415 routines. 2416 2417 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2418 MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed. 2419 2420 Level: intermediate 2421 2422 Developer Note: 2423 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2424 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2425 2426 .seealso: `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, 2427 `MatSetValuesLocal()`, `MatSetValuesBlocked()` 2428 @*/ 2429 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2430 { 2431 PetscFunctionBeginHot; 2432 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2433 PetscValidType(mat, 1); 2434 MatCheckPreallocated(mat, 1); 2435 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2436 PetscValidIntPointer(irow, 3); 2437 PetscValidIntPointer(icol, 5); 2438 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2439 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2440 if (PetscDefined(USE_DEBUG)) { 2441 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2442 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); 2443 } 2444 2445 if (mat->assembled) { 2446 mat->was_assembled = PETSC_TRUE; 2447 mat->assembled = PETSC_FALSE; 2448 } 2449 if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */ 2450 PetscInt irbs, rbs; 2451 PetscCall(MatGetBlockSizes(mat, &rbs, NULL)); 2452 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs)); 2453 PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs); 2454 } 2455 if (PetscUnlikelyDebug(mat->cmap->mapping)) { 2456 PetscInt icbs, cbs; 2457 PetscCall(MatGetBlockSizes(mat, NULL, &cbs)); 2458 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs)); 2459 PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs); 2460 } 2461 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2462 if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv); 2463 else { 2464 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2465 const PetscInt *irowm, *icolm; 2466 2467 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2468 bufr = buf; 2469 bufc = buf + nrow; 2470 irowm = bufr; 2471 icolm = bufc; 2472 } else { 2473 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2474 irowm = bufr; 2475 icolm = bufc; 2476 } 2477 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr)); 2478 else irowm = irow; 2479 if (mat->cmap->mapping) { 2480 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2481 PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc)); 2482 } else icolm = irowm; 2483 } else icolm = icol; 2484 PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv)); 2485 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2486 } 2487 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2488 PetscFunctionReturn(PETSC_SUCCESS); 2489 } 2490 2491 /*@ 2492 MatMultDiagonalBlock - Computes the matrix-vector product, y = Dx. Where D is defined by the inode or block structure of the diagonal 2493 2494 Collective 2495 2496 Input Parameters: 2497 + mat - the matrix 2498 - x - the vector to be multiplied 2499 2500 Output Parameters: 2501 . y - the result 2502 2503 Note: 2504 The vectors x and y cannot be the same. I.e., one cannot 2505 call `MatMultDiagonalBlock`(A,y,y). 2506 2507 Level: developer 2508 2509 .seealso: `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2510 @*/ 2511 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y) 2512 { 2513 PetscFunctionBegin; 2514 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2515 PetscValidType(mat, 1); 2516 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2517 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2518 2519 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2520 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2521 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2522 MatCheckPreallocated(mat, 1); 2523 2524 PetscUseTypeMethod(mat, multdiagonalblock, x, y); 2525 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2526 PetscFunctionReturn(PETSC_SUCCESS); 2527 } 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 Parameters: 2540 . y - the result 2541 2542 Note: 2543 The vectors x and y cannot be the same. I.e., one cannot 2544 call `MatMult`(A,y,y). 2545 2546 Level: beginner 2547 2548 .seealso: `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 Parameters: 2588 . y - the result 2589 2590 Notes: 2591 The vectors x and y cannot be the same. I.e., one cannot 2592 call `MatMultTranspose`(A,y,y). 2593 2594 For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple, 2595 use `MatMultHermitianTranspose()` 2596 2597 Level: beginner 2598 2599 .seealso: `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 Parameters: 2646 . y - the result 2647 2648 Notes: 2649 The vectors x and y cannot be the same. I.e., one cannot 2650 call `MatMultHermitianTranspose`(A,y,y). 2651 2652 Also called the conjugate transpose, complex conjugate transpose, or adjoint. 2653 2654 For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical. 2655 2656 Level: beginner 2657 2658 .seealso: `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, v2 - the vectors 2709 2710 Output Parameters: 2711 . v3 - the result 2712 2713 Note: 2714 The vectors v1 and v3 cannot be the same. I.e., one cannot 2715 call `MatMultAdd`(A,v1,v2,v1). 2716 2717 Level: beginner 2718 2719 .seealso: `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()` 2720 @*/ 2721 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2722 { 2723 PetscFunctionBegin; 2724 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2725 PetscValidType(mat, 1); 2726 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2727 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2728 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2729 2730 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2731 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2732 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); 2733 /* 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); 2734 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); */ 2735 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); 2736 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); 2737 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2738 MatCheckPreallocated(mat, 1); 2739 2740 PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3)); 2741 PetscCall(VecLockReadPush(v1)); 2742 PetscUseTypeMethod(mat, multadd, v1, v2, v3); 2743 PetscCall(VecLockReadPop(v1)); 2744 PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3)); 2745 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2746 PetscFunctionReturn(PETSC_SUCCESS); 2747 } 2748 2749 /*@ 2750 MatMultTransposeAdd - Computes v3 = v2 + A' * v1. 2751 2752 Neighbor-wise Collective 2753 2754 Input Parameters: 2755 + mat - the matrix 2756 - v1, v2 - the vectors 2757 2758 Output Parameters: 2759 . v3 - the result 2760 2761 Note: 2762 The vectors v1 and v3 cannot be the same. I.e., one cannot 2763 call `MatMultTransposeAdd`(A,v1,v2,v1). 2764 2765 Level: beginner 2766 2767 .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2768 @*/ 2769 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2770 { 2771 PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd; 2772 2773 PetscFunctionBegin; 2774 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2775 PetscValidType(mat, 1); 2776 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2777 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2778 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2779 2780 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2781 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2782 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); 2783 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); 2784 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); 2785 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2786 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2787 MatCheckPreallocated(mat, 1); 2788 2789 PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2790 PetscCall(VecLockReadPush(v1)); 2791 PetscCall((*op)(mat, v1, v2, v3)); 2792 PetscCall(VecLockReadPop(v1)); 2793 PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2794 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2795 PetscFunctionReturn(PETSC_SUCCESS); 2796 } 2797 2798 /*@ 2799 MatMultHermitianTransposeAdd - Computes v3 = v2 + A^H * v1. 2800 2801 Neighbor-wise Collective 2802 2803 Input Parameters: 2804 + mat - the matrix 2805 - v1, v2 - the vectors 2806 2807 Output Parameters: 2808 . v3 - the result 2809 2810 Note: 2811 The vectors v1 and v3 cannot be the same. I.e., one cannot 2812 call `MatMultHermitianTransposeAdd`(A,v1,v2,v1). 2813 2814 Level: beginner 2815 2816 .seealso: `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2817 @*/ 2818 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2819 { 2820 PetscFunctionBegin; 2821 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2822 PetscValidType(mat, 1); 2823 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2824 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2825 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2826 2827 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2828 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2829 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2830 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); 2831 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); 2832 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); 2833 MatCheckPreallocated(mat, 1); 2834 2835 PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2836 PetscCall(VecLockReadPush(v1)); 2837 if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3); 2838 else { 2839 Vec w, z; 2840 PetscCall(VecDuplicate(v1, &w)); 2841 PetscCall(VecCopy(v1, w)); 2842 PetscCall(VecConjugate(w)); 2843 PetscCall(VecDuplicate(v3, &z)); 2844 PetscCall(MatMultTranspose(mat, w, z)); 2845 PetscCall(VecDestroy(&w)); 2846 PetscCall(VecConjugate(z)); 2847 if (v2 != v3) { 2848 PetscCall(VecWAXPY(v3, 1.0, v2, z)); 2849 } else { 2850 PetscCall(VecAXPY(v3, 1.0, z)); 2851 } 2852 PetscCall(VecDestroy(&z)); 2853 } 2854 PetscCall(VecLockReadPop(v1)); 2855 PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2856 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2857 PetscFunctionReturn(PETSC_SUCCESS); 2858 } 2859 2860 /*@C 2861 MatGetFactorType - gets the type of factorization it is 2862 2863 Not Collective 2864 2865 Input Parameters: 2866 . mat - the matrix 2867 2868 Output Parameters: 2869 . 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` 2870 2871 Level: intermediate 2872 2873 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2874 `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2875 @*/ 2876 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t) 2877 { 2878 PetscFunctionBegin; 2879 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2880 PetscValidType(mat, 1); 2881 PetscValidPointer(t, 2); 2882 *t = mat->factortype; 2883 PetscFunctionReturn(PETSC_SUCCESS); 2884 } 2885 2886 /*@C 2887 MatSetFactorType - sets the type of factorization it is 2888 2889 Logically Collective 2890 2891 Input Parameters: 2892 + mat - the matrix 2893 - 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` 2894 2895 Level: intermediate 2896 2897 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2898 `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2899 @*/ 2900 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t) 2901 { 2902 PetscFunctionBegin; 2903 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2904 PetscValidType(mat, 1); 2905 mat->factortype = t; 2906 PetscFunctionReturn(PETSC_SUCCESS); 2907 } 2908 2909 /* ------------------------------------------------------------*/ 2910 /*@C 2911 MatGetInfo - Returns information about matrix storage (number of 2912 nonzeros, memory, etc.). 2913 2914 Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag 2915 2916 Input Parameter: 2917 . mat - the matrix 2918 2919 Output Parameters: 2920 + flag - flag indicating the type of parameters to be returned 2921 (`MAT_LOCAL` - local matrix, `MAT_GLOBAL_MAX` - maximum over all processors, 2922 MAT_GLOBAL_SUM - sum over all processors) 2923 - info - matrix information context 2924 2925 Notes: 2926 The `MatInfo` context contains a variety of matrix data, including 2927 number of nonzeros allocated and used, number of mallocs during 2928 matrix assembly, etc. Additional information for factored matrices 2929 is provided (such as the fill ratio, number of mallocs during 2930 factorization, etc.). Much of this info is printed to `PETSC_STDOUT` 2931 when using the runtime options 2932 $ -info -mat_view ::ascii_info 2933 2934 Example for C/C++ Users: 2935 See the file ${PETSC_DIR}/include/petscmat.h for a complete list of 2936 data within the MatInfo context. For example, 2937 .vb 2938 MatInfo info; 2939 Mat A; 2940 double mal, nz_a, nz_u; 2941 2942 MatGetInfo(A,MAT_LOCAL,&info); 2943 mal = info.mallocs; 2944 nz_a = info.nz_allocated; 2945 .ve 2946 2947 Example for Fortran Users: 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 Fortran interface is not autogenerated as the 2967 interface definition cannot be generated correctly [due to MatInfo] 2968 2969 .seealso: `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 /* ----------------------------------------------------------*/ 2994 2995 /*@C 2996 MatLUFactor - Performs in-place LU factorization of matrix. 2997 2998 Collective 2999 3000 Input Parameters: 3001 + mat - the matrix 3002 . row - row permutation 3003 . col - column permutation 3004 - info - options for factorization, includes 3005 $ fill - expected fill as ratio of original fill. 3006 $ dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3007 $ Run with the option -info to determine an optimal value to use 3008 3009 Notes: 3010 Most users should employ the `KSP` interface for linear solvers 3011 instead of working directly with matrix algebra routines such as this. 3012 See, e.g., `KSPCreate()`. 3013 3014 This changes the state of the matrix to a factored matrix; it cannot be used 3015 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3016 3017 This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()` 3018 when not using `KSP`. 3019 3020 Level: developer 3021 3022 Developer Note: 3023 The Fortran interface is not autogenerated as the 3024 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3025 3026 .seealso: [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, 3027 `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3028 @*/ 3029 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3030 { 3031 MatFactorInfo tinfo; 3032 3033 PetscFunctionBegin; 3034 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3035 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3036 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3037 if (info) PetscValidPointer(info, 4); 3038 PetscValidType(mat, 1); 3039 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3040 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3041 MatCheckPreallocated(mat, 1); 3042 if (!info) { 3043 PetscCall(MatFactorInfoInitialize(&tinfo)); 3044 info = &tinfo; 3045 } 3046 3047 PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0)); 3048 PetscUseTypeMethod(mat, lufactor, row, col, info); 3049 PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0)); 3050 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3051 PetscFunctionReturn(PETSC_SUCCESS); 3052 } 3053 3054 /*@C 3055 MatILUFactor - Performs in-place ILU factorization of matrix. 3056 3057 Collective 3058 3059 Input Parameters: 3060 + mat - the matrix 3061 . row - row permutation 3062 . col - column permutation 3063 - info - structure containing 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 3069 Level: developer 3070 3071 Notes: 3072 Most users should employ the `KSP` interface for linear solvers 3073 instead of working directly with matrix algebra routines such as this. 3074 See, e.g., `KSPCreate()`. 3075 3076 Probably really in-place only when level of fill is zero, otherwise allocates 3077 new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()` 3078 when not using `KSP`. 3079 3080 Developer Note: 3081 The Fortran interface is not autogenerated as the 3082 interface definition cannot be generated correctly [due to MatFactorInfo] 3083 3084 .seealso: [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 3085 @*/ 3086 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3087 { 3088 PetscFunctionBegin; 3089 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3090 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3091 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3092 PetscValidPointer(info, 4); 3093 PetscValidType(mat, 1); 3094 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 3095 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3096 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3097 MatCheckPreallocated(mat, 1); 3098 3099 PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0)); 3100 PetscUseTypeMethod(mat, ilufactor, row, col, info); 3101 PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0)); 3102 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3103 PetscFunctionReturn(PETSC_SUCCESS); 3104 } 3105 3106 /*@C 3107 MatLUFactorSymbolic - Performs symbolic LU factorization of matrix. 3108 Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`. 3109 3110 Collective on fact 3111 3112 Input Parameters: 3113 + fact - the factor matrix obtained with `MatGetFactor()` 3114 . mat - the matrix 3115 . row, col - row and column permutations 3116 - info - options for factorization, includes 3117 .vb 3118 fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use 3119 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3120 .ve 3121 3122 Level: developer 3123 3124 Notes: 3125 See [Matrix Factorization](sec_matfactor) for additional information about factorizations 3126 3127 Most users should employ the simplified `KSP` interface for linear solvers 3128 instead of working directly with matrix algebra routines such as this. 3129 See, e.g., `KSPCreate()`. 3130 3131 Developer Note: 3132 The Fortran interface is not autogenerated as the 3133 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3134 3135 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3136 @*/ 3137 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 3138 { 3139 MatFactorInfo tinfo; 3140 3141 PetscFunctionBegin; 3142 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3143 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 3144 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 3145 if (info) PetscValidPointer(info, 5); 3146 PetscValidType(mat, 2); 3147 PetscValidPointer(fact, 1); 3148 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3149 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3150 if (!(fact)->ops->lufactorsymbolic) { 3151 MatSolverType stype; 3152 PetscCall(MatFactorGetSolverType(fact, &stype)); 3153 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic LU using solver package %s", ((PetscObject)mat)->type_name, stype); 3154 } 3155 MatCheckPreallocated(mat, 2); 3156 if (!info) { 3157 PetscCall(MatFactorInfoInitialize(&tinfo)); 3158 info = &tinfo; 3159 } 3160 3161 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0)); 3162 PetscCall((fact->ops->lufactorsymbolic)(fact, mat, row, col, info)); 3163 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0)); 3164 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3165 PetscFunctionReturn(PETSC_SUCCESS); 3166 } 3167 3168 /*@C 3169 MatLUFactorNumeric - Performs numeric LU factorization of a matrix. 3170 Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`. 3171 3172 Collective on fact 3173 3174 Input Parameters: 3175 + fact - the factor matrix obtained with `MatGetFactor()` 3176 . mat - the matrix 3177 - info - options for factorization 3178 3179 Level: developer 3180 3181 Notes: 3182 See `MatLUFactor()` for in-place factorization. See 3183 `MatCholeskyFactorNumeric()` for the symmetric, positive definite case. 3184 3185 Most users should employ the `KSP` interface for linear solvers 3186 instead of working directly with matrix algebra routines such as this. 3187 See, e.g., `KSPCreate()`. 3188 3189 Developer Note: 3190 The Fortran interface is not autogenerated as the 3191 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3192 3193 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()` 3194 @*/ 3195 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3196 { 3197 MatFactorInfo tinfo; 3198 3199 PetscFunctionBegin; 3200 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3201 PetscValidType(mat, 2); 3202 PetscValidPointer(fact, 1); 3203 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3204 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3205 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, 3206 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3207 3208 PetscCheck((fact)->ops->lufactornumeric, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s numeric LU", ((PetscObject)mat)->type_name); 3209 MatCheckPreallocated(mat, 2); 3210 if (!info) { 3211 PetscCall(MatFactorInfoInitialize(&tinfo)); 3212 info = &tinfo; 3213 } 3214 3215 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3216 else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0)); 3217 PetscCall((fact->ops->lufactornumeric)(fact, mat, info)); 3218 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3219 else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0)); 3220 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3221 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3222 PetscFunctionReturn(PETSC_SUCCESS); 3223 } 3224 3225 /*@C 3226 MatCholeskyFactor - Performs in-place Cholesky factorization of a 3227 symmetric matrix. 3228 3229 Collective 3230 3231 Input Parameters: 3232 + mat - the matrix 3233 . perm - row and column permutations 3234 - f - expected fill as ratio of original fill 3235 3236 Level: developer 3237 3238 Notes: 3239 See `MatLUFactor()` for the nonsymmetric case. See also `MatGetFactor()`, 3240 `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`. 3241 3242 Most users should employ the `KSP` interface for linear solvers 3243 instead of working directly with matrix algebra routines such as this. 3244 See, e.g., `KSPCreate()`. 3245 3246 Developer Note: 3247 The Fortran interface is not autogenerated as the 3248 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3249 3250 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()` 3251 `MatGetOrdering()` 3252 @*/ 3253 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info) 3254 { 3255 MatFactorInfo tinfo; 3256 3257 PetscFunctionBegin; 3258 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3259 PetscValidType(mat, 1); 3260 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2); 3261 if (info) PetscValidPointer(info, 3); 3262 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3263 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3264 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3265 MatCheckPreallocated(mat, 1); 3266 if (!info) { 3267 PetscCall(MatFactorInfoInitialize(&tinfo)); 3268 info = &tinfo; 3269 } 3270 3271 PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0)); 3272 PetscUseTypeMethod(mat, choleskyfactor, perm, info); 3273 PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0)); 3274 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3275 PetscFunctionReturn(PETSC_SUCCESS); 3276 } 3277 3278 /*@C 3279 MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization 3280 of a symmetric matrix. 3281 3282 Collective on fact 3283 3284 Input Parameters: 3285 + fact - the factor matrix obtained with `MatGetFactor()` 3286 . mat - the matrix 3287 . perm - row and column permutations 3288 - info - options for factorization, includes 3289 .vb 3290 fill - expected fill as ratio of original fill. 3291 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3292 Run with the option -info to determine an optimal value to use 3293 .ve 3294 3295 Level: developer 3296 3297 Notes: 3298 See `MatLUFactorSymbolic()` for the nonsymmetric case. See also 3299 `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`. 3300 3301 Most users should employ the `KSP` interface for linear solvers 3302 instead of working directly with matrix algebra routines such as this. 3303 See, e.g., `KSPCreate()`. 3304 3305 Developer Note: 3306 The Fortran interface is not autogenerated as the 3307 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3308 3309 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()` 3310 `MatGetOrdering()` 3311 @*/ 3312 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 3313 { 3314 MatFactorInfo tinfo; 3315 3316 PetscFunctionBegin; 3317 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3318 PetscValidType(mat, 2); 3319 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 3320 if (info) PetscValidPointer(info, 4); 3321 PetscValidPointer(fact, 1); 3322 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3323 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3324 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3325 if (!(fact)->ops->choleskyfactorsymbolic) { 3326 MatSolverType stype; 3327 PetscCall(MatFactorGetSolverType(fact, &stype)); 3328 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s symbolic factor Cholesky using solver package %s", ((PetscObject)mat)->type_name, stype); 3329 } 3330 MatCheckPreallocated(mat, 2); 3331 if (!info) { 3332 PetscCall(MatFactorInfoInitialize(&tinfo)); 3333 info = &tinfo; 3334 } 3335 3336 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3337 PetscCall((fact->ops->choleskyfactorsymbolic)(fact, mat, perm, info)); 3338 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3339 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3340 PetscFunctionReturn(PETSC_SUCCESS); 3341 } 3342 3343 /*@C 3344 MatCholeskyFactorNumeric - Performs numeric Cholesky factorization 3345 of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and 3346 `MatCholeskyFactorSymbolic()`. 3347 3348 Collective on fact 3349 3350 Input Parameters: 3351 + fact - the factor matrix obtained with `MatGetFactor()` 3352 . mat - the initial matrix 3353 . info - options for factorization 3354 - fact - the symbolic factor of mat 3355 3356 Level: developer 3357 3358 Note: 3359 Most users should employ the `KSP` interface for linear solvers 3360 instead of working directly with matrix algebra routines such as this. 3361 See, e.g., `KSPCreate()`. 3362 3363 Developer Note: 3364 The Fortran interface is not autogenerated as the 3365 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3366 3367 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()` 3368 @*/ 3369 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3370 { 3371 MatFactorInfo tinfo; 3372 3373 PetscFunctionBegin; 3374 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3375 PetscValidType(mat, 2); 3376 PetscValidPointer(fact, 1); 3377 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3378 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3379 PetscCheck((fact)->ops->choleskyfactornumeric, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s numeric factor Cholesky", ((PetscObject)mat)->type_name); 3380 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, 3381 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3382 MatCheckPreallocated(mat, 2); 3383 if (!info) { 3384 PetscCall(MatFactorInfoInitialize(&tinfo)); 3385 info = &tinfo; 3386 } 3387 3388 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3389 else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0)); 3390 PetscCall((fact->ops->choleskyfactornumeric)(fact, mat, info)); 3391 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3392 else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0)); 3393 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3394 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3395 PetscFunctionReturn(PETSC_SUCCESS); 3396 } 3397 3398 /*@ 3399 MatQRFactor - Performs in-place QR factorization of matrix. 3400 3401 Collective 3402 3403 Input Parameters: 3404 + mat - the matrix 3405 . col - column permutation 3406 - info - options for factorization, includes 3407 .vb 3408 fill - expected fill as ratio of original fill. 3409 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3410 Run with the option -info to determine an optimal value to use 3411 .ve 3412 3413 Level: developer 3414 3415 Notes: 3416 Most users should employ the `KSP` interface for linear solvers 3417 instead of working directly with matrix algebra routines such as this. 3418 See, e.g., `KSPCreate()`. 3419 3420 This changes the state of the matrix to a factored matrix; it cannot be used 3421 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3422 3423 Developer Note: 3424 The Fortran interface is not autogenerated as the 3425 interface definition cannot be generated correctly [due to MatFactorInfo] 3426 3427 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`, 3428 `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3429 @*/ 3430 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info) 3431 { 3432 PetscFunctionBegin; 3433 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3434 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2); 3435 if (info) PetscValidPointer(info, 3); 3436 PetscValidType(mat, 1); 3437 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3438 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3439 MatCheckPreallocated(mat, 1); 3440 PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0)); 3441 PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info)); 3442 PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0)); 3443 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3444 PetscFunctionReturn(PETSC_SUCCESS); 3445 } 3446 3447 /*@ 3448 MatQRFactorSymbolic - Performs symbolic QR factorization of matrix. 3449 Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`. 3450 3451 Collective on fact 3452 3453 Input Parameters: 3454 + fact - the factor matrix obtained with `MatGetFactor()` 3455 . mat - the matrix 3456 . col - column permutation 3457 - info - options for factorization, includes 3458 .vb 3459 fill - expected fill as ratio of original fill. 3460 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3461 Run with the option -info to determine an optimal value to use 3462 .ve 3463 3464 Level: developer 3465 3466 Note: 3467 Most users should employ the `KSP` interface for linear solvers 3468 instead of working directly with matrix algebra routines such as this. 3469 See, e.g., `KSPCreate()`. 3470 3471 Developer Note: 3472 The Fortran interface is not autogenerated as the 3473 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3474 3475 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3476 @*/ 3477 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info) 3478 { 3479 MatFactorInfo tinfo; 3480 3481 PetscFunctionBegin; 3482 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3483 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3484 if (info) PetscValidPointer(info, 4); 3485 PetscValidType(mat, 2); 3486 PetscValidPointer(fact, 1); 3487 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3488 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3489 MatCheckPreallocated(mat, 2); 3490 if (!info) { 3491 PetscCall(MatFactorInfoInitialize(&tinfo)); 3492 info = &tinfo; 3493 } 3494 3495 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3496 PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info)); 3497 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3498 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3499 PetscFunctionReturn(PETSC_SUCCESS); 3500 } 3501 3502 /*@ 3503 MatQRFactorNumeric - Performs numeric QR factorization of a matrix. 3504 Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`. 3505 3506 Collective on fact 3507 3508 Input Parameters: 3509 + fact - the factor matrix obtained with `MatGetFactor()` 3510 . mat - the matrix 3511 - info - options for factorization 3512 3513 Level: developer 3514 3515 Notes: 3516 See `MatQRFactor()` for in-place factorization. 3517 3518 Most users should employ the `KSP` interface for linear solvers 3519 instead of working directly with matrix algebra routines such as this. 3520 See, e.g., `KSPCreate()`. 3521 3522 Developer Note: 3523 The Fortran interface is not autogenerated as the 3524 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3525 3526 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()` 3527 @*/ 3528 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3529 { 3530 MatFactorInfo tinfo; 3531 3532 PetscFunctionBegin; 3533 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3534 PetscValidType(mat, 2); 3535 PetscValidPointer(fact, 1); 3536 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3537 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3538 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, 3539 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3540 3541 MatCheckPreallocated(mat, 2); 3542 if (!info) { 3543 PetscCall(MatFactorInfoInitialize(&tinfo)); 3544 info = &tinfo; 3545 } 3546 3547 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3548 else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0)); 3549 PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info)); 3550 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3551 else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0)); 3552 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3553 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3554 PetscFunctionReturn(PETSC_SUCCESS); 3555 } 3556 3557 /* ----------------------------------------------------------------*/ 3558 /*@ 3559 MatSolve - Solves A x = b, given a factored matrix. 3560 3561 Neighbor-wise Collective 3562 3563 Input Parameters: 3564 + mat - the factored matrix 3565 - b - the right-hand-side vector 3566 3567 Output Parameter: 3568 . x - the result vector 3569 3570 Notes: 3571 The vectors b and x cannot be the same. I.e., one cannot 3572 call `MatSolve`(A,x,x). 3573 3574 Most users should employ the `KSP` interface for linear solvers 3575 instead of working directly with matrix algebra routines such as this. 3576 See, e.g., `KSPCreate()`. 3577 3578 Level: developer 3579 3580 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3581 @*/ 3582 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x) 3583 { 3584 PetscFunctionBegin; 3585 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3586 PetscValidType(mat, 1); 3587 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3588 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3589 PetscCheckSameComm(mat, 1, b, 2); 3590 PetscCheckSameComm(mat, 1, x, 3); 3591 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3592 PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N); 3593 PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N); 3594 PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n); 3595 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3596 MatCheckPreallocated(mat, 1); 3597 3598 PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0)); 3599 if (mat->factorerrortype) { 3600 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3601 PetscCall(VecSetInf(x)); 3602 } else PetscUseTypeMethod(mat, solve, b, x); 3603 PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0)); 3604 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3605 PetscFunctionReturn(PETSC_SUCCESS); 3606 } 3607 3608 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans) 3609 { 3610 Vec b, x; 3611 PetscInt N, i; 3612 PetscErrorCode (*f)(Mat, Vec, Vec); 3613 PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE; 3614 3615 PetscFunctionBegin; 3616 if (A->factorerrortype) { 3617 PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype)); 3618 PetscCall(MatSetInf(X)); 3619 PetscFunctionReturn(PETSC_SUCCESS); 3620 } 3621 f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose; 3622 PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 3623 PetscCall(MatBoundToCPU(A, &Abound)); 3624 if (!Abound) { 3625 PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3626 PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3627 } 3628 #if defined(PETSC_HAVE_CUDA) 3629 if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B)); 3630 if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X)); 3631 #elif (PETSC_HAVE_HIP) 3632 if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B)); 3633 if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X)); 3634 #endif 3635 PetscCall(MatGetSize(B, NULL, &N)); 3636 for (i = 0; i < N; i++) { 3637 PetscCall(MatDenseGetColumnVecRead(B, i, &b)); 3638 PetscCall(MatDenseGetColumnVecWrite(X, i, &x)); 3639 PetscCall((*f)(A, b, x)); 3640 PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x)); 3641 PetscCall(MatDenseRestoreColumnVecRead(B, i, &b)); 3642 } 3643 if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B)); 3644 if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X)); 3645 PetscFunctionReturn(PETSC_SUCCESS); 3646 } 3647 3648 /*@ 3649 MatMatSolve - Solves A X = B, given a factored matrix. 3650 3651 Neighbor-wise Collective on A 3652 3653 Input Parameters: 3654 + A - the factored matrix 3655 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS) 3656 3657 Output Parameter: 3658 . X - the result matrix (dense matrix) 3659 3660 Note: 3661 If B is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with MKL_CPARDISO; 3662 otherwise, B and X cannot be the same. 3663 3664 Level: developer 3665 3666 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3667 @*/ 3668 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X) 3669 { 3670 PetscFunctionBegin; 3671 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3672 PetscValidType(A, 1); 3673 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3674 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3675 PetscCheckSameComm(A, 1, B, 2); 3676 PetscCheckSameComm(A, 1, X, 3); 3677 PetscCheck(A->cmap->N == X->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat X: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->cmap->N, X->rmap->N); 3678 PetscCheck(A->rmap->N == B->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat B: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->N, B->rmap->N); 3679 PetscCheck(X->cmap->N == B->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Solution matrix must have same number of columns as rhs matrix"); 3680 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3681 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3682 MatCheckPreallocated(A, 1); 3683 3684 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3685 if (!A->ops->matsolve) { 3686 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name)); 3687 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE)); 3688 } else PetscUseTypeMethod(A, matsolve, B, X); 3689 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3690 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3691 PetscFunctionReturn(PETSC_SUCCESS); 3692 } 3693 3694 /*@ 3695 MatMatSolveTranspose - Solves A^T X = B, given a factored matrix. 3696 3697 Neighbor-wise Collective on A 3698 3699 Input Parameters: 3700 + A - the factored matrix 3701 - B - the right-hand-side matrix (`MATDENSE` matrix) 3702 3703 Output Parameter: 3704 . X - the result matrix (dense matrix) 3705 3706 Note: 3707 The matrices B and X cannot be the same. I.e., one cannot 3708 call `MatMatSolveTranspose`(A,X,X). 3709 3710 Level: developer 3711 3712 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()` 3713 @*/ 3714 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X) 3715 { 3716 PetscFunctionBegin; 3717 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3718 PetscValidType(A, 1); 3719 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3720 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3721 PetscCheckSameComm(A, 1, B, 2); 3722 PetscCheckSameComm(A, 1, X, 3); 3723 PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3724 PetscCheck(A->cmap->N == X->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat X: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->cmap->N, X->rmap->N); 3725 PetscCheck(A->rmap->N == B->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat B: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->N, B->rmap->N); 3726 PetscCheck(A->rmap->n == B->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat A,Mat B: local dim %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->n, B->rmap->n); 3727 PetscCheck(X->cmap->N >= B->cmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Solution matrix must have same number of columns as rhs matrix"); 3728 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3729 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3730 MatCheckPreallocated(A, 1); 3731 3732 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3733 if (!A->ops->matsolvetranspose) { 3734 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name)); 3735 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE)); 3736 } else PetscUseTypeMethod(A, matsolvetranspose, B, X); 3737 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3738 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3739 PetscFunctionReturn(PETSC_SUCCESS); 3740 } 3741 3742 /*@ 3743 MatMatTransposeSolve - Solves A X = B^T, given a factored matrix. 3744 3745 Neighbor-wise Collective on A 3746 3747 Input Parameters: 3748 + A - the factored matrix 3749 - Bt - the transpose of right-hand-side matrix as a `MATDENSE` 3750 3751 Output Parameter: 3752 . X - the result matrix (dense matrix) 3753 3754 Note: 3755 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 3756 format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`. 3757 3758 Level: developer 3759 3760 .seealso: [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3761 @*/ 3762 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X) 3763 { 3764 PetscFunctionBegin; 3765 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3766 PetscValidType(A, 1); 3767 PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2); 3768 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3769 PetscCheckSameComm(A, 1, Bt, 2); 3770 PetscCheckSameComm(A, 1, X, 3); 3771 3772 PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3773 PetscCheck(A->cmap->N == X->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat X: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->cmap->N, X->rmap->N); 3774 PetscCheck(A->rmap->N == Bt->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat Bt: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->N, Bt->cmap->N); 3775 PetscCheck(X->cmap->N >= Bt->rmap->N, PetscObjectComm((PetscObject)X), PETSC_ERR_ARG_SIZ, "Solution matrix must have same number of columns as row number of the rhs matrix"); 3776 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3777 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3778 MatCheckPreallocated(A, 1); 3779 3780 PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0)); 3781 PetscUseTypeMethod(A, mattransposesolve, Bt, X); 3782 PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0)); 3783 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3784 PetscFunctionReturn(PETSC_SUCCESS); 3785 } 3786 3787 /*@ 3788 MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or 3789 U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U, 3790 3791 Neighbor-wise Collective 3792 3793 Input Parameters: 3794 + mat - the factored matrix 3795 - b - the right-hand-side vector 3796 3797 Output Parameter: 3798 . x - the result vector 3799 3800 Notes: 3801 `MatSolve()` should be used for most applications, as it performs 3802 a forward solve followed by a backward solve. 3803 3804 The vectors b and x cannot be the same, i.e., one cannot 3805 call `MatForwardSolve`(A,x,x). 3806 3807 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3808 the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet. 3809 `MatForwardSolve()` solves U^T*D y = b, and 3810 `MatBackwardSolve()` solves U x = y. 3811 Thus they do not provide a symmetric preconditioner. 3812 3813 Level: developer 3814 3815 .seealso: `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatBackwardSolve()` 3816 @*/ 3817 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x) 3818 { 3819 PetscFunctionBegin; 3820 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3821 PetscValidType(mat, 1); 3822 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3823 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3824 PetscCheckSameComm(mat, 1, b, 2); 3825 PetscCheckSameComm(mat, 1, x, 3); 3826 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3827 PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N); 3828 PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N); 3829 PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n); 3830 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3831 MatCheckPreallocated(mat, 1); 3832 3833 PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0)); 3834 PetscUseTypeMethod(mat, forwardsolve, b, x); 3835 PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0)); 3836 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3837 PetscFunctionReturn(PETSC_SUCCESS); 3838 } 3839 3840 /*@ 3841 MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU. 3842 D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U, 3843 3844 Neighbor-wise Collective 3845 3846 Input Parameters: 3847 + mat - the factored matrix 3848 - b - the right-hand-side vector 3849 3850 Output Parameter: 3851 . x - the result vector 3852 3853 Notes: 3854 `MatSolve()` should be used for most applications, as it performs 3855 a forward solve followed by a backward solve. 3856 3857 The vectors b and x cannot be the same. I.e., one cannot 3858 call `MatBackwardSolve`(A,x,x). 3859 3860 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3861 the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet. 3862 `MatForwardSolve()` solves U^T*D y = b, and 3863 `MatBackwardSolve()` solves U x = y. 3864 Thus they do not provide a symmetric preconditioner. 3865 3866 Level: developer 3867 3868 .seealso: `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatForwardSolve()` 3869 @*/ 3870 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x) 3871 { 3872 PetscFunctionBegin; 3873 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3874 PetscValidType(mat, 1); 3875 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3876 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3877 PetscCheckSameComm(mat, 1, b, 2); 3878 PetscCheckSameComm(mat, 1, x, 3); 3879 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3880 PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N); 3881 PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N); 3882 PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n); 3883 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3884 MatCheckPreallocated(mat, 1); 3885 3886 PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0)); 3887 PetscUseTypeMethod(mat, backwardsolve, b, x); 3888 PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0)); 3889 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3890 PetscFunctionReturn(PETSC_SUCCESS); 3891 } 3892 3893 /*@ 3894 MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix. 3895 3896 Neighbor-wise Collective 3897 3898 Input Parameters: 3899 + mat - the factored matrix 3900 . b - the right-hand-side vector 3901 - y - the vector to be added to 3902 3903 Output Parameter: 3904 . x - the result vector 3905 3906 Note: 3907 The vectors b and x cannot be the same. I.e., one cannot 3908 call `MatSolveAdd`(A,x,y,x). 3909 3910 Level: developer 3911 3912 .seealso: [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3913 @*/ 3914 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x) 3915 { 3916 PetscScalar one = 1.0; 3917 Vec tmp; 3918 3919 PetscFunctionBegin; 3920 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3921 PetscValidType(mat, 1); 3922 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 3923 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3924 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 3925 PetscCheckSameComm(mat, 1, b, 2); 3926 PetscCheckSameComm(mat, 1, y, 3); 3927 PetscCheckSameComm(mat, 1, x, 4); 3928 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3929 PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N); 3930 PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N); 3931 PetscCheck(mat->rmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, y->map->N); 3932 PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n); 3933 PetscCheck(x->map->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Vec x,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, x->map->n, y->map->n); 3934 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3935 MatCheckPreallocated(mat, 1); 3936 3937 PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y)); 3938 if (mat->factorerrortype) { 3939 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3940 PetscCall(VecSetInf(x)); 3941 } else if (mat->ops->solveadd) { 3942 PetscUseTypeMethod(mat, solveadd, b, y, x); 3943 } else { 3944 /* do the solve then the add manually */ 3945 if (x != y) { 3946 PetscCall(MatSolve(mat, b, x)); 3947 PetscCall(VecAXPY(x, one, y)); 3948 } else { 3949 PetscCall(VecDuplicate(x, &tmp)); 3950 PetscCall(VecCopy(x, tmp)); 3951 PetscCall(MatSolve(mat, b, x)); 3952 PetscCall(VecAXPY(x, one, tmp)); 3953 PetscCall(VecDestroy(&tmp)); 3954 } 3955 } 3956 PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y)); 3957 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3958 PetscFunctionReturn(PETSC_SUCCESS); 3959 } 3960 3961 /*@ 3962 MatSolveTranspose - Solves A' x = b, given a factored matrix. 3963 3964 Neighbor-wise Collective 3965 3966 Input Parameters: 3967 + mat - the factored matrix 3968 - b - the right-hand-side vector 3969 3970 Output Parameter: 3971 . x - the result vector 3972 3973 Notes: 3974 The vectors b and x cannot be the same. I.e., one cannot 3975 call `MatSolveTranspose`(A,x,x). 3976 3977 Most users should employ the `KSP` interface for linear solvers 3978 instead of working directly with matrix algebra routines such as this. 3979 See, e.g., `KSPCreate()`. 3980 3981 Level: developer 3982 3983 .seealso: `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()` 3984 @*/ 3985 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x) 3986 { 3987 PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose; 3988 3989 PetscFunctionBegin; 3990 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3991 PetscValidType(mat, 1); 3992 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3993 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3994 PetscCheckSameComm(mat, 1, b, 2); 3995 PetscCheckSameComm(mat, 1, x, 3); 3996 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3997 PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N); 3998 PetscCheck(mat->cmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, b->map->N); 3999 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4000 MatCheckPreallocated(mat, 1); 4001 PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0)); 4002 if (mat->factorerrortype) { 4003 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4004 PetscCall(VecSetInf(x)); 4005 } else { 4006 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name); 4007 PetscCall((*f)(mat, b, x)); 4008 } 4009 PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0)); 4010 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4011 PetscFunctionReturn(PETSC_SUCCESS); 4012 } 4013 4014 /*@ 4015 MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a 4016 factored matrix. 4017 4018 Neighbor-wise Collective 4019 4020 Input Parameters: 4021 + mat - the factored matrix 4022 . b - the right-hand-side vector 4023 - y - the vector to be added to 4024 4025 Output Parameter: 4026 . x - the result vector 4027 4028 Note: 4029 The vectors b and x cannot be the same. I.e., one cannot 4030 call `MatSolveTransposeAdd`(A,x,y,x). 4031 4032 Level: developer 4033 4034 .seealso: `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()` 4035 @*/ 4036 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x) 4037 { 4038 PetscScalar one = 1.0; 4039 Vec tmp; 4040 PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd; 4041 4042 PetscFunctionBegin; 4043 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4044 PetscValidType(mat, 1); 4045 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4046 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4047 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4048 PetscCheckSameComm(mat, 1, b, 2); 4049 PetscCheckSameComm(mat, 1, y, 3); 4050 PetscCheckSameComm(mat, 1, x, 4); 4051 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4052 PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N); 4053 PetscCheck(mat->cmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, b->map->N); 4054 PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N); 4055 PetscCheck(x->map->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Vec x,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, x->map->n, y->map->n); 4056 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4057 MatCheckPreallocated(mat, 1); 4058 4059 PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y)); 4060 if (mat->factorerrortype) { 4061 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4062 PetscCall(VecSetInf(x)); 4063 } else if (f) { 4064 PetscCall((*f)(mat, b, y, x)); 4065 } else { 4066 /* do the solve then the add manually */ 4067 if (x != y) { 4068 PetscCall(MatSolveTranspose(mat, b, x)); 4069 PetscCall(VecAXPY(x, one, y)); 4070 } else { 4071 PetscCall(VecDuplicate(x, &tmp)); 4072 PetscCall(VecCopy(x, tmp)); 4073 PetscCall(MatSolveTranspose(mat, b, x)); 4074 PetscCall(VecAXPY(x, one, tmp)); 4075 PetscCall(VecDestroy(&tmp)); 4076 } 4077 } 4078 PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y)); 4079 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4080 PetscFunctionReturn(PETSC_SUCCESS); 4081 } 4082 /* ----------------------------------------------------------------*/ 4083 4084 /*@ 4085 MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps. 4086 4087 Neighbor-wise Collective 4088 4089 Input Parameters: 4090 + mat - the matrix 4091 . b - the right hand side 4092 . omega - the relaxation factor 4093 . flag - flag indicating the type of SOR (see below) 4094 . shift - diagonal shift 4095 . its - the number of iterations 4096 - lits - the number of local iterations 4097 4098 Output Parameter: 4099 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess) 4100 4101 SOR Flags: 4102 + `SOR_FORWARD_SWEEP` - forward SOR 4103 . `SOR_BACKWARD_SWEEP` - backward SOR 4104 . `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR) 4105 . `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR 4106 . `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR 4107 . `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR 4108 . `SOR_EISENSTAT` - SOR with Eisenstat trick 4109 . `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies 4110 upper/lower triangular part of matrix to 4111 vector (with omega) 4112 - `SOR_ZERO_INITIAL_GUESS` - zero initial guess 4113 4114 Notes: 4115 `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and 4116 `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings 4117 on each processor. 4118 4119 Application programmers will not generally use `MatSOR()` directly, 4120 but instead will employ the `KSP`/`PC` interface. 4121 4122 For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing 4123 4124 Most users should employ the `KSP` interface for linear solvers 4125 instead of working directly with matrix algebra routines such as this. 4126 See, e.g., `KSPCreate()`. 4127 4128 Vectors x and b CANNOT be the same 4129 4130 Notes for Advanced Users: 4131 The flags are implemented as bitwise inclusive or operations. 4132 For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`) 4133 to specify a zero initial guess for SSOR. 4134 4135 Developer Note: 4136 We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes 4137 4138 Level: developer 4139 4140 .seealso: `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()` 4141 @*/ 4142 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x) 4143 { 4144 PetscFunctionBegin; 4145 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4146 PetscValidType(mat, 1); 4147 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4148 PetscValidHeaderSpecific(x, VEC_CLASSID, 8); 4149 PetscCheckSameComm(mat, 1, b, 2); 4150 PetscCheckSameComm(mat, 1, x, 8); 4151 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4152 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4153 PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N); 4154 PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N); 4155 PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n); 4156 PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its); 4157 PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits); 4158 PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same"); 4159 4160 MatCheckPreallocated(mat, 1); 4161 PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0)); 4162 PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x); 4163 PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0)); 4164 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4165 PetscFunctionReturn(PETSC_SUCCESS); 4166 } 4167 4168 /* 4169 Default matrix copy routine. 4170 */ 4171 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str) 4172 { 4173 PetscInt i, rstart = 0, rend = 0, nz; 4174 const PetscInt *cwork; 4175 const PetscScalar *vwork; 4176 4177 PetscFunctionBegin; 4178 if (B->assembled) PetscCall(MatZeroEntries(B)); 4179 if (str == SAME_NONZERO_PATTERN) { 4180 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 4181 for (i = rstart; i < rend; i++) { 4182 PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork)); 4183 PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES)); 4184 PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork)); 4185 } 4186 } else { 4187 PetscCall(MatAYPX(B, 0.0, A, str)); 4188 } 4189 PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 4190 PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 4191 PetscFunctionReturn(PETSC_SUCCESS); 4192 } 4193 4194 /*@ 4195 MatCopy - Copies a matrix to another matrix. 4196 4197 Collective on A 4198 4199 Input Parameters: 4200 + A - the matrix 4201 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN` 4202 4203 Output Parameter: 4204 . B - where the copy is put 4205 4206 Notes: 4207 If you use `SAME_NONZERO_PATTERN `then the two matrices must have the same nonzero pattern or the routine will crash. 4208 4209 `MatCopy()` copies the matrix entries of a matrix to another existing 4210 matrix (after first zeroing the second matrix). A related routine is 4211 `MatConvert()`, which first creates a new matrix and then copies the data. 4212 4213 Level: intermediate 4214 4215 .seealso: `Mat`, `MatConvert()`, `MatDuplicate()` 4216 @*/ 4217 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str) 4218 { 4219 PetscInt i; 4220 4221 PetscFunctionBegin; 4222 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 4223 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 4224 PetscValidType(A, 1); 4225 PetscValidType(B, 2); 4226 PetscCheckSameComm(A, 1, B, 2); 4227 MatCheckPreallocated(B, 2); 4228 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4229 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4230 PetscCheck(A->rmap->N == B->rmap->N && A->cmap->N == B->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat B: global dim (%" PetscInt_FMT ",%" PetscInt_FMT ") (%" PetscInt_FMT ",%" PetscInt_FMT ")", A->rmap->N, B->rmap->N, 4231 A->cmap->N, B->cmap->N); 4232 MatCheckPreallocated(A, 1); 4233 if (A == B) PetscFunctionReturn(PETSC_SUCCESS); 4234 4235 PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0)); 4236 if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str); 4237 else PetscCall(MatCopy_Basic(A, B, str)); 4238 4239 B->stencil.dim = A->stencil.dim; 4240 B->stencil.noc = A->stencil.noc; 4241 for (i = 0; i <= A->stencil.dim; i++) { 4242 B->stencil.dims[i] = A->stencil.dims[i]; 4243 B->stencil.starts[i] = A->stencil.starts[i]; 4244 } 4245 4246 PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0)); 4247 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4248 PetscFunctionReturn(PETSC_SUCCESS); 4249 } 4250 4251 /*@C 4252 MatConvert - Converts a matrix to another matrix, either of the same 4253 or different type. 4254 4255 Collective 4256 4257 Input Parameters: 4258 + mat - the matrix 4259 . newtype - new matrix type. Use `MATSAME` to create a new matrix of the 4260 same type as the original matrix. 4261 - reuse - denotes if the destination matrix is to be created or reused. 4262 Use `MAT_INPLACE_MATRIX` for inplace conversion (that is when you want the input mat to be changed to contain the matrix in the new format), otherwise use 4263 `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` (can only be used after the first call was made with `MAT_INITIAL_MATRIX`, causes the matrix space in M to be reused). 4264 4265 Output Parameter: 4266 . M - pointer to place new matrix 4267 4268 Notes: 4269 `MatConvert()` first creates a new matrix and then copies the data from 4270 the first matrix. A related routine is `MatCopy()`, which copies the matrix 4271 entries of one matrix to another already existing matrix context. 4272 4273 Cannot be used to convert a sequential matrix to parallel or parallel to sequential, 4274 the MPI communicator of the generated matrix is always the same as the communicator 4275 of the input matrix. 4276 4277 Level: intermediate 4278 4279 .seealso: `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 4280 @*/ 4281 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M) 4282 { 4283 PetscBool sametype, issame, flg; 4284 PetscBool3 issymmetric, ishermitian; 4285 char convname[256], mtype[256]; 4286 Mat B; 4287 4288 PetscFunctionBegin; 4289 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4290 PetscValidType(mat, 1); 4291 PetscValidPointer(M, 4); 4292 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4293 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4294 MatCheckPreallocated(mat, 1); 4295 4296 PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg)); 4297 if (flg) newtype = mtype; 4298 4299 PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype)); 4300 PetscCall(PetscStrcmp(newtype, "same", &issame)); 4301 PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix"); 4302 PetscCheck(!(reuse == MAT_REUSE_MATRIX) || !(mat == *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX"); 4303 4304 if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) { 4305 PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4306 PetscFunctionReturn(PETSC_SUCCESS); 4307 } 4308 4309 /* Cache Mat options because some converters use MatHeaderReplace */ 4310 issymmetric = mat->symmetric; 4311 ishermitian = mat->hermitian; 4312 4313 if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) { 4314 PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4315 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4316 } else { 4317 PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL; 4318 const char *prefix[3] = {"seq", "mpi", ""}; 4319 PetscInt i; 4320 /* 4321 Order of precedence: 4322 0) See if newtype is a superclass of the current matrix. 4323 1) See if a specialized converter is known to the current matrix. 4324 2) See if a specialized converter is known to the desired matrix class. 4325 3) See if a good general converter is registered for the desired class 4326 (as of 6/27/03 only MATMPIADJ falls into this category). 4327 4) See if a good general converter is known for the current matrix. 4328 5) Use a really basic converter. 4329 */ 4330 4331 /* 0) See if newtype is a superclass of the current matrix. 4332 i.e mat is mpiaij and newtype is aij */ 4333 for (i = 0; i < 2; i++) { 4334 PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname))); 4335 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4336 PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg)); 4337 PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg)); 4338 if (flg) { 4339 if (reuse == MAT_INPLACE_MATRIX) { 4340 PetscCall(PetscInfo(mat, "Early return\n")); 4341 PetscFunctionReturn(PETSC_SUCCESS); 4342 } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) { 4343 PetscCall(PetscInfo(mat, "Calling MatDuplicate\n")); 4344 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4345 PetscFunctionReturn(PETSC_SUCCESS); 4346 } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) { 4347 PetscCall(PetscInfo(mat, "Calling MatCopy\n")); 4348 PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN)); 4349 PetscFunctionReturn(PETSC_SUCCESS); 4350 } 4351 } 4352 } 4353 /* 1) See if a specialized converter is known to the current matrix and the desired class */ 4354 for (i = 0; i < 3; i++) { 4355 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4356 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4357 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4358 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4359 PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname))); 4360 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4361 PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv)); 4362 PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv)); 4363 if (conv) goto foundconv; 4364 } 4365 4366 /* 2) See if a specialized converter is known to the desired matrix class. */ 4367 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B)); 4368 PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 4369 PetscCall(MatSetType(B, newtype)); 4370 for (i = 0; i < 3; i++) { 4371 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4372 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4373 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4374 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4375 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4376 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4377 PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv)); 4378 PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv)); 4379 if (conv) { 4380 PetscCall(MatDestroy(&B)); 4381 goto foundconv; 4382 } 4383 } 4384 4385 /* 3) See if a good general converter is registered for the desired class */ 4386 conv = B->ops->convertfrom; 4387 PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv)); 4388 PetscCall(MatDestroy(&B)); 4389 if (conv) goto foundconv; 4390 4391 /* 4) See if a good general converter is known for the current matrix */ 4392 if (mat->ops->convert) conv = mat->ops->convert; 4393 PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv)); 4394 if (conv) goto foundconv; 4395 4396 /* 5) Use a really basic converter. */ 4397 PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n")); 4398 conv = MatConvert_Basic; 4399 4400 foundconv: 4401 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4402 PetscCall((*conv)(mat, newtype, reuse, M)); 4403 if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) { 4404 /* the block sizes must be same if the mappings are copied over */ 4405 (*M)->rmap->bs = mat->rmap->bs; 4406 (*M)->cmap->bs = mat->cmap->bs; 4407 PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping)); 4408 PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping)); 4409 (*M)->rmap->mapping = mat->rmap->mapping; 4410 (*M)->cmap->mapping = mat->cmap->mapping; 4411 } 4412 (*M)->stencil.dim = mat->stencil.dim; 4413 (*M)->stencil.noc = mat->stencil.noc; 4414 for (i = 0; i <= mat->stencil.dim; i++) { 4415 (*M)->stencil.dims[i] = mat->stencil.dims[i]; 4416 (*M)->stencil.starts[i] = mat->stencil.starts[i]; 4417 } 4418 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4419 } 4420 PetscCall(PetscObjectStateIncrease((PetscObject)*M)); 4421 4422 /* Copy Mat options */ 4423 if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE)); 4424 else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE)); 4425 if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE)); 4426 else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE)); 4427 PetscFunctionReturn(PETSC_SUCCESS); 4428 } 4429 4430 /*@C 4431 MatFactorGetSolverType - Returns name of the package providing the factorization routines 4432 4433 Not Collective 4434 4435 Input Parameter: 4436 . mat - the matrix, must be a factored matrix 4437 4438 Output Parameter: 4439 . type - the string name of the package (do not free this string) 4440 4441 Level: intermediate 4442 4443 Note: 4444 In Fortran you pass in a empty string and the package name will be copied into it. 4445 (Make sure the string is long enough) 4446 4447 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()` 4448 @*/ 4449 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type) 4450 { 4451 PetscErrorCode (*conv)(Mat, MatSolverType *); 4452 4453 PetscFunctionBegin; 4454 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4455 PetscValidType(mat, 1); 4456 PetscValidPointer(type, 2); 4457 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 4458 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv)); 4459 if (conv) PetscCall((*conv)(mat, type)); 4460 else *type = MATSOLVERPETSC; 4461 PetscFunctionReturn(PETSC_SUCCESS); 4462 } 4463 4464 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType; 4465 struct _MatSolverTypeForSpecifcType { 4466 MatType mtype; 4467 /* no entry for MAT_FACTOR_NONE */ 4468 PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *); 4469 MatSolverTypeForSpecifcType next; 4470 }; 4471 4472 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder; 4473 struct _MatSolverTypeHolder { 4474 char *name; 4475 MatSolverTypeForSpecifcType handlers; 4476 MatSolverTypeHolder next; 4477 }; 4478 4479 static MatSolverTypeHolder MatSolverTypeHolders = NULL; 4480 4481 /*@C 4482 MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type 4483 4484 Input Parameters: 4485 + package - name of the package, for example petsc or superlu 4486 . mtype - the matrix type that works with this package 4487 . ftype - the type of factorization supported by the package 4488 - createfactor - routine that will create the factored matrix ready to be used 4489 4490 Level: developer 4491 4492 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()` 4493 @*/ 4494 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *)) 4495 { 4496 MatSolverTypeHolder next = MatSolverTypeHolders, prev = NULL; 4497 PetscBool flg; 4498 MatSolverTypeForSpecifcType inext, iprev = NULL; 4499 4500 PetscFunctionBegin; 4501 PetscCall(MatInitializePackage()); 4502 if (!next) { 4503 PetscCall(PetscNew(&MatSolverTypeHolders)); 4504 PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name)); 4505 PetscCall(PetscNew(&MatSolverTypeHolders->handlers)); 4506 PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype)); 4507 MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor; 4508 PetscFunctionReturn(PETSC_SUCCESS); 4509 } 4510 while (next) { 4511 PetscCall(PetscStrcasecmp(package, next->name, &flg)); 4512 if (flg) { 4513 PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers"); 4514 inext = next->handlers; 4515 while (inext) { 4516 PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg)); 4517 if (flg) { 4518 inext->createfactor[(int)ftype - 1] = createfactor; 4519 PetscFunctionReturn(PETSC_SUCCESS); 4520 } 4521 iprev = inext; 4522 inext = inext->next; 4523 } 4524 PetscCall(PetscNew(&iprev->next)); 4525 PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype)); 4526 iprev->next->createfactor[(int)ftype - 1] = createfactor; 4527 PetscFunctionReturn(PETSC_SUCCESS); 4528 } 4529 prev = next; 4530 next = next->next; 4531 } 4532 PetscCall(PetscNew(&prev->next)); 4533 PetscCall(PetscStrallocpy(package, &prev->next->name)); 4534 PetscCall(PetscNew(&prev->next->handlers)); 4535 PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype)); 4536 prev->next->handlers->createfactor[(int)ftype - 1] = createfactor; 4537 PetscFunctionReturn(PETSC_SUCCESS); 4538 } 4539 4540 /*@C 4541 MatSolverTypeGet - Gets the function that creates the factor matrix if it exist 4542 4543 Input Parameters: 4544 + type - name of the package, for example petsc or superlu 4545 . ftype - the type of factorization supported by the type 4546 - mtype - the matrix type that works with this type 4547 4548 Output Parameters: 4549 + foundtype - `PETSC_TRUE` if the type was registered 4550 . foundmtype - `PETSC_TRUE` if the type supports the requested mtype 4551 - createfactor - routine that will create the factored matrix ready to be used or NULL if not found 4552 4553 Level: developer 4554 4555 .seealso: `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()` 4556 @*/ 4557 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *)) 4558 { 4559 MatSolverTypeHolder next = MatSolverTypeHolders; 4560 PetscBool flg; 4561 MatSolverTypeForSpecifcType inext; 4562 4563 PetscFunctionBegin; 4564 if (foundtype) *foundtype = PETSC_FALSE; 4565 if (foundmtype) *foundmtype = PETSC_FALSE; 4566 if (createfactor) *createfactor = NULL; 4567 4568 if (type) { 4569 while (next) { 4570 PetscCall(PetscStrcasecmp(type, next->name, &flg)); 4571 if (flg) { 4572 if (foundtype) *foundtype = PETSC_TRUE; 4573 inext = next->handlers; 4574 while (inext) { 4575 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4576 if (flg) { 4577 if (foundmtype) *foundmtype = PETSC_TRUE; 4578 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4579 PetscFunctionReturn(PETSC_SUCCESS); 4580 } 4581 inext = inext->next; 4582 } 4583 } 4584 next = next->next; 4585 } 4586 } else { 4587 while (next) { 4588 inext = next->handlers; 4589 while (inext) { 4590 PetscCall(PetscStrcmp(mtype, inext->mtype, &flg)); 4591 if (flg && inext->createfactor[(int)ftype - 1]) { 4592 if (foundtype) *foundtype = PETSC_TRUE; 4593 if (foundmtype) *foundmtype = PETSC_TRUE; 4594 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4595 PetscFunctionReturn(PETSC_SUCCESS); 4596 } 4597 inext = inext->next; 4598 } 4599 next = next->next; 4600 } 4601 /* try with base classes inext->mtype */ 4602 next = MatSolverTypeHolders; 4603 while (next) { 4604 inext = next->handlers; 4605 while (inext) { 4606 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4607 if (flg && inext->createfactor[(int)ftype - 1]) { 4608 if (foundtype) *foundtype = PETSC_TRUE; 4609 if (foundmtype) *foundmtype = PETSC_TRUE; 4610 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4611 PetscFunctionReturn(PETSC_SUCCESS); 4612 } 4613 inext = inext->next; 4614 } 4615 next = next->next; 4616 } 4617 } 4618 PetscFunctionReturn(PETSC_SUCCESS); 4619 } 4620 4621 PetscErrorCode MatSolverTypeDestroy(void) 4622 { 4623 MatSolverTypeHolder next = MatSolverTypeHolders, prev; 4624 MatSolverTypeForSpecifcType inext, iprev; 4625 4626 PetscFunctionBegin; 4627 while (next) { 4628 PetscCall(PetscFree(next->name)); 4629 inext = next->handlers; 4630 while (inext) { 4631 PetscCall(PetscFree(inext->mtype)); 4632 iprev = inext; 4633 inext = inext->next; 4634 PetscCall(PetscFree(iprev)); 4635 } 4636 prev = next; 4637 next = next->next; 4638 PetscCall(PetscFree(prev)); 4639 } 4640 MatSolverTypeHolders = NULL; 4641 PetscFunctionReturn(PETSC_SUCCESS); 4642 } 4643 4644 /*@C 4645 MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4646 4647 Logically Collective 4648 4649 Input Parameters: 4650 . mat - the matrix 4651 4652 Output Parameters: 4653 . flg - `PETSC_TRUE` if uses the ordering 4654 4655 Note: 4656 Most internal PETSc factorizations use the ordering passed to the factorization routine but external 4657 packages do not, thus we want to skip generating the ordering when it is not needed or used. 4658 4659 Level: developer 4660 4661 .seealso: [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4662 @*/ 4663 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg) 4664 { 4665 PetscFunctionBegin; 4666 *flg = mat->canuseordering; 4667 PetscFunctionReturn(PETSC_SUCCESS); 4668 } 4669 4670 /*@C 4671 MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object 4672 4673 Logically Collective 4674 4675 Input Parameters: 4676 . mat - the matrix obtained with `MatGetFactor()` 4677 4678 Output Parameters: 4679 . otype - the preferred type 4680 4681 Level: developer 4682 4683 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4684 @*/ 4685 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype) 4686 { 4687 PetscFunctionBegin; 4688 *otype = mat->preferredordering[ftype]; 4689 PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering"); 4690 PetscFunctionReturn(PETSC_SUCCESS); 4691 } 4692 4693 /*@C 4694 MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic() 4695 4696 Collective 4697 4698 Input Parameters: 4699 + mat - the matrix 4700 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4701 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4702 4703 Output Parameters: 4704 . f - the factor matrix used with MatXXFactorSymbolic() calls 4705 4706 Options Database Key: 4707 . -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory. 4708 One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices. 4709 4710 Notes: 4711 Users usually access the factorization solvers via `KSP` 4712 4713 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4714 such as pastix, superlu, mumps etc. 4715 4716 PETSc must have been ./configure to use the external solver, using the option --download-package 4717 4718 Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption 4719 where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set 4720 call `MatSetOptionsPrefixFactor()` on the originating matrix or `MatSetOptionsPrefix()` on the resulting factor matrix. 4721 4722 Developer Note: 4723 This should actually be called `MatCreateFactor()` since it creates a new factor object 4724 4725 Level: intermediate 4726 4727 .seealso: [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, 4728 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4729 @*/ 4730 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f) 4731 { 4732 PetscBool foundtype, foundmtype; 4733 PetscErrorCode (*conv)(Mat, MatFactorType, Mat *); 4734 4735 PetscFunctionBegin; 4736 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4737 PetscValidType(mat, 1); 4738 4739 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4740 MatCheckPreallocated(mat, 1); 4741 4742 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv)); 4743 if (!foundtype) { 4744 if (type) { 4745 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], 4746 ((PetscObject)mat)->type_name, type); 4747 } else { 4748 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); 4749 } 4750 } 4751 PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name); 4752 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); 4753 4754 PetscCall((*conv)(mat, ftype, f)); 4755 if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix)); 4756 PetscFunctionReturn(PETSC_SUCCESS); 4757 } 4758 4759 /*@C 4760 MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type 4761 4762 Not Collective 4763 4764 Input Parameters: 4765 + mat - the matrix 4766 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4767 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4768 4769 Output Parameter: 4770 . flg - PETSC_TRUE if the factorization is available 4771 4772 Notes: 4773 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4774 such as pastix, superlu, mumps etc. 4775 4776 PETSc must have been ./configure to use the external solver, using the option --download-package 4777 4778 Developer Note: 4779 This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object 4780 4781 Level: intermediate 4782 4783 .seealso: [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactor()`, `MatSolverTypeRegister()`, 4784 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4785 @*/ 4786 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg) 4787 { 4788 PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *); 4789 4790 PetscFunctionBegin; 4791 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4792 PetscValidType(mat, 1); 4793 PetscValidBoolPointer(flg, 4); 4794 4795 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4796 MatCheckPreallocated(mat, 1); 4797 4798 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv)); 4799 *flg = gconv ? PETSC_TRUE : PETSC_FALSE; 4800 PetscFunctionReturn(PETSC_SUCCESS); 4801 } 4802 4803 /*@ 4804 MatDuplicate - Duplicates a matrix including the non-zero structure. 4805 4806 Collective 4807 4808 Input Parameters: 4809 + mat - the matrix 4810 - op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`. 4811 See the manual page for `MatDuplicateOption()` for an explanation of these options. 4812 4813 Output Parameter: 4814 . M - pointer to place new matrix 4815 4816 Level: intermediate 4817 4818 Notes: 4819 You cannot change the nonzero pattern for the parent or child matrix if you use `MAT_SHARE_NONZERO_PATTERN`. 4820 4821 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. 4822 4823 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 4824 is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated. 4825 User should not use `MatDuplicate()` to create new matrix M if M is intended to be reused as the product of matrix operation. 4826 4827 .seealso: `MatCopy()`, `MatConvert()`, `MatDuplicateOption` 4828 @*/ 4829 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M) 4830 { 4831 Mat B; 4832 VecType vtype; 4833 PetscInt i; 4834 PetscObject dm; 4835 void (*viewf)(void); 4836 4837 PetscFunctionBegin; 4838 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4839 PetscValidType(mat, 1); 4840 PetscValidPointer(M, 3); 4841 PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix"); 4842 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4843 MatCheckPreallocated(mat, 1); 4844 4845 *M = NULL; 4846 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4847 PetscUseTypeMethod(mat, duplicate, op, M); 4848 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4849 B = *M; 4850 4851 PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf)); 4852 if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf)); 4853 PetscCall(MatGetVecType(mat, &vtype)); 4854 PetscCall(MatSetVecType(B, vtype)); 4855 4856 B->stencil.dim = mat->stencil.dim; 4857 B->stencil.noc = mat->stencil.noc; 4858 for (i = 0; i <= mat->stencil.dim; i++) { 4859 B->stencil.dims[i] = mat->stencil.dims[i]; 4860 B->stencil.starts[i] = mat->stencil.starts[i]; 4861 } 4862 4863 B->nooffproczerorows = mat->nooffproczerorows; 4864 B->nooffprocentries = mat->nooffprocentries; 4865 4866 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm)); 4867 if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm)); 4868 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4869 PetscFunctionReturn(PETSC_SUCCESS); 4870 } 4871 4872 /*@ 4873 MatGetDiagonal - Gets the diagonal of a matrix as a `Vec` 4874 4875 Logically Collective 4876 4877 Input Parameters: 4878 + mat - the matrix 4879 - v - the vector for storing the diagonal 4880 4881 Output Parameter: 4882 . v - the diagonal of the matrix 4883 4884 Level: intermediate 4885 4886 Note: 4887 Currently only correct in parallel for square matrices. 4888 4889 .seealso: `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()` 4890 @*/ 4891 PetscErrorCode MatGetDiagonal(Mat mat, Vec v) 4892 { 4893 PetscFunctionBegin; 4894 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4895 PetscValidType(mat, 1); 4896 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4897 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4898 MatCheckPreallocated(mat, 1); 4899 4900 PetscUseTypeMethod(mat, getdiagonal, v); 4901 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4902 PetscFunctionReturn(PETSC_SUCCESS); 4903 } 4904 4905 /*@C 4906 MatGetRowMin - Gets the minimum value (of the real part) of each 4907 row of the matrix 4908 4909 Logically Collective 4910 4911 Input Parameter: 4912 . mat - the matrix 4913 4914 Output Parameters: 4915 + v - the vector for storing the maximums 4916 - idx - the indices of the column found for each row (optional) 4917 4918 Level: intermediate 4919 4920 Note: 4921 The result of this call are the same as if one converted the matrix to dense format 4922 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 4923 4924 This code is only implemented for a couple of matrix formats. 4925 4926 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, 4927 `MatGetRowMax()` 4928 @*/ 4929 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[]) 4930 { 4931 PetscFunctionBegin; 4932 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4933 PetscValidType(mat, 1); 4934 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4935 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4936 4937 if (!mat->cmap->N) { 4938 PetscCall(VecSet(v, PETSC_MAX_REAL)); 4939 if (idx) { 4940 PetscInt i, m = mat->rmap->n; 4941 for (i = 0; i < m; i++) idx[i] = -1; 4942 } 4943 } else { 4944 MatCheckPreallocated(mat, 1); 4945 } 4946 PetscUseTypeMethod(mat, getrowmin, v, idx); 4947 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4948 PetscFunctionReturn(PETSC_SUCCESS); 4949 } 4950 4951 /*@C 4952 MatGetRowMinAbs - Gets the minimum value (in absolute value) of each 4953 row of the matrix 4954 4955 Logically Collective 4956 4957 Input Parameter: 4958 . mat - the matrix 4959 4960 Output Parameters: 4961 + v - the vector for storing the minimums 4962 - idx - the indices of the column found for each row (or NULL if not needed) 4963 4964 Level: intermediate 4965 4966 Notes: 4967 if a row is completely empty or has only 0.0 values then the idx[] value for that 4968 row is 0 (the first column). 4969 4970 This code is only implemented for a couple of matrix formats. 4971 4972 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()` 4973 @*/ 4974 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[]) 4975 { 4976 PetscFunctionBegin; 4977 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4978 PetscValidType(mat, 1); 4979 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4980 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4981 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4982 4983 if (!mat->cmap->N) { 4984 PetscCall(VecSet(v, 0.0)); 4985 if (idx) { 4986 PetscInt i, m = mat->rmap->n; 4987 for (i = 0; i < m; i++) idx[i] = -1; 4988 } 4989 } else { 4990 MatCheckPreallocated(mat, 1); 4991 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 4992 PetscUseTypeMethod(mat, getrowminabs, v, idx); 4993 } 4994 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4995 PetscFunctionReturn(PETSC_SUCCESS); 4996 } 4997 4998 /*@C 4999 MatGetRowMax - Gets the maximum value (of the real part) of each 5000 row of the matrix 5001 5002 Logically Collective 5003 5004 Input Parameter: 5005 . mat - the matrix 5006 5007 Output Parameters: 5008 + v - the vector for storing the maximums 5009 - idx - the indices of the column found for each row (optional) 5010 5011 Level: intermediate 5012 5013 Notes: 5014 The result of this call are the same as if one converted the matrix to dense format 5015 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5016 5017 This code is only implemented for a couple of matrix formats. 5018 5019 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5020 @*/ 5021 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[]) 5022 { 5023 PetscFunctionBegin; 5024 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5025 PetscValidType(mat, 1); 5026 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5027 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5028 5029 if (!mat->cmap->N) { 5030 PetscCall(VecSet(v, PETSC_MIN_REAL)); 5031 if (idx) { 5032 PetscInt i, m = mat->rmap->n; 5033 for (i = 0; i < m; i++) idx[i] = -1; 5034 } 5035 } else { 5036 MatCheckPreallocated(mat, 1); 5037 PetscUseTypeMethod(mat, getrowmax, v, idx); 5038 } 5039 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5040 PetscFunctionReturn(PETSC_SUCCESS); 5041 } 5042 5043 /*@C 5044 MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each 5045 row of the matrix 5046 5047 Logically Collective 5048 5049 Input Parameter: 5050 . mat - the matrix 5051 5052 Output Parameters: 5053 + v - the vector for storing the maximums 5054 - idx - the indices of the column found for each row (or NULL if not needed) 5055 5056 Level: intermediate 5057 5058 Notes: 5059 if a row is completely empty or has only 0.0 values then the idx[] value for that 5060 row is 0 (the first column). 5061 5062 This code is only implemented for a couple of matrix formats. 5063 5064 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5065 @*/ 5066 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[]) 5067 { 5068 PetscFunctionBegin; 5069 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5070 PetscValidType(mat, 1); 5071 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5072 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5073 5074 if (!mat->cmap->N) { 5075 PetscCall(VecSet(v, 0.0)); 5076 if (idx) { 5077 PetscInt i, m = mat->rmap->n; 5078 for (i = 0; i < m; i++) idx[i] = -1; 5079 } 5080 } else { 5081 MatCheckPreallocated(mat, 1); 5082 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5083 PetscUseTypeMethod(mat, getrowmaxabs, v, idx); 5084 } 5085 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5086 PetscFunctionReturn(PETSC_SUCCESS); 5087 } 5088 5089 /*@ 5090 MatGetRowSum - Gets the sum of each row of the matrix 5091 5092 Logically or Neighborhood Collective 5093 5094 Input Parameters: 5095 . mat - the matrix 5096 5097 Output Parameter: 5098 . v - the vector for storing the sum of rows 5099 5100 Level: intermediate 5101 5102 Notes: 5103 This code is slow since it is not currently specialized for different formats 5104 5105 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()` 5106 @*/ 5107 PetscErrorCode MatGetRowSum(Mat mat, Vec v) 5108 { 5109 Vec ones; 5110 5111 PetscFunctionBegin; 5112 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5113 PetscValidType(mat, 1); 5114 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5115 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5116 MatCheckPreallocated(mat, 1); 5117 PetscCall(MatCreateVecs(mat, &ones, NULL)); 5118 PetscCall(VecSet(ones, 1.)); 5119 PetscCall(MatMult(mat, ones, v)); 5120 PetscCall(VecDestroy(&ones)); 5121 PetscFunctionReturn(PETSC_SUCCESS); 5122 } 5123 5124 /*@ 5125 MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) 5126 when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B) 5127 5128 Collective 5129 5130 Input Parameter: 5131 . mat - the matrix to provide the transpose 5132 5133 Output Parameter: 5134 . 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 5135 5136 Level: advanced 5137 5138 Note: 5139 Normally he use of `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) requires that B was obtained with a call to `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B). This 5140 routine allows bypassing that call. 5141 5142 .seealso: `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5143 @*/ 5144 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B) 5145 { 5146 PetscContainer rB = NULL; 5147 MatParentState *rb = NULL; 5148 5149 PetscFunctionBegin; 5150 PetscCall(PetscNew(&rb)); 5151 rb->id = ((PetscObject)mat)->id; 5152 rb->state = 0; 5153 PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate)); 5154 PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB)); 5155 PetscCall(PetscContainerSetPointer(rB, rb)); 5156 PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault)); 5157 PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB)); 5158 PetscCall(PetscObjectDereference((PetscObject)rB)); 5159 PetscFunctionReturn(PETSC_SUCCESS); 5160 } 5161 5162 /*@ 5163 MatTranspose - Computes an in-place or out-of-place transpose of a matrix. 5164 5165 Collective 5166 5167 Input Parameters: 5168 + mat - the matrix to transpose 5169 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5170 5171 Output Parameter: 5172 . B - the transpose 5173 5174 Notes: 5175 If you use `MAT_INPLACE_MATRIX` then you must pass in &mat for B 5176 5177 `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 5178 transpose, call `MatTransposeSetPrecursor`(mat,B) before calling this routine. 5179 5180 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. 5181 5182 Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed. 5183 5184 If mat is unchanged from the last call this function returns immediately without recomputing the result 5185 5186 If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()` 5187 5188 Level: intermediate 5189 5190 .seealso: `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`, 5191 `MatTransposeSymbolic()` 5192 @*/ 5193 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B) 5194 { 5195 PetscContainer rB = NULL; 5196 MatParentState *rb = NULL; 5197 5198 PetscFunctionBegin; 5199 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5200 PetscValidType(mat, 1); 5201 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5202 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5203 PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first"); 5204 PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX"); 5205 MatCheckPreallocated(mat, 1); 5206 if (reuse == MAT_REUSE_MATRIX) { 5207 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5208 PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor()."); 5209 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5210 PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5211 if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS); 5212 } 5213 5214 PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0)); 5215 if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) { 5216 PetscUseTypeMethod(mat, transpose, reuse, B); 5217 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5218 } 5219 PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0)); 5220 5221 if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B)); 5222 if (reuse != MAT_INPLACE_MATRIX) { 5223 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5224 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5225 rb->state = ((PetscObject)mat)->state; 5226 rb->nonzerostate = mat->nonzerostate; 5227 } 5228 PetscFunctionReturn(PETSC_SUCCESS); 5229 } 5230 5231 /*@ 5232 MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix. 5233 5234 Collective on A 5235 5236 Input Parameters: 5237 . A - the matrix to transpose 5238 5239 Output Parameter: 5240 . 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 5241 numerical portion. 5242 5243 Level: intermediate 5244 5245 Note: 5246 This is not supported for many matrix types, use `MatTranspose()` in those cases 5247 5248 .seealso: `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5249 @*/ 5250 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B) 5251 { 5252 PetscFunctionBegin; 5253 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5254 PetscValidType(A, 1); 5255 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5256 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5257 PetscCheck(A->ops->transposesymbolic, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 5258 PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0)); 5259 PetscCall((*A->ops->transposesymbolic)(A, B)); 5260 PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0)); 5261 5262 PetscCall(MatTransposeSetPrecursor(A, *B)); 5263 PetscFunctionReturn(PETSC_SUCCESS); 5264 } 5265 5266 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B) 5267 { 5268 PetscContainer rB; 5269 MatParentState *rb; 5270 5271 PetscFunctionBegin; 5272 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5273 PetscValidType(A, 1); 5274 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5275 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5276 PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB)); 5277 PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()"); 5278 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5279 PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5280 PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure"); 5281 PetscFunctionReturn(PETSC_SUCCESS); 5282 } 5283 5284 /*@ 5285 MatIsTranspose - Test whether a matrix is another one's transpose, 5286 or its own, in which case it tests symmetry. 5287 5288 Collective on A 5289 5290 Input Parameters: 5291 + A - the matrix to test 5292 - B - the matrix to test against, this can equal the first parameter 5293 5294 Output Parameters: 5295 . flg - the result 5296 5297 Notes: 5298 Only available for `MATAIJ` matrices. 5299 5300 The sequential algorithm has a running time of the order of the number of nonzeros; the parallel 5301 test involves parallel copies of the block-offdiagonal parts of the matrix. 5302 5303 Level: intermediate 5304 5305 .seealso: `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()` 5306 @*/ 5307 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5308 { 5309 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5310 5311 PetscFunctionBegin; 5312 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5313 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5314 PetscValidBoolPointer(flg, 4); 5315 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f)); 5316 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g)); 5317 *flg = PETSC_FALSE; 5318 if (f && g) { 5319 PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test"); 5320 PetscCall((*f)(A, B, tol, flg)); 5321 } else { 5322 MatType mattype; 5323 5324 PetscCall(MatGetType(f ? B : A, &mattype)); 5325 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype); 5326 } 5327 PetscFunctionReturn(PETSC_SUCCESS); 5328 } 5329 5330 /*@ 5331 MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate. 5332 5333 Collective 5334 5335 Input Parameters: 5336 + mat - the matrix to transpose and complex conjugate 5337 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5338 5339 Output Parameter: 5340 . B - the Hermitian transpose 5341 5342 Level: intermediate 5343 5344 .seealso: `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse` 5345 @*/ 5346 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B) 5347 { 5348 PetscFunctionBegin; 5349 PetscCall(MatTranspose(mat, reuse, B)); 5350 #if defined(PETSC_USE_COMPLEX) 5351 PetscCall(MatConjugate(*B)); 5352 #endif 5353 PetscFunctionReturn(PETSC_SUCCESS); 5354 } 5355 5356 /*@ 5357 MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose, 5358 5359 Collective on A 5360 5361 Input Parameters: 5362 + A - the matrix to test 5363 - B - the matrix to test against, this can equal the first parameter 5364 5365 Output Parameters: 5366 . flg - the result 5367 5368 Notes: 5369 Only available for `MATAIJ` matrices. 5370 5371 The sequential algorithm 5372 has a running time of the order of the number of nonzeros; the parallel 5373 test involves parallel copies of the block-offdiagonal parts of the matrix. 5374 5375 Level: intermediate 5376 5377 .seealso: `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()` 5378 @*/ 5379 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5380 { 5381 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5382 5383 PetscFunctionBegin; 5384 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5385 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5386 PetscValidBoolPointer(flg, 4); 5387 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f)); 5388 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g)); 5389 if (f && g) { 5390 PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test"); 5391 PetscCall((*f)(A, B, tol, flg)); 5392 } 5393 PetscFunctionReturn(PETSC_SUCCESS); 5394 } 5395 5396 /*@ 5397 MatPermute - Creates a new matrix with rows and columns permuted from the 5398 original. 5399 5400 Collective 5401 5402 Input Parameters: 5403 + mat - the matrix to permute 5404 . row - row permutation, each processor supplies only the permutation for its rows 5405 - col - column permutation, each processor supplies only the permutation for its columns 5406 5407 Output Parameters: 5408 . B - the permuted matrix 5409 5410 Level: advanced 5411 5412 Note: 5413 The index sets map from row/col of permuted matrix to row/col of original matrix. 5414 The index sets should be on the same communicator as mat and have the same local sizes. 5415 5416 Developer Note: 5417 If you want to implement `MatPermute()` for a matrix type, and your approach doesn't 5418 exploit the fact that row and col are permutations, consider implementing the 5419 more general `MatCreateSubMatrix()` instead. 5420 5421 .seealso: `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()` 5422 @*/ 5423 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B) 5424 { 5425 PetscFunctionBegin; 5426 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5427 PetscValidType(mat, 1); 5428 PetscValidHeaderSpecific(row, IS_CLASSID, 2); 5429 PetscValidHeaderSpecific(col, IS_CLASSID, 3); 5430 PetscValidPointer(B, 4); 5431 PetscCheckSameComm(mat, 1, row, 2); 5432 if (row != col) PetscCheckSameComm(row, 2, col, 3); 5433 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5434 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5435 PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name); 5436 MatCheckPreallocated(mat, 1); 5437 5438 if (mat->ops->permute) { 5439 PetscUseTypeMethod(mat, permute, row, col, B); 5440 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5441 } else { 5442 PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B)); 5443 } 5444 PetscFunctionReturn(PETSC_SUCCESS); 5445 } 5446 5447 /*@ 5448 MatEqual - Compares two matrices. 5449 5450 Collective on A 5451 5452 Input Parameters: 5453 + A - the first matrix 5454 - B - the second matrix 5455 5456 Output Parameter: 5457 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise. 5458 5459 Level: intermediate 5460 5461 .seealso: `Mat` 5462 @*/ 5463 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg) 5464 { 5465 PetscFunctionBegin; 5466 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5467 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5468 PetscValidType(A, 1); 5469 PetscValidType(B, 2); 5470 PetscValidBoolPointer(flg, 3); 5471 PetscCheckSameComm(A, 1, B, 2); 5472 MatCheckPreallocated(A, 1); 5473 MatCheckPreallocated(B, 2); 5474 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5475 PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5476 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, 5477 B->cmap->N); 5478 if (A->ops->equal && A->ops->equal == B->ops->equal) { 5479 PetscUseTypeMethod(A, equal, B, flg); 5480 } else { 5481 PetscCall(MatMultEqual(A, B, 10, flg)); 5482 } 5483 PetscFunctionReturn(PETSC_SUCCESS); 5484 } 5485 5486 /*@ 5487 MatDiagonalScale - Scales a matrix on the left and right by diagonal 5488 matrices that are stored as vectors. Either of the two scaling 5489 matrices can be NULL. 5490 5491 Collective 5492 5493 Input Parameters: 5494 + mat - the matrix to be scaled 5495 . l - the left scaling vector (or NULL) 5496 - r - the right scaling vector (or NULL) 5497 5498 Note: 5499 `MatDiagonalScale()` computes A = LAR, where 5500 L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector) 5501 The L scales the rows of the matrix, the R scales the columns of the matrix. 5502 5503 Level: intermediate 5504 5505 .seealso: `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()` 5506 @*/ 5507 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r) 5508 { 5509 PetscFunctionBegin; 5510 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5511 PetscValidType(mat, 1); 5512 if (l) { 5513 PetscValidHeaderSpecific(l, VEC_CLASSID, 2); 5514 PetscCheckSameComm(mat, 1, l, 2); 5515 } 5516 if (r) { 5517 PetscValidHeaderSpecific(r, VEC_CLASSID, 3); 5518 PetscCheckSameComm(mat, 1, r, 3); 5519 } 5520 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5521 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5522 MatCheckPreallocated(mat, 1); 5523 if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS); 5524 5525 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5526 PetscUseTypeMethod(mat, diagonalscale, l, r); 5527 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5528 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5529 if (l != r) mat->symmetric = PETSC_BOOL3_FALSE; 5530 PetscFunctionReturn(PETSC_SUCCESS); 5531 } 5532 5533 /*@ 5534 MatScale - Scales all elements of a matrix by a given number. 5535 5536 Logically Collective 5537 5538 Input Parameters: 5539 + mat - the matrix to be scaled 5540 - a - the scaling value 5541 5542 Output Parameter: 5543 . mat - the scaled matrix 5544 5545 Level: intermediate 5546 5547 .seealso: `Mat`, `MatDiagonalScale()` 5548 @*/ 5549 PetscErrorCode MatScale(Mat mat, PetscScalar a) 5550 { 5551 PetscFunctionBegin; 5552 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5553 PetscValidType(mat, 1); 5554 PetscCheck(a == (PetscScalar)1.0 || mat->ops->scale, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 5555 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5556 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5557 PetscValidLogicalCollectiveScalar(mat, a, 2); 5558 MatCheckPreallocated(mat, 1); 5559 5560 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5561 if (a != (PetscScalar)1.0) { 5562 PetscUseTypeMethod(mat, scale, a); 5563 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5564 } 5565 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5566 PetscFunctionReturn(PETSC_SUCCESS); 5567 } 5568 5569 /*@ 5570 MatNorm - Calculates various norms of a matrix. 5571 5572 Collective 5573 5574 Input Parameters: 5575 + mat - the matrix 5576 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY` 5577 5578 Output Parameter: 5579 . nrm - the resulting norm 5580 5581 Level: intermediate 5582 5583 .seealso: `Mat` 5584 @*/ 5585 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm) 5586 { 5587 PetscFunctionBegin; 5588 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5589 PetscValidType(mat, 1); 5590 PetscValidRealPointer(nrm, 3); 5591 5592 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5593 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5594 MatCheckPreallocated(mat, 1); 5595 5596 PetscUseTypeMethod(mat, norm, type, nrm); 5597 PetscFunctionReturn(PETSC_SUCCESS); 5598 } 5599 5600 /* 5601 This variable is used to prevent counting of MatAssemblyBegin() that 5602 are called from within a MatAssemblyEnd(). 5603 */ 5604 static PetscInt MatAssemblyEnd_InUse = 0; 5605 /*@ 5606 MatAssemblyBegin - Begins assembling the matrix. This routine should 5607 be called after completing all calls to `MatSetValues()`. 5608 5609 Collective 5610 5611 Input Parameters: 5612 + mat - the matrix 5613 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5614 5615 Notes: 5616 `MatSetValues()` generally caches the values that belong to other MPI ranks. The matrix is ready to 5617 use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called. 5618 5619 Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES` 5620 in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before 5621 using the matrix. 5622 5623 ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the 5624 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 5625 a global collective operation requiring all processes that share the matrix. 5626 5627 Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed 5628 out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros 5629 before `MAT_FINAL_ASSEMBLY` so the space is not compressed out. 5630 5631 Level: beginner 5632 5633 .seealso: `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()` 5634 @*/ 5635 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type) 5636 { 5637 PetscFunctionBegin; 5638 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5639 PetscValidType(mat, 1); 5640 MatCheckPreallocated(mat, 1); 5641 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?"); 5642 if (mat->assembled) { 5643 mat->was_assembled = PETSC_TRUE; 5644 mat->assembled = PETSC_FALSE; 5645 } 5646 5647 if (!MatAssemblyEnd_InUse) { 5648 PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0)); 5649 PetscTryTypeMethod(mat, assemblybegin, type); 5650 PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0)); 5651 } else PetscTryTypeMethod(mat, assemblybegin, type); 5652 PetscFunctionReturn(PETSC_SUCCESS); 5653 } 5654 5655 /*@ 5656 MatAssembled - Indicates if a matrix has been assembled and is ready for 5657 use; for example, in matrix-vector product. 5658 5659 Not Collective 5660 5661 Input Parameter: 5662 . mat - the matrix 5663 5664 Output Parameter: 5665 . assembled - `PETSC_TRUE` or `PETSC_FALSE` 5666 5667 Level: advanced 5668 5669 .seealso: `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()` 5670 @*/ 5671 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled) 5672 { 5673 PetscFunctionBegin; 5674 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5675 PetscValidBoolPointer(assembled, 2); 5676 *assembled = mat->assembled; 5677 PetscFunctionReturn(PETSC_SUCCESS); 5678 } 5679 5680 /*@ 5681 MatAssemblyEnd - Completes assembling the matrix. This routine should 5682 be called after `MatAssemblyBegin()`. 5683 5684 Collective on Mat 5685 5686 Input Parameters: 5687 + mat - the matrix 5688 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5689 5690 Options Database Keys: 5691 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatEndAssembly()` 5692 . -mat_view ::ascii_info_detail - Prints more detailed info 5693 . -mat_view - Prints matrix in ASCII format 5694 . -mat_view ::ascii_matlab - Prints matrix in Matlab format 5695 . -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 5696 . -display <name> - Sets display name (default is host) 5697 . -draw_pause <sec> - Sets number of seconds to pause after display 5698 . -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See [Using MATLAB with PETSc](ch_matlab)) 5699 . -viewer_socket_machine <machine> - Machine to use for socket 5700 . -viewer_socket_port <port> - Port number to use for socket 5701 - -mat_view binary:filename[:append] - Save matrix to file in binary format 5702 5703 Level: beginner 5704 5705 .seealso: `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()` 5706 @*/ 5707 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type) 5708 { 5709 static PetscInt inassm = 0; 5710 PetscBool flg = PETSC_FALSE; 5711 5712 PetscFunctionBegin; 5713 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5714 PetscValidType(mat, 1); 5715 5716 inassm++; 5717 MatAssemblyEnd_InUse++; 5718 if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */ 5719 PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0)); 5720 PetscTryTypeMethod(mat, assemblyend, type); 5721 PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0)); 5722 } else PetscTryTypeMethod(mat, assemblyend, type); 5723 5724 /* Flush assembly is not a true assembly */ 5725 if (type != MAT_FLUSH_ASSEMBLY) { 5726 if (mat->num_ass) { 5727 if (!mat->symmetry_eternal) { 5728 mat->symmetric = PETSC_BOOL3_UNKNOWN; 5729 mat->hermitian = PETSC_BOOL3_UNKNOWN; 5730 } 5731 if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN; 5732 if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN; 5733 } 5734 mat->num_ass++; 5735 mat->assembled = PETSC_TRUE; 5736 mat->ass_nonzerostate = mat->nonzerostate; 5737 } 5738 5739 mat->insertmode = NOT_SET_VALUES; 5740 MatAssemblyEnd_InUse--; 5741 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5742 if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) { 5743 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 5744 5745 if (mat->checksymmetryonassembly) { 5746 PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg)); 5747 if (flg) { 5748 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5749 } else { 5750 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5751 } 5752 } 5753 if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL)); 5754 } 5755 inassm--; 5756 PetscFunctionReturn(PETSC_SUCCESS); 5757 } 5758 5759 /*@ 5760 MatSetOption - Sets a parameter option for a matrix. Some options 5761 may be specific to certain storage formats. Some options 5762 determine how values will be inserted (or added). Sorted, 5763 row-oriented input will generally assemble the fastest. The default 5764 is row-oriented. 5765 5766 Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption` 5767 5768 Input Parameters: 5769 + mat - the matrix 5770 . option - the option, one of those listed below (and possibly others), 5771 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5772 5773 Options Describing Matrix Structure: 5774 + `MAT_SPD` - symmetric positive definite 5775 . `MAT_SYMMETRIC` - symmetric in terms of both structure and value 5776 . `MAT_HERMITIAN` - transpose is the complex conjugation 5777 . `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure 5778 . `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix 5779 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix 5780 - `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix 5781 5782 These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they 5783 do not need to be computed (usually at a high cost) 5784 5785 Options For Use with `MatSetValues()`: 5786 Insert a logically dense subblock, which can be 5787 . `MAT_ROW_ORIENTED` - row-oriented (default) 5788 5789 Note these options reflect the data you pass in with `MatSetValues()`; it has 5790 nothing to do with how the data is stored internally in the matrix 5791 data structure. 5792 5793 When (re)assembling a matrix, we can restrict the input for 5794 efficiency/debugging purposes. These options include 5795 + `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow) 5796 . `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated 5797 . `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries 5798 . `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry 5799 . `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly 5800 . `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if 5801 any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves 5802 performance for very large process counts. 5803 - `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset 5804 of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly 5805 functions, instead sending only neighbor messages. 5806 5807 Notes: 5808 Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg! 5809 5810 Some options are relevant only for particular matrix types and 5811 are thus ignored by others. Other options are not supported by 5812 certain matrix types and will generate an error message if set. 5813 5814 If using Fortran to compute a matrix, one may need to 5815 use the column-oriented option (or convert to the row-oriented 5816 format). 5817 5818 `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion 5819 that would generate a new entry in the nonzero structure is instead 5820 ignored. Thus, if memory has not already been allocated for this particular 5821 data, then the insertion is ignored. For dense matrices, in which 5822 the entire array is allocated, no entries are ever ignored. 5823 Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction 5824 5825 `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion 5826 that would generate a new entry in the nonzero structure instead produces 5827 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 5828 5829 `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion 5830 that would generate a new entry that has not been preallocated will 5831 instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats 5832 only.) This is a useful flag when debugging matrix memory preallocation. 5833 If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 5834 5835 `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for 5836 other processors should be dropped, rather than stashed. 5837 This is useful if you know that the "owning" processor is also 5838 always generating the correct matrix entries, so that PETSc need 5839 not transfer duplicate entries generated on another processor. 5840 5841 `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the 5842 searches during matrix assembly. When this flag is set, the hash table 5843 is created during the first matrix assembly. This hash table is 5844 used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()` 5845 to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag 5846 should be used with `MAT_USE_HASH_TABLE` flag. This option is currently 5847 supported by `MATMPIBAIJ` format only. 5848 5849 `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries 5850 are kept in the nonzero structure 5851 5852 `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating 5853 a zero location in the matrix 5854 5855 `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types 5856 5857 `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the 5858 zero row routines and thus improves performance for very large process counts. 5859 5860 `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular 5861 part of the matrix (since they should match the upper triangular part). 5862 5863 `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a 5864 single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common 5865 with finite difference schemes with non-periodic boundary conditions. 5866 5867 Developer Note: 5868 `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other 5869 places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRIC` or `MAT_SPD` would need to be changed back 5870 to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had 5871 not changed. 5872 5873 Level: intermediate 5874 5875 .seealso: `MatOption`, `Mat`, `MatGetOption()` 5876 @*/ 5877 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg) 5878 { 5879 PetscFunctionBegin; 5880 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5881 if (op > 0) { 5882 PetscValidLogicalCollectiveEnum(mat, op, 2); 5883 PetscValidLogicalCollectiveBool(mat, flg, 3); 5884 } 5885 5886 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); 5887 5888 switch (op) { 5889 case MAT_FORCE_DIAGONAL_ENTRIES: 5890 mat->force_diagonals = flg; 5891 PetscFunctionReturn(PETSC_SUCCESS); 5892 case MAT_NO_OFF_PROC_ENTRIES: 5893 mat->nooffprocentries = flg; 5894 PetscFunctionReturn(PETSC_SUCCESS); 5895 case MAT_SUBSET_OFF_PROC_ENTRIES: 5896 mat->assembly_subset = flg; 5897 if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */ 5898 #if !defined(PETSC_HAVE_MPIUNI) 5899 PetscCall(MatStashScatterDestroy_BTS(&mat->stash)); 5900 #endif 5901 mat->stash.first_assembly_done = PETSC_FALSE; 5902 } 5903 PetscFunctionReturn(PETSC_SUCCESS); 5904 case MAT_NO_OFF_PROC_ZERO_ROWS: 5905 mat->nooffproczerorows = flg; 5906 PetscFunctionReturn(PETSC_SUCCESS); 5907 case MAT_SPD: 5908 if (flg) { 5909 mat->spd = PETSC_BOOL3_TRUE; 5910 mat->symmetric = PETSC_BOOL3_TRUE; 5911 mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5912 } else { 5913 mat->spd = PETSC_BOOL3_FALSE; 5914 } 5915 break; 5916 case MAT_SYMMETRIC: 5917 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5918 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5919 #if !defined(PETSC_USE_COMPLEX) 5920 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5921 #endif 5922 break; 5923 case MAT_HERMITIAN: 5924 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5925 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5926 #if !defined(PETSC_USE_COMPLEX) 5927 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5928 #endif 5929 break; 5930 case MAT_STRUCTURALLY_SYMMETRIC: 5931 mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5932 break; 5933 case MAT_SYMMETRY_ETERNAL: 5934 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"); 5935 mat->symmetry_eternal = flg; 5936 if (flg) mat->structural_symmetry_eternal = PETSC_TRUE; 5937 break; 5938 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 5939 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"); 5940 mat->structural_symmetry_eternal = flg; 5941 break; 5942 case MAT_SPD_ETERNAL: 5943 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"); 5944 mat->spd_eternal = flg; 5945 if (flg) { 5946 mat->structural_symmetry_eternal = PETSC_TRUE; 5947 mat->symmetry_eternal = PETSC_TRUE; 5948 } 5949 break; 5950 case MAT_STRUCTURE_ONLY: 5951 mat->structure_only = flg; 5952 break; 5953 case MAT_SORTED_FULL: 5954 mat->sortedfull = flg; 5955 break; 5956 default: 5957 break; 5958 } 5959 PetscTryTypeMethod(mat, setoption, op, flg); 5960 PetscFunctionReturn(PETSC_SUCCESS); 5961 } 5962 5963 /*@ 5964 MatGetOption - Gets a parameter option that has been set for a matrix. 5965 5966 Logically Collective 5967 5968 Input Parameters: 5969 + mat - the matrix 5970 - option - the option, this only responds to certain options, check the code for which ones 5971 5972 Output Parameter: 5973 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5974 5975 Notes: 5976 Can only be called after `MatSetSizes()` and `MatSetType()` have been set. 5977 5978 Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or 5979 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 5980 5981 Level: intermediate 5982 5983 .seealso: `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, 5984 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 5985 @*/ 5986 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg) 5987 { 5988 PetscFunctionBegin; 5989 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5990 PetscValidType(mat, 1); 5991 5992 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); 5993 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()"); 5994 5995 switch (op) { 5996 case MAT_NO_OFF_PROC_ENTRIES: 5997 *flg = mat->nooffprocentries; 5998 break; 5999 case MAT_NO_OFF_PROC_ZERO_ROWS: 6000 *flg = mat->nooffproczerorows; 6001 break; 6002 case MAT_SYMMETRIC: 6003 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()"); 6004 break; 6005 case MAT_HERMITIAN: 6006 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()"); 6007 break; 6008 case MAT_STRUCTURALLY_SYMMETRIC: 6009 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()"); 6010 break; 6011 case MAT_SPD: 6012 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()"); 6013 break; 6014 case MAT_SYMMETRY_ETERNAL: 6015 *flg = mat->symmetry_eternal; 6016 break; 6017 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6018 *flg = mat->symmetry_eternal; 6019 break; 6020 default: 6021 break; 6022 } 6023 PetscFunctionReturn(PETSC_SUCCESS); 6024 } 6025 6026 /*@ 6027 MatZeroEntries - Zeros all entries of a matrix. For sparse matrices 6028 this routine retains the old nonzero structure. 6029 6030 Logically Collective 6031 6032 Input Parameters: 6033 . mat - the matrix 6034 6035 Level: intermediate 6036 6037 Note: 6038 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. 6039 See the Performance chapter of the users manual for information on preallocating matrices. 6040 6041 .seealso: `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()` 6042 @*/ 6043 PetscErrorCode MatZeroEntries(Mat mat) 6044 { 6045 PetscFunctionBegin; 6046 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6047 PetscValidType(mat, 1); 6048 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6049 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"); 6050 MatCheckPreallocated(mat, 1); 6051 6052 PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0)); 6053 PetscUseTypeMethod(mat, zeroentries); 6054 PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0)); 6055 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6056 PetscFunctionReturn(PETSC_SUCCESS); 6057 } 6058 6059 /*@ 6060 MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal) 6061 of a set of rows and columns of a matrix. 6062 6063 Collective 6064 6065 Input Parameters: 6066 + mat - the matrix 6067 . numRows - the number of rows to remove 6068 . rows - the global row indices 6069 . diag - value put in the diagonal of the eliminated rows 6070 . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call 6071 - b - optional vector of right hand side, that will be adjusted by provided solution 6072 6073 Notes: 6074 This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6075 6076 For each zeroed row, the value of the corresponding b is set to diag times the value of the corresponding x. 6077 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 6078 6079 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6080 Krylov method to take advantage of the known solution on the zeroed rows. 6081 6082 For the parallel case, all processes that share the matrix (i.e., 6083 those in the communicator used for matrix creation) MUST call this 6084 routine, regardless of whether any rows being zeroed are owned by 6085 them. 6086 6087 Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix. 6088 6089 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6090 list only rows local to itself). 6091 6092 The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine. 6093 6094 Level: intermediate 6095 6096 .seealso: `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6097 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6098 @*/ 6099 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6100 { 6101 PetscFunctionBegin; 6102 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6103 PetscValidType(mat, 1); 6104 if (numRows) PetscValidIntPointer(rows, 3); 6105 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6106 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6107 MatCheckPreallocated(mat, 1); 6108 6109 PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b); 6110 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6111 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6112 PetscFunctionReturn(PETSC_SUCCESS); 6113 } 6114 6115 /*@ 6116 MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal) 6117 of a set of rows and columns of a matrix. 6118 6119 Collective 6120 6121 Input Parameters: 6122 + mat - the matrix 6123 . is - the rows to zero 6124 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6125 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6126 - b - optional vector of right hand side, that will be adjusted by provided solution 6127 6128 Note: 6129 See `MatZeroRowsColumns()` for details on how this routine operates. 6130 6131 Level: intermediate 6132 6133 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6134 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()` 6135 @*/ 6136 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6137 { 6138 PetscInt numRows; 6139 const PetscInt *rows; 6140 6141 PetscFunctionBegin; 6142 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6143 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6144 PetscValidType(mat, 1); 6145 PetscValidType(is, 2); 6146 PetscCall(ISGetLocalSize(is, &numRows)); 6147 PetscCall(ISGetIndices(is, &rows)); 6148 PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b)); 6149 PetscCall(ISRestoreIndices(is, &rows)); 6150 PetscFunctionReturn(PETSC_SUCCESS); 6151 } 6152 6153 /*@ 6154 MatZeroRows - Zeros all entries (except possibly the main diagonal) 6155 of a set of rows of a matrix. 6156 6157 Collective 6158 6159 Input Parameters: 6160 + mat - the matrix 6161 . numRows - the number of rows to remove 6162 . rows - the global row indices 6163 . diag - value put in the diagonal of the eliminated rows 6164 . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call 6165 - b - optional vector of right hand side, that will be adjusted by provided solution 6166 6167 Notes: 6168 This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6169 6170 For each zeroed row, the value of the corresponding b is set to diag times the value of the corresponding x. 6171 6172 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6173 Krylov method to take advantage of the known solution on the zeroed rows. 6174 6175 May be followed by using a `PC` of type `PCREDISTRIBUTE` to solve the reducing problem (after completely eliminating the zeroed rows and their corresponding columns) 6176 from the matrix. 6177 6178 Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix 6179 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 6180 formats this does not alter the nonzero structure. 6181 6182 If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure 6183 of the matrix is not changed the values are 6184 merely zeroed. 6185 6186 The user can set a value in the diagonal entry (or for the `MATAIJ` format 6187 formats can optionally remove the main diagonal entry from the 6188 nonzero structure as well, by passing 0.0 as the final argument). 6189 6190 For the parallel case, all processes that share the matrix (i.e., 6191 those in the communicator used for matrix creation) MUST call this 6192 routine, regardless of whether any rows being zeroed are owned by 6193 them. 6194 6195 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6196 list only rows local to itself). 6197 6198 You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it 6199 owns that are to be zeroed. This saves a global synchronization in the implementation. 6200 6201 Level: intermediate 6202 6203 .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6204 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE` 6205 @*/ 6206 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6207 { 6208 PetscFunctionBegin; 6209 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6210 PetscValidType(mat, 1); 6211 if (numRows) PetscValidIntPointer(rows, 3); 6212 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6213 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6214 MatCheckPreallocated(mat, 1); 6215 6216 PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b); 6217 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6218 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6219 PetscFunctionReturn(PETSC_SUCCESS); 6220 } 6221 6222 /*@ 6223 MatZeroRowsIS - Zeros all entries (except possibly the main diagonal) 6224 of a set of rows of a matrix. 6225 6226 Collective on Mat 6227 6228 Input Parameters: 6229 + mat - the matrix 6230 . is - index set of rows to remove (if NULL then no row is removed) 6231 . diag - value put in all diagonals of eliminated rows 6232 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6233 - b - optional vector of right hand side, that will be adjusted by provided solution 6234 6235 Note: 6236 See `MatZeroRows()` for details on how this routine operates. 6237 6238 Level: intermediate 6239 6240 .seealso: `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6241 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6242 @*/ 6243 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6244 { 6245 PetscInt numRows = 0; 6246 const PetscInt *rows = NULL; 6247 6248 PetscFunctionBegin; 6249 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6250 PetscValidType(mat, 1); 6251 if (is) { 6252 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6253 PetscCall(ISGetLocalSize(is, &numRows)); 6254 PetscCall(ISGetIndices(is, &rows)); 6255 } 6256 PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b)); 6257 if (is) PetscCall(ISRestoreIndices(is, &rows)); 6258 PetscFunctionReturn(PETSC_SUCCESS); 6259 } 6260 6261 /*@ 6262 MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal) 6263 of a set of rows of a matrix. These rows must be local to the process. 6264 6265 Collective 6266 6267 Input Parameters: 6268 + mat - the matrix 6269 . numRows - the number of rows to remove 6270 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6271 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6272 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6273 - b - optional vector of right hand side, that will be adjusted by provided solution 6274 6275 Level: intermediate 6276 6277 Notes: 6278 See `MatZeroRows()` for details on how this routine operates. 6279 6280 The grid coordinates are across the entire grid, not just the local portion 6281 6282 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6283 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6284 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6285 `DM_BOUNDARY_PERIODIC` boundary type. 6286 6287 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 6288 a single value per point) you can skip filling those indices. 6289 6290 Fortran Note: 6291 idxm and idxn should be declared as 6292 $ MatStencil idxm(4,m) 6293 and the values inserted using 6294 .vb 6295 idxm(MatStencil_i,1) = i 6296 idxm(MatStencil_j,1) = j 6297 idxm(MatStencil_k,1) = k 6298 idxm(MatStencil_c,1) = c 6299 etc 6300 .ve 6301 6302 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6303 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6304 @*/ 6305 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6306 { 6307 PetscInt dim = mat->stencil.dim; 6308 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6309 PetscInt *dims = mat->stencil.dims + 1; 6310 PetscInt *starts = mat->stencil.starts; 6311 PetscInt *dxm = (PetscInt *)rows; 6312 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6313 6314 PetscFunctionBegin; 6315 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6316 PetscValidType(mat, 1); 6317 if (numRows) PetscValidPointer(rows, 3); 6318 6319 PetscCall(PetscMalloc1(numRows, &jdxm)); 6320 for (i = 0; i < numRows; ++i) { 6321 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6322 for (j = 0; j < 3 - sdim; ++j) dxm++; 6323 /* Local index in X dir */ 6324 tmp = *dxm++ - starts[0]; 6325 /* Loop over remaining dimensions */ 6326 for (j = 0; j < dim - 1; ++j) { 6327 /* If nonlocal, set index to be negative */ 6328 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6329 /* Update local index */ 6330 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6331 } 6332 /* Skip component slot if necessary */ 6333 if (mat->stencil.noc) dxm++; 6334 /* Local row number */ 6335 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6336 } 6337 PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b)); 6338 PetscCall(PetscFree(jdxm)); 6339 PetscFunctionReturn(PETSC_SUCCESS); 6340 } 6341 6342 /*@ 6343 MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal) 6344 of a set of rows and columns of a matrix. 6345 6346 Collective 6347 6348 Input Parameters: 6349 + mat - the matrix 6350 . numRows - the number of rows/columns to remove 6351 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6352 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6353 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6354 - b - optional vector of right hand side, that will be adjusted by provided solution 6355 6356 Level: intermediate 6357 6358 Notes: 6359 See `MatZeroRowsColumns()` for details on how this routine operates. 6360 6361 The grid coordinates are across the entire grid, not just the local portion 6362 6363 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6364 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6365 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6366 `DM_BOUNDARY_PERIODIC` boundary type. 6367 6368 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 6369 a single value per point) you can skip filling those indices. 6370 6371 Fortran Note: 6372 In Fortran idxm and idxn should be declared as 6373 $ MatStencil idxm(4,m) 6374 and the values inserted using 6375 .vb 6376 idxm(MatStencil_i,1) = i 6377 idxm(MatStencil_j,1) = j 6378 idxm(MatStencil_k,1) = k 6379 idxm(MatStencil_c,1) = c 6380 etc 6381 .ve 6382 6383 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6384 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()` 6385 @*/ 6386 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6387 { 6388 PetscInt dim = mat->stencil.dim; 6389 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6390 PetscInt *dims = mat->stencil.dims + 1; 6391 PetscInt *starts = mat->stencil.starts; 6392 PetscInt *dxm = (PetscInt *)rows; 6393 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6394 6395 PetscFunctionBegin; 6396 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6397 PetscValidType(mat, 1); 6398 if (numRows) PetscValidPointer(rows, 3); 6399 6400 PetscCall(PetscMalloc1(numRows, &jdxm)); 6401 for (i = 0; i < numRows; ++i) { 6402 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6403 for (j = 0; j < 3 - sdim; ++j) dxm++; 6404 /* Local index in X dir */ 6405 tmp = *dxm++ - starts[0]; 6406 /* Loop over remaining dimensions */ 6407 for (j = 0; j < dim - 1; ++j) { 6408 /* If nonlocal, set index to be negative */ 6409 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6410 /* Update local index */ 6411 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6412 } 6413 /* Skip component slot if necessary */ 6414 if (mat->stencil.noc) dxm++; 6415 /* Local row number */ 6416 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6417 } 6418 PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b)); 6419 PetscCall(PetscFree(jdxm)); 6420 PetscFunctionReturn(PETSC_SUCCESS); 6421 } 6422 6423 /*@C 6424 MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal) 6425 of a set of rows of a matrix; using local numbering of rows. 6426 6427 Collective 6428 6429 Input Parameters: 6430 + mat - the matrix 6431 . numRows - the number of rows to remove 6432 . rows - the local row indices 6433 . diag - value put in all diagonals of eliminated rows 6434 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6435 - b - optional vector of right hand side, that will be adjusted by provided solution 6436 6437 Notes: 6438 Before calling `MatZeroRowsLocal()`, the user must first set the 6439 local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`. 6440 6441 See `MatZeroRows()` for details on how this routine operates. 6442 6443 Level: intermediate 6444 6445 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`, 6446 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6447 @*/ 6448 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6449 { 6450 PetscFunctionBegin; 6451 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6452 PetscValidType(mat, 1); 6453 if (numRows) PetscValidIntPointer(rows, 3); 6454 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6455 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6456 MatCheckPreallocated(mat, 1); 6457 6458 if (mat->ops->zerorowslocal) { 6459 PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b); 6460 } else { 6461 IS is, newis; 6462 const PetscInt *newRows; 6463 6464 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6465 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6466 PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis)); 6467 PetscCall(ISGetIndices(newis, &newRows)); 6468 PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b); 6469 PetscCall(ISRestoreIndices(newis, &newRows)); 6470 PetscCall(ISDestroy(&newis)); 6471 PetscCall(ISDestroy(&is)); 6472 } 6473 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6474 PetscFunctionReturn(PETSC_SUCCESS); 6475 } 6476 6477 /*@ 6478 MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal) 6479 of a set of rows of a matrix; using local numbering of rows. 6480 6481 Collective 6482 6483 Input Parameters: 6484 + mat - the matrix 6485 . is - index set of rows to remove 6486 . diag - value put in all diagonals of eliminated rows 6487 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6488 - b - optional vector of right hand side, that will be adjusted by provided solution 6489 6490 Notes: 6491 Before calling `MatZeroRowsLocalIS()`, the user must first set the 6492 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6493 6494 See `MatZeroRows()` for details on how this routine operates. 6495 6496 Level: intermediate 6497 6498 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6499 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6500 @*/ 6501 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6502 { 6503 PetscInt numRows; 6504 const PetscInt *rows; 6505 6506 PetscFunctionBegin; 6507 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6508 PetscValidType(mat, 1); 6509 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6510 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6511 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6512 MatCheckPreallocated(mat, 1); 6513 6514 PetscCall(ISGetLocalSize(is, &numRows)); 6515 PetscCall(ISGetIndices(is, &rows)); 6516 PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b)); 6517 PetscCall(ISRestoreIndices(is, &rows)); 6518 PetscFunctionReturn(PETSC_SUCCESS); 6519 } 6520 6521 /*@ 6522 MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal) 6523 of a set of rows and columns of a matrix; using local numbering of rows. 6524 6525 Collective 6526 6527 Input Parameters: 6528 + mat - the matrix 6529 . numRows - the number of rows to remove 6530 . rows - the global row indices 6531 . diag - value put in all diagonals of eliminated rows 6532 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6533 - b - optional vector of right hand side, that will be adjusted by provided solution 6534 6535 Notes: 6536 Before calling `MatZeroRowsColumnsLocal()`, the user must first set the 6537 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6538 6539 See `MatZeroRowsColumns()` for details on how this routine operates. 6540 6541 Level: intermediate 6542 6543 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6544 `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6545 @*/ 6546 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6547 { 6548 IS is, newis; 6549 const PetscInt *newRows; 6550 6551 PetscFunctionBegin; 6552 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6553 PetscValidType(mat, 1); 6554 if (numRows) PetscValidIntPointer(rows, 3); 6555 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6556 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6557 MatCheckPreallocated(mat, 1); 6558 6559 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6560 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6561 PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis)); 6562 PetscCall(ISGetIndices(newis, &newRows)); 6563 PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b); 6564 PetscCall(ISRestoreIndices(newis, &newRows)); 6565 PetscCall(ISDestroy(&newis)); 6566 PetscCall(ISDestroy(&is)); 6567 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6568 PetscFunctionReturn(PETSC_SUCCESS); 6569 } 6570 6571 /*@ 6572 MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal) 6573 of a set of rows and columns of a matrix; using local numbering of rows. 6574 6575 Collective on Mat 6576 6577 Input Parameters: 6578 + mat - the matrix 6579 . is - index set of rows to remove 6580 . diag - value put in all diagonals of eliminated rows 6581 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6582 - b - optional vector of right hand side, that will be adjusted by provided solution 6583 6584 Notes: 6585 Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the 6586 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6587 6588 See `MatZeroRowsColumns()` for details on how this routine operates. 6589 6590 Level: intermediate 6591 6592 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6593 `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6594 @*/ 6595 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6596 { 6597 PetscInt numRows; 6598 const PetscInt *rows; 6599 6600 PetscFunctionBegin; 6601 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6602 PetscValidType(mat, 1); 6603 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6604 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6605 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6606 MatCheckPreallocated(mat, 1); 6607 6608 PetscCall(ISGetLocalSize(is, &numRows)); 6609 PetscCall(ISGetIndices(is, &rows)); 6610 PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b)); 6611 PetscCall(ISRestoreIndices(is, &rows)); 6612 PetscFunctionReturn(PETSC_SUCCESS); 6613 } 6614 6615 /*@C 6616 MatGetSize - Returns the numbers of rows and columns in a matrix. 6617 6618 Not Collective 6619 6620 Input Parameter: 6621 . mat - the matrix 6622 6623 Output Parameters: 6624 + m - the number of global rows 6625 - n - the number of global columns 6626 6627 Note: both output parameters can be NULL on input. 6628 6629 Level: beginner 6630 6631 .seealso: `Mat`, `MatSetSizes()`, `MatGetLocalSize()` 6632 @*/ 6633 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n) 6634 { 6635 PetscFunctionBegin; 6636 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6637 if (m) *m = mat->rmap->N; 6638 if (n) *n = mat->cmap->N; 6639 PetscFunctionReturn(PETSC_SUCCESS); 6640 } 6641 6642 /*@C 6643 MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns 6644 of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`. 6645 6646 Not Collective 6647 6648 Input Parameter: 6649 . mat - the matrix 6650 6651 Output Parameters: 6652 + m - the number of local rows, use `NULL` to not obtain this value 6653 - n - the number of local columns, use `NULL` to not obtain this value 6654 6655 Level: beginner 6656 6657 .seealso: `Mat`, `MatSetSizes()`, `MatGetSize()` 6658 @*/ 6659 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n) 6660 { 6661 PetscFunctionBegin; 6662 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6663 if (m) PetscValidIntPointer(m, 2); 6664 if (n) PetscValidIntPointer(n, 3); 6665 if (m) *m = mat->rmap->n; 6666 if (n) *n = mat->cmap->n; 6667 PetscFunctionReturn(PETSC_SUCCESS); 6668 } 6669 6670 /*@C 6671 MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by 6672 this processor. (The columns of the "diagonal block" for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts. 6673 6674 Not Collective, unless matrix has not been allocated, then collective 6675 6676 Input Parameter: 6677 . mat - the matrix 6678 6679 Output Parameters: 6680 + m - the global index of the first local column, use `NULL` to not obtain this value 6681 - n - one more than the global index of the last local column, use `NULL` to not obtain this value 6682 6683 Level: developer 6684 6685 .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout` 6686 @*/ 6687 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n) 6688 { 6689 PetscFunctionBegin; 6690 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6691 PetscValidType(mat, 1); 6692 if (m) PetscValidIntPointer(m, 2); 6693 if (n) PetscValidIntPointer(n, 3); 6694 MatCheckPreallocated(mat, 1); 6695 if (m) *m = mat->cmap->rstart; 6696 if (n) *n = mat->cmap->rend; 6697 PetscFunctionReturn(PETSC_SUCCESS); 6698 } 6699 6700 /*@C 6701 MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6702 this MPI rank. For all matrices it returns the range of matrix rows associated with rows of a vector that would contain the result of a matrix 6703 vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts 6704 6705 Not Collective 6706 6707 Input Parameter: 6708 . mat - the matrix 6709 6710 Output Parameters: 6711 + m - the global index of the first local row, use `NULL` to not obtain this value 6712 - n - one more than the global index of the last local row, use `NULL` to not obtain this value 6713 6714 Note: 6715 This function requires that the matrix be preallocated. If you have not preallocated, consider using 6716 `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N) 6717 and then `MPI_Scan()` to calculate prefix sums of the local sizes. 6718 6719 Level: beginner 6720 6721 .seealso: `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, 6722 `PetscLayout` 6723 @*/ 6724 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n) 6725 { 6726 PetscFunctionBegin; 6727 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6728 PetscValidType(mat, 1); 6729 if (m) PetscValidIntPointer(m, 2); 6730 if (n) PetscValidIntPointer(n, 3); 6731 MatCheckPreallocated(mat, 1); 6732 if (m) *m = mat->rmap->rstart; 6733 if (n) *n = mat->rmap->rend; 6734 PetscFunctionReturn(PETSC_SUCCESS); 6735 } 6736 6737 /*@C 6738 MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6739 each process. For all matrices it returns the ranges of matrix rows associated with rows of a vector that would contain the result of a matrix 6740 vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts 6741 6742 Not Collective, unless matrix has not been allocated, then collective 6743 6744 Input Parameters: 6745 . mat - the matrix 6746 6747 Output Parameters: 6748 . ranges - start of each processors portion plus one more than the total length at the end 6749 6750 Level: beginner 6751 6752 .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout` 6753 @*/ 6754 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges) 6755 { 6756 PetscFunctionBegin; 6757 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6758 PetscValidType(mat, 1); 6759 MatCheckPreallocated(mat, 1); 6760 PetscCall(PetscLayoutGetRanges(mat->rmap, ranges)); 6761 PetscFunctionReturn(PETSC_SUCCESS); 6762 } 6763 6764 /*@C 6765 MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by 6766 each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts. 6767 6768 Not Collective, unless matrix has not been allocated, then collective on Mat 6769 6770 Input Parameters: 6771 . mat - the matrix 6772 6773 Output Parameters: 6774 . ranges - start of each processors portion plus one more then the total length at the end 6775 6776 Level: beginner 6777 6778 .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()` 6779 @*/ 6780 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges) 6781 { 6782 PetscFunctionBegin; 6783 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6784 PetscValidType(mat, 1); 6785 MatCheckPreallocated(mat, 1); 6786 PetscCall(PetscLayoutGetRanges(mat->cmap, ranges)); 6787 PetscFunctionReturn(PETSC_SUCCESS); 6788 } 6789 6790 /*@C 6791 MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this 6792 corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership 6793 is more complicated. See :any:`<sec_matlayout>` for details on matrix layouts. 6794 6795 Not Collective 6796 6797 Input Parameter: 6798 . A - matrix 6799 6800 Output Parameters: 6801 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value 6802 - cols - columns in which this process owns elements, use `NULL` to not obtain this value 6803 6804 Level: intermediate 6805 6806 .seealso: `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK`` 6807 @*/ 6808 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols) 6809 { 6810 PetscErrorCode (*f)(Mat, IS *, IS *); 6811 6812 PetscFunctionBegin; 6813 MatCheckPreallocated(A, 1); 6814 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f)); 6815 if (f) { 6816 PetscCall((*f)(A, rows, cols)); 6817 } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */ 6818 if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows)); 6819 if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols)); 6820 } 6821 PetscFunctionReturn(PETSC_SUCCESS); 6822 } 6823 6824 /*@C 6825 MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()` 6826 Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()` 6827 to complete the factorization. 6828 6829 Collective on fact 6830 6831 Input Parameters: 6832 + fact - the factorized matrix obtained with `MatGetFactor()` 6833 . mat - the matrix 6834 . row - row permutation 6835 . column - column permutation 6836 - info - structure containing 6837 $ levels - number of levels of fill. 6838 $ expected fill - as ratio of original fill. 6839 $ 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 6840 missing diagonal entries) 6841 6842 Output Parameters: 6843 . fact - new matrix that has been symbolically factored 6844 6845 Level: developer 6846 6847 Notes: 6848 See [Matrix Factorization](sec_matfactor) for additional information. 6849 6850 Most users should employ the `KSP` interface for linear solvers 6851 instead of working directly with matrix algebra routines such as this. 6852 See, e.g., `KSPCreate()`. 6853 6854 Uses the definition of level of fill as in Y. Saad, 2003 6855 6856 Developer Note: 6857 The Fortran interface is not autogenerated as the 6858 interface definition cannot be generated correctly [due to `MatFactorInfo`] 6859 6860 References: 6861 . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003 6862 6863 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 6864 `MatGetOrdering()`, `MatFactorInfo` 6865 @*/ 6866 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 6867 { 6868 PetscFunctionBegin; 6869 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 6870 PetscValidType(mat, 2); 6871 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 6872 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 6873 PetscValidPointer(info, 5); 6874 PetscValidPointer(fact, 1); 6875 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels); 6876 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 6877 if (!fact->ops->ilufactorsymbolic) { 6878 MatSolverType stype; 6879 PetscCall(MatFactorGetSolverType(fact, &stype)); 6880 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ILU using solver type %s", ((PetscObject)mat)->type_name, stype); 6881 } 6882 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6883 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6884 MatCheckPreallocated(mat, 2); 6885 6886 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0)); 6887 PetscCall((fact->ops->ilufactorsymbolic)(fact, mat, row, col, info)); 6888 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0)); 6889 PetscFunctionReturn(PETSC_SUCCESS); 6890 } 6891 6892 /*@C 6893 MatICCFactorSymbolic - Performs symbolic incomplete 6894 Cholesky factorization for a symmetric matrix. Use 6895 `MatCholeskyFactorNumeric()` to complete the factorization. 6896 6897 Collective on fact 6898 6899 Input Parameters: 6900 + fact - the factorized matrix obtained with `MatGetFactor()` 6901 . mat - the matrix to be factored 6902 . perm - row and column permutation 6903 - info - structure containing 6904 $ levels - number of levels of fill. 6905 $ expected fill - as ratio of original fill. 6906 6907 Output Parameter: 6908 . fact - the factored matrix 6909 6910 Level: developer 6911 6912 Notes: 6913 Most users should employ the `KSP` interface for linear solvers 6914 instead of working directly with matrix algebra routines such as this. 6915 See, e.g., `KSPCreate()`. 6916 6917 This uses the definition of level of fill as in Y. Saad, 2003 6918 6919 Developer Note: 6920 The Fortran interface is not autogenerated as the 6921 interface definition cannot be generated correctly [due to `MatFactorInfo`] 6922 6923 References: 6924 . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003 6925 6926 .seealso: `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 6927 @*/ 6928 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 6929 { 6930 PetscFunctionBegin; 6931 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 6932 PetscValidType(mat, 2); 6933 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 6934 PetscValidPointer(info, 4); 6935 PetscValidPointer(fact, 1); 6936 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6937 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels); 6938 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 6939 if (!(fact)->ops->iccfactorsymbolic) { 6940 MatSolverType stype; 6941 PetscCall(MatFactorGetSolverType(fact, &stype)); 6942 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ICC using solver type %s", ((PetscObject)mat)->type_name, stype); 6943 } 6944 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6945 MatCheckPreallocated(mat, 2); 6946 6947 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 6948 PetscCall((fact->ops->iccfactorsymbolic)(fact, mat, perm, info)); 6949 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 6950 PetscFunctionReturn(PETSC_SUCCESS); 6951 } 6952 6953 /*@C 6954 MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat 6955 points to an array of valid matrices, they may be reused to store the new 6956 submatrices. 6957 6958 Collective 6959 6960 Input Parameters: 6961 + mat - the matrix 6962 . n - the number of submatrixes to be extracted (on this processor, may be zero) 6963 . irow, icol - index sets of rows and columns to extract 6964 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 6965 6966 Output Parameter: 6967 . submat - the array of submatrices 6968 6969 Notes: 6970 `MatCreateSubMatrices()` can extract ONLY sequential submatrices 6971 (from both sequential and parallel matrices). Use `MatCreateSubMatrix()` 6972 to extract a parallel submatrix. 6973 6974 Some matrix types place restrictions on the row and column 6975 indices, such as that they be sorted or that they be equal to each other. 6976 6977 The index sets may not have duplicate entries. 6978 6979 When extracting submatrices from a parallel matrix, each processor can 6980 form a different submatrix by setting the rows and columns of its 6981 individual index sets according to the local submatrix desired. 6982 6983 When finished using the submatrices, the user should destroy 6984 them with `MatDestroySubMatrices()`. 6985 6986 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 6987 original matrix has not changed from that last call to `MatCreateSubMatrices()`. 6988 6989 This routine creates the matrices in submat; you should NOT create them before 6990 calling it. It also allocates the array of matrix pointers submat. 6991 6992 For `MATBAIJ` matrices the index sets must respect the block structure, that is if they 6993 request one row/column in a block, they must request all rows/columns that are in 6994 that block. For example, if the block size is 2 you cannot request just row 0 and 6995 column 0. 6996 6997 Fortran Note: 6998 The Fortran interface is slightly different from that given below; it 6999 requires one to pass in as submat a `Mat` (integer) array of size at least n+1. 7000 7001 Level: advanced 7002 7003 .seealso: `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7004 @*/ 7005 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7006 { 7007 PetscInt i; 7008 PetscBool eq; 7009 7010 PetscFunctionBegin; 7011 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7012 PetscValidType(mat, 1); 7013 if (n) { 7014 PetscValidPointer(irow, 3); 7015 for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3); 7016 PetscValidPointer(icol, 4); 7017 for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4); 7018 } 7019 PetscValidPointer(submat, 6); 7020 if (n && scall == MAT_REUSE_MATRIX) { 7021 PetscValidPointer(*submat, 6); 7022 for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6); 7023 } 7024 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7025 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7026 MatCheckPreallocated(mat, 1); 7027 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7028 PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat); 7029 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7030 for (i = 0; i < n; i++) { 7031 (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */ 7032 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7033 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7034 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 7035 if (mat->boundtocpu && mat->bindingpropagates) { 7036 PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE)); 7037 PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE)); 7038 } 7039 #endif 7040 } 7041 PetscFunctionReturn(PETSC_SUCCESS); 7042 } 7043 7044 /*@C 7045 MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms). 7046 7047 Collective 7048 7049 Input Parameters: 7050 + mat - the matrix 7051 . n - the number of submatrixes to be extracted 7052 . irow, icol - index sets of rows and columns to extract 7053 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7054 7055 Output Parameter: 7056 . submat - the array of submatrices 7057 7058 Level: advanced 7059 7060 Note: 7061 This is used by `PCGASM` 7062 7063 .seealso: `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7064 @*/ 7065 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7066 { 7067 PetscInt i; 7068 PetscBool eq; 7069 7070 PetscFunctionBegin; 7071 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7072 PetscValidType(mat, 1); 7073 if (n) { 7074 PetscValidPointer(irow, 3); 7075 PetscValidHeaderSpecific(*irow, IS_CLASSID, 3); 7076 PetscValidPointer(icol, 4); 7077 PetscValidHeaderSpecific(*icol, IS_CLASSID, 4); 7078 } 7079 PetscValidPointer(submat, 6); 7080 if (n && scall == MAT_REUSE_MATRIX) { 7081 PetscValidPointer(*submat, 6); 7082 PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6); 7083 } 7084 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7085 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7086 MatCheckPreallocated(mat, 1); 7087 7088 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7089 PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat); 7090 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7091 for (i = 0; i < n; i++) { 7092 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7093 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7094 } 7095 PetscFunctionReturn(PETSC_SUCCESS); 7096 } 7097 7098 /*@C 7099 MatDestroyMatrices - Destroys an array of matrices. 7100 7101 Collective 7102 7103 Input Parameters: 7104 + n - the number of local matrices 7105 - mat - the matrices (note that this is a pointer to the array of matrices) 7106 7107 Level: advanced 7108 7109 Note: 7110 Frees not only the matrices, but also the array that contains the matrices 7111 In Fortran will not free the array. 7112 7113 .seealso: `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()` 7114 @*/ 7115 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[]) 7116 { 7117 PetscInt i; 7118 7119 PetscFunctionBegin; 7120 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7121 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7122 PetscValidPointer(mat, 2); 7123 7124 for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i])); 7125 7126 /* memory is allocated even if n = 0 */ 7127 PetscCall(PetscFree(*mat)); 7128 PetscFunctionReturn(PETSC_SUCCESS); 7129 } 7130 7131 /*@C 7132 MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`. 7133 7134 Collective 7135 7136 Input Parameters: 7137 + n - the number of local matrices 7138 - mat - the matrices (note that this is a pointer to the array of matrices, just to match the calling 7139 sequence of MatCreateSubMatrices()) 7140 7141 Level: advanced 7142 7143 Note: 7144 Frees not only the matrices, but also the array that contains the matrices 7145 In Fortran will not free the array. 7146 7147 .seealso: `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7148 @*/ 7149 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[]) 7150 { 7151 Mat mat0; 7152 7153 PetscFunctionBegin; 7154 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7155 /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */ 7156 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7157 PetscValidPointer(mat, 2); 7158 7159 mat0 = (*mat)[0]; 7160 if (mat0 && mat0->ops->destroysubmatrices) { 7161 PetscCall((mat0->ops->destroysubmatrices)(n, mat)); 7162 } else { 7163 PetscCall(MatDestroyMatrices(n, mat)); 7164 } 7165 PetscFunctionReturn(PETSC_SUCCESS); 7166 } 7167 7168 /*@C 7169 MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process 7170 7171 Collective 7172 7173 Input Parameters: 7174 . mat - the matrix 7175 7176 Output Parameter: 7177 . matstruct - the sequential matrix with the nonzero structure of mat 7178 7179 Level: developer 7180 7181 .seealso: `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7182 @*/ 7183 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct) 7184 { 7185 PetscFunctionBegin; 7186 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7187 PetscValidPointer(matstruct, 2); 7188 7189 PetscValidType(mat, 1); 7190 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7191 MatCheckPreallocated(mat, 1); 7192 7193 PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7194 PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct); 7195 PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7196 PetscFunctionReturn(PETSC_SUCCESS); 7197 } 7198 7199 /*@C 7200 MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`. 7201 7202 Collective 7203 7204 Input Parameters: 7205 . mat - the matrix (note that this is a pointer to the array of matrices, just to match the calling 7206 sequence of `MatGetSequentialNonzeroStructure()`) 7207 7208 Level: advanced 7209 7210 Note: 7211 Frees not only the matrices, but also the array that contains the matrices 7212 7213 .seealso: `Mat`, `MatGetSeqNonzeroStructure()` 7214 @*/ 7215 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat) 7216 { 7217 PetscFunctionBegin; 7218 PetscValidPointer(mat, 1); 7219 PetscCall(MatDestroy(mat)); 7220 PetscFunctionReturn(PETSC_SUCCESS); 7221 } 7222 7223 /*@ 7224 MatIncreaseOverlap - Given a set of submatrices indicated by index sets, 7225 replaces the index sets by larger ones that represent submatrices with 7226 additional overlap. 7227 7228 Collective 7229 7230 Input Parameters: 7231 + mat - the matrix 7232 . n - the number of index sets 7233 . is - the array of index sets (these index sets will changed during the call) 7234 - ov - the additional overlap requested 7235 7236 Options Database Key: 7237 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7238 7239 Level: developer 7240 7241 Note: 7242 The computed overlap preserves the matrix block sizes when the blocks are square. 7243 That is: if a matrix nonzero for a given block would increase the overlap all columns associated with 7244 that block are included in the overlap regardless of whether each specific column would increase the overlap. 7245 7246 .seealso: `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()` 7247 @*/ 7248 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov) 7249 { 7250 PetscInt i, bs, cbs; 7251 7252 PetscFunctionBegin; 7253 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7254 PetscValidType(mat, 1); 7255 PetscValidLogicalCollectiveInt(mat, n, 2); 7256 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7257 if (n) { 7258 PetscValidPointer(is, 3); 7259 for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3); 7260 } 7261 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7262 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7263 MatCheckPreallocated(mat, 1); 7264 7265 if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS); 7266 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7267 PetscUseTypeMethod(mat, increaseoverlap, n, is, ov); 7268 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7269 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 7270 if (bs == cbs) { 7271 for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs)); 7272 } 7273 PetscFunctionReturn(PETSC_SUCCESS); 7274 } 7275 7276 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt); 7277 7278 /*@ 7279 MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across 7280 a sub communicator, replaces the index sets by larger ones that represent submatrices with 7281 additional overlap. 7282 7283 Collective 7284 7285 Input Parameters: 7286 + mat - the matrix 7287 . n - the number of index sets 7288 . is - the array of index sets (these index sets will changed during the call) 7289 - ov - the additional overlap requested 7290 7291 ` Options Database Key: 7292 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7293 7294 Level: developer 7295 7296 .seealso: `MatCreateSubMatrices()`, `MatIncreaseOverlap()` 7297 @*/ 7298 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov) 7299 { 7300 PetscInt i; 7301 7302 PetscFunctionBegin; 7303 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7304 PetscValidType(mat, 1); 7305 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7306 if (n) { 7307 PetscValidPointer(is, 3); 7308 PetscValidHeaderSpecific(*is, IS_CLASSID, 3); 7309 } 7310 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7311 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7312 MatCheckPreallocated(mat, 1); 7313 if (!ov) PetscFunctionReturn(PETSC_SUCCESS); 7314 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7315 for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov)); 7316 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7317 PetscFunctionReturn(PETSC_SUCCESS); 7318 } 7319 7320 /*@ 7321 MatGetBlockSize - Returns the matrix block size. 7322 7323 Not Collective 7324 7325 Input Parameter: 7326 . mat - the matrix 7327 7328 Output Parameter: 7329 . bs - block size 7330 7331 Notes: 7332 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7333 7334 If the block size has not been set yet this routine returns 1. 7335 7336 Level: intermediate 7337 7338 .seealso: `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()` 7339 @*/ 7340 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs) 7341 { 7342 PetscFunctionBegin; 7343 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7344 PetscValidIntPointer(bs, 2); 7345 *bs = PetscAbs(mat->rmap->bs); 7346 PetscFunctionReturn(PETSC_SUCCESS); 7347 } 7348 7349 /*@ 7350 MatGetBlockSizes - Returns the matrix block row and column sizes. 7351 7352 Not Collective 7353 7354 Input Parameter: 7355 . mat - the matrix 7356 7357 Output Parameters: 7358 + rbs - row block size 7359 - cbs - column block size 7360 7361 Notes: 7362 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7363 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7364 7365 If a block size has not been set yet this routine returns 1. 7366 7367 Level: intermediate 7368 7369 .seealso: `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()` 7370 @*/ 7371 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs) 7372 { 7373 PetscFunctionBegin; 7374 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7375 if (rbs) PetscValidIntPointer(rbs, 2); 7376 if (cbs) PetscValidIntPointer(cbs, 3); 7377 if (rbs) *rbs = PetscAbs(mat->rmap->bs); 7378 if (cbs) *cbs = PetscAbs(mat->cmap->bs); 7379 PetscFunctionReturn(PETSC_SUCCESS); 7380 } 7381 7382 /*@ 7383 MatSetBlockSize - Sets the matrix block size. 7384 7385 Logically Collective 7386 7387 Input Parameters: 7388 + mat - the matrix 7389 - bs - block size 7390 7391 Notes: 7392 Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix. 7393 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7394 7395 For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size 7396 is compatible with the matrix local sizes. 7397 7398 Level: intermediate 7399 7400 .seealso: `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()` 7401 @*/ 7402 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs) 7403 { 7404 PetscFunctionBegin; 7405 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7406 PetscValidLogicalCollectiveInt(mat, bs, 2); 7407 PetscCall(MatSetBlockSizes(mat, bs, bs)); 7408 PetscFunctionReturn(PETSC_SUCCESS); 7409 } 7410 7411 typedef struct { 7412 PetscInt n; 7413 IS *is; 7414 Mat *mat; 7415 PetscObjectState nonzerostate; 7416 Mat C; 7417 } EnvelopeData; 7418 7419 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata) 7420 { 7421 for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i])); 7422 PetscCall(PetscFree(edata->is)); 7423 PetscCall(PetscFree(edata)); 7424 return PETSC_SUCCESS; 7425 } 7426 7427 /* 7428 MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores 7429 the sizes of these blocks in the matrix. An individual block may lie over several processes. 7430 7431 Collective 7432 7433 Input Parameter: 7434 . mat - the matrix 7435 7436 Notes: 7437 There can be zeros within the blocks 7438 7439 The blocks can overlap between processes, including laying on more than two processes 7440 7441 .seealso: `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()` 7442 */ 7443 static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat) 7444 { 7445 PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend; 7446 PetscInt *diag, *odiag, sc; 7447 VecScatter scatter; 7448 PetscScalar *seqv; 7449 const PetscScalar *parv; 7450 const PetscInt *ia, *ja; 7451 PetscBool set, flag, done; 7452 Mat AA = mat, A; 7453 MPI_Comm comm; 7454 PetscMPIInt rank, size, tag; 7455 MPI_Status status; 7456 PetscContainer container; 7457 EnvelopeData *edata; 7458 Vec seq, par; 7459 IS isglobal; 7460 7461 PetscFunctionBegin; 7462 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7463 PetscCall(MatIsSymmetricKnown(mat, &set, &flag)); 7464 if (!set || !flag) { 7465 /* TOO: only needs nonzero structure of transpose */ 7466 PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA)); 7467 PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN)); 7468 } 7469 PetscCall(MatAIJGetLocalMat(AA, &A)); 7470 PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7471 PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix"); 7472 7473 PetscCall(MatGetLocalSize(mat, &n, NULL)); 7474 PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag)); 7475 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 7476 PetscCallMPI(MPI_Comm_size(comm, &size)); 7477 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7478 7479 PetscCall(PetscMalloc2(n, &sizes, n, &starts)); 7480 7481 if (rank > 0) { 7482 PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7483 PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7484 } 7485 PetscCall(MatGetOwnershipRange(mat, &rstart, NULL)); 7486 for (i = 0; i < n; i++) { 7487 env = PetscMax(env, ja[ia[i + 1] - 1]); 7488 II = rstart + i; 7489 if (env == II) { 7490 starts[lblocks] = tbs; 7491 sizes[lblocks++] = 1 + II - tbs; 7492 tbs = 1 + II; 7493 } 7494 } 7495 if (rank < size - 1) { 7496 PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm)); 7497 PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm)); 7498 } 7499 7500 PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7501 if (!set || !flag) PetscCall(MatDestroy(&AA)); 7502 PetscCall(MatDestroy(&A)); 7503 7504 PetscCall(PetscNew(&edata)); 7505 PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate)); 7506 edata->n = lblocks; 7507 /* create IS needed for extracting blocks from the original matrix */ 7508 PetscCall(PetscMalloc1(lblocks, &edata->is)); 7509 for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i])); 7510 7511 /* Create the resulting inverse matrix structure with preallocation information */ 7512 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C)); 7513 PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 7514 PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat)); 7515 PetscCall(MatSetType(edata->C, MATAIJ)); 7516 7517 /* Communicate the start and end of each row, from each block to the correct rank */ 7518 /* TODO: Use PetscSF instead of VecScatter */ 7519 for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i]; 7520 PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq)); 7521 PetscCall(VecGetArrayWrite(seq, &seqv)); 7522 for (PetscInt i = 0; i < lblocks; i++) { 7523 for (PetscInt j = 0; j < sizes[i]; j++) { 7524 seqv[cnt] = starts[i]; 7525 seqv[cnt + 1] = starts[i] + sizes[i]; 7526 cnt += 2; 7527 } 7528 } 7529 PetscCall(VecRestoreArrayWrite(seq, &seqv)); 7530 PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 7531 sc -= cnt; 7532 PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par)); 7533 PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal)); 7534 PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter)); 7535 PetscCall(ISDestroy(&isglobal)); 7536 PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7537 PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7538 PetscCall(VecScatterDestroy(&scatter)); 7539 PetscCall(VecDestroy(&seq)); 7540 PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend)); 7541 PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag)); 7542 PetscCall(VecGetArrayRead(par, &parv)); 7543 cnt = 0; 7544 PetscCall(MatGetSize(mat, NULL, &n)); 7545 for (PetscInt i = 0; i < mat->rmap->n; i++) { 7546 PetscInt start, end, d = 0, od = 0; 7547 7548 start = (PetscInt)PetscRealPart(parv[cnt]); 7549 end = (PetscInt)PetscRealPart(parv[cnt + 1]); 7550 cnt += 2; 7551 7552 if (start < cstart) { 7553 od += cstart - start + n - cend; 7554 d += cend - cstart; 7555 } else if (start < cend) { 7556 od += n - cend; 7557 d += cend - start; 7558 } else od += n - start; 7559 if (end <= cstart) { 7560 od -= cstart - end + n - cend; 7561 d -= cend - cstart; 7562 } else if (end < cend) { 7563 od -= n - cend; 7564 d -= cend - end; 7565 } else od -= n - end; 7566 7567 odiag[i] = od; 7568 diag[i] = d; 7569 } 7570 PetscCall(VecRestoreArrayRead(par, &parv)); 7571 PetscCall(VecDestroy(&par)); 7572 PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL)); 7573 PetscCall(PetscFree2(diag, odiag)); 7574 PetscCall(PetscFree2(sizes, starts)); 7575 7576 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container)); 7577 PetscCall(PetscContainerSetPointer(container, edata)); 7578 PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy)); 7579 PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container)); 7580 PetscCall(PetscObjectDereference((PetscObject)container)); 7581 PetscFunctionReturn(PETSC_SUCCESS); 7582 } 7583 7584 /*@ 7585 MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A 7586 7587 Collective on A 7588 7589 Input Parameters: 7590 . A - the matrix 7591 7592 Output Parameters: 7593 . C - matrix with inverted block diagonal of A. This matrix should be created and may have its type set. 7594 7595 Note: 7596 For efficiency the matrix A should have all the nonzero entries clustered in smallish blocks along the diagonal. 7597 7598 Level: advanced 7599 7600 .seealso: `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()` 7601 @*/ 7602 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C) 7603 { 7604 PetscContainer container; 7605 EnvelopeData *edata; 7606 PetscObjectState nonzerostate; 7607 7608 PetscFunctionBegin; 7609 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7610 if (!container) { 7611 PetscCall(MatComputeVariableBlockEnvelope(A)); 7612 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7613 } 7614 PetscCall(PetscContainerGetPointer(container, (void **)&edata)); 7615 PetscCall(MatGetNonzeroState(A, &nonzerostate)); 7616 PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure"); 7617 PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output"); 7618 7619 PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat)); 7620 *C = edata->C; 7621 7622 for (PetscInt i = 0; i < edata->n; i++) { 7623 Mat D; 7624 PetscScalar *dvalues; 7625 7626 PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D)); 7627 PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE)); 7628 PetscCall(MatSeqDenseInvert(D)); 7629 PetscCall(MatDenseGetArray(D, &dvalues)); 7630 PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES)); 7631 PetscCall(MatDestroy(&D)); 7632 } 7633 PetscCall(MatDestroySubMatrices(edata->n, &edata->mat)); 7634 PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY)); 7635 PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY)); 7636 PetscFunctionReturn(PETSC_SUCCESS); 7637 } 7638 7639 /*@ 7640 MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size 7641 7642 Logically Collective 7643 7644 Input Parameters: 7645 + mat - the matrix 7646 . nblocks - the number of blocks on this process, each block can only exist on a single process 7647 - bsizes - the block sizes 7648 7649 Notes: 7650 Currently used by `PCVPBJACOBI` for `MATAIJ` matrices 7651 7652 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. 7653 7654 Level: intermediate 7655 7656 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, 7657 `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI` 7658 @*/ 7659 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes) 7660 { 7661 PetscInt i, ncnt = 0, nlocal; 7662 7663 PetscFunctionBegin; 7664 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7665 PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero"); 7666 PetscCall(MatGetLocalSize(mat, &nlocal, NULL)); 7667 for (i = 0; i < nblocks; i++) ncnt += bsizes[i]; 7668 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); 7669 PetscCall(PetscFree(mat->bsizes)); 7670 mat->nblocks = nblocks; 7671 PetscCall(PetscMalloc1(nblocks, &mat->bsizes)); 7672 PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks)); 7673 PetscFunctionReturn(PETSC_SUCCESS); 7674 } 7675 7676 /*@C 7677 MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size 7678 7679 Logically Collective; No Fortran Support 7680 7681 Input Parameter: 7682 . mat - the matrix 7683 7684 Output Parameters: 7685 + nblocks - the number of blocks on this process 7686 - bsizes - the block sizes 7687 7688 Level: intermediate 7689 7690 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()` 7691 @*/ 7692 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes) 7693 { 7694 PetscFunctionBegin; 7695 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7696 *nblocks = mat->nblocks; 7697 *bsizes = mat->bsizes; 7698 PetscFunctionReturn(PETSC_SUCCESS); 7699 } 7700 7701 /*@ 7702 MatSetBlockSizes - Sets the matrix block row and column sizes. 7703 7704 Logically Collective 7705 7706 Input Parameters: 7707 + mat - the matrix 7708 . rbs - row block size 7709 - cbs - column block size 7710 7711 Notes: 7712 Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix. 7713 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7714 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7715 7716 For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes 7717 are compatible with the matrix local sizes. 7718 7719 The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`. 7720 7721 Level: intermediate 7722 7723 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()` 7724 @*/ 7725 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs) 7726 { 7727 PetscFunctionBegin; 7728 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7729 PetscValidLogicalCollectiveInt(mat, rbs, 2); 7730 PetscValidLogicalCollectiveInt(mat, cbs, 3); 7731 PetscTryTypeMethod(mat, setblocksizes, rbs, cbs); 7732 if (mat->rmap->refcnt) { 7733 ISLocalToGlobalMapping l2g = NULL; 7734 PetscLayout nmap = NULL; 7735 7736 PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap)); 7737 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g)); 7738 PetscCall(PetscLayoutDestroy(&mat->rmap)); 7739 mat->rmap = nmap; 7740 mat->rmap->mapping = l2g; 7741 } 7742 if (mat->cmap->refcnt) { 7743 ISLocalToGlobalMapping l2g = NULL; 7744 PetscLayout nmap = NULL; 7745 7746 PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap)); 7747 if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g)); 7748 PetscCall(PetscLayoutDestroy(&mat->cmap)); 7749 mat->cmap = nmap; 7750 mat->cmap->mapping = l2g; 7751 } 7752 PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs)); 7753 PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs)); 7754 PetscFunctionReturn(PETSC_SUCCESS); 7755 } 7756 7757 /*@ 7758 MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices 7759 7760 Logically Collective 7761 7762 Input Parameters: 7763 + mat - the matrix 7764 . fromRow - matrix from which to copy row block size 7765 - fromCol - matrix from which to copy column block size (can be same as fromRow) 7766 7767 Level: developer 7768 7769 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()` 7770 @*/ 7771 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol) 7772 { 7773 PetscFunctionBegin; 7774 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7775 PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2); 7776 PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3); 7777 if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs)); 7778 if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs)); 7779 PetscFunctionReturn(PETSC_SUCCESS); 7780 } 7781 7782 /*@ 7783 MatResidual - Default routine to calculate the residual r = b - Ax 7784 7785 Collective 7786 7787 Input Parameters: 7788 + mat - the matrix 7789 . b - the right-hand-side 7790 - x - the approximate solution 7791 7792 Output Parameter: 7793 . r - location to store the residual 7794 7795 Level: developer 7796 7797 .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()` 7798 @*/ 7799 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r) 7800 { 7801 PetscFunctionBegin; 7802 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7803 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 7804 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 7805 PetscValidHeaderSpecific(r, VEC_CLASSID, 4); 7806 PetscValidType(mat, 1); 7807 MatCheckPreallocated(mat, 1); 7808 PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0)); 7809 if (!mat->ops->residual) { 7810 PetscCall(MatMult(mat, x, r)); 7811 PetscCall(VecAYPX(r, -1.0, b)); 7812 } else { 7813 PetscUseTypeMethod(mat, residual, b, x, r); 7814 } 7815 PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0)); 7816 PetscFunctionReturn(PETSC_SUCCESS); 7817 } 7818 7819 /*MC 7820 MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix 7821 7822 Synopsis: 7823 MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 7824 7825 Not Collective 7826 7827 Input Parameters: 7828 + A - the matrix 7829 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7830 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7831 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicats if the nonzero structure of the 7832 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7833 always used. 7834 7835 Output Parameters: 7836 + n - number of local rows in the (possibly compressed) matrix 7837 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 7838 . ja - the column indices 7839 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7840 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7841 7842 Level: developer 7843 7844 Note: 7845 Use `MatRestoreRowIJF90()` when you no longer need access to the data 7846 7847 .seealso: [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()` 7848 M*/ 7849 7850 /*MC 7851 MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()` 7852 7853 Synopsis: 7854 MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 7855 7856 Not Collective 7857 7858 Input Parameters: 7859 + A - the matrix 7860 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7861 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7862 inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicats if the nonzero structure of the 7863 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7864 always used. 7865 . n - number of local rows in the (possibly compressed) matrix 7866 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 7867 . ja - the column indices 7868 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7869 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7870 7871 Level: developer 7872 7873 .seealso: [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()` 7874 M*/ 7875 7876 /*@C 7877 MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix 7878 7879 Collective 7880 7881 Input Parameters: 7882 + mat - the matrix 7883 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7884 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7885 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicats if the nonzero structure of the 7886 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7887 always used. 7888 7889 Output Parameters: 7890 + n - number of local rows in the (possibly compressed) matrix, use NULL if not needed 7891 . 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 7892 . ja - the column indices, use NULL if not needed 7893 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7894 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7895 7896 Level: developer 7897 7898 Notes: 7899 You CANNOT change any of the ia[] or ja[] values. 7900 7901 Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values. 7902 7903 Fortran Notes: 7904 In Fortran use 7905 .vb 7906 PetscInt, pointer :: ia(:),ja(:) 7907 call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr) 7908 ! Access the ith and jth entries via ia(i) and ja(j) 7909 .ve 7910 `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()` 7911 7912 .seealso: `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()` 7913 @*/ 7914 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7915 { 7916 PetscFunctionBegin; 7917 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7918 PetscValidType(mat, 1); 7919 if (n) PetscValidIntPointer(n, 5); 7920 if (ia) PetscValidPointer(ia, 6); 7921 if (ja) PetscValidPointer(ja, 7); 7922 if (done) PetscValidBoolPointer(done, 8); 7923 MatCheckPreallocated(mat, 1); 7924 if (!mat->ops->getrowij && done) *done = PETSC_FALSE; 7925 else { 7926 if (done) *done = PETSC_TRUE; 7927 PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0)); 7928 PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done); 7929 PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0)); 7930 } 7931 PetscFunctionReturn(PETSC_SUCCESS); 7932 } 7933 7934 /*@C 7935 MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices. 7936 7937 Collective 7938 7939 Input Parameters: 7940 + mat - the matrix 7941 . shift - 1 or zero indicating we want the indices starting at 0 or 1 7942 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be 7943 symmetrized 7944 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7945 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7946 always used. 7947 . n - number of columns in the (possibly compressed) matrix 7948 . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix 7949 - ja - the row indices 7950 7951 Output Parameters: 7952 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned 7953 7954 Level: developer 7955 7956 .seealso: `MatGetRowIJ()`, `MatRestoreColumnIJ()` 7957 @*/ 7958 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7959 { 7960 PetscFunctionBegin; 7961 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7962 PetscValidType(mat, 1); 7963 PetscValidIntPointer(n, 5); 7964 if (ia) PetscValidPointer(ia, 6); 7965 if (ja) PetscValidPointer(ja, 7); 7966 PetscValidBoolPointer(done, 8); 7967 MatCheckPreallocated(mat, 1); 7968 if (!mat->ops->getcolumnij) *done = PETSC_FALSE; 7969 else { 7970 *done = PETSC_TRUE; 7971 PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 7972 } 7973 PetscFunctionReturn(PETSC_SUCCESS); 7974 } 7975 7976 /*@C 7977 MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`. 7978 7979 Collective 7980 7981 Input Parameters: 7982 + mat - the matrix 7983 . shift - 1 or zero indicating we want the indices starting at 0 or 1 7984 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7985 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7986 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7987 always used. 7988 . n - size of (possibly compressed) matrix 7989 . ia - the row pointers 7990 - ja - the column indices 7991 7992 Output Parameters: 7993 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 7994 7995 Level: developer 7996 7997 Note: 7998 This routine zeros out n, ia, and ja. This is to prevent accidental 7999 us of the array after it has been restored. If you pass NULL, it will 8000 not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid. 8001 8002 Fortran Note: 8003 `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()` 8004 8005 .seealso: `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()` 8006 @*/ 8007 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8008 { 8009 PetscFunctionBegin; 8010 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8011 PetscValidType(mat, 1); 8012 if (ia) PetscValidPointer(ia, 6); 8013 if (ja) PetscValidPointer(ja, 7); 8014 if (done) PetscValidBoolPointer(done, 8); 8015 MatCheckPreallocated(mat, 1); 8016 8017 if (!mat->ops->restorerowij && done) *done = PETSC_FALSE; 8018 else { 8019 if (done) *done = PETSC_TRUE; 8020 PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8021 if (n) *n = 0; 8022 if (ia) *ia = NULL; 8023 if (ja) *ja = NULL; 8024 } 8025 PetscFunctionReturn(PETSC_SUCCESS); 8026 } 8027 8028 /*@C 8029 MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`. 8030 8031 Collective on Mat 8032 8033 Input Parameters: 8034 + mat - the matrix 8035 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8036 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8037 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8038 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8039 always used. 8040 8041 Output Parameters: 8042 + n - size of (possibly compressed) matrix 8043 . ia - the column pointers 8044 . ja - the row indices 8045 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8046 8047 Level: developer 8048 8049 .seealso: `MatGetColumnIJ()`, `MatRestoreRowIJ()` 8050 @*/ 8051 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8052 { 8053 PetscFunctionBegin; 8054 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8055 PetscValidType(mat, 1); 8056 if (ia) PetscValidPointer(ia, 6); 8057 if (ja) PetscValidPointer(ja, 7); 8058 PetscValidBoolPointer(done, 8); 8059 MatCheckPreallocated(mat, 1); 8060 8061 if (!mat->ops->restorecolumnij) *done = PETSC_FALSE; 8062 else { 8063 *done = PETSC_TRUE; 8064 PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8065 if (n) *n = 0; 8066 if (ia) *ia = NULL; 8067 if (ja) *ja = NULL; 8068 } 8069 PetscFunctionReturn(PETSC_SUCCESS); 8070 } 8071 8072 /*@C 8073 MatColoringPatch -Used inside matrix coloring routines that use `MatGetRowIJ()` and/or `MatGetColumnIJ()`. 8074 8075 Collective 8076 8077 Input Parameters: 8078 + mat - the matrix 8079 . ncolors - max color value 8080 . n - number of entries in colorarray 8081 - colorarray - array indicating color for each column 8082 8083 Output Parameters: 8084 . iscoloring - coloring generated using colorarray information 8085 8086 Level: developer 8087 8088 .seealso: `MatGetRowIJ()`, `MatGetColumnIJ()` 8089 @*/ 8090 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring) 8091 { 8092 PetscFunctionBegin; 8093 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8094 PetscValidType(mat, 1); 8095 PetscValidIntPointer(colorarray, 4); 8096 PetscValidPointer(iscoloring, 5); 8097 MatCheckPreallocated(mat, 1); 8098 8099 if (!mat->ops->coloringpatch) { 8100 PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring)); 8101 } else { 8102 PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring); 8103 } 8104 PetscFunctionReturn(PETSC_SUCCESS); 8105 } 8106 8107 /*@ 8108 MatSetUnfactored - Resets a factored matrix to be treated as unfactored. 8109 8110 Logically Collective 8111 8112 Input Parameter: 8113 . mat - the factored matrix to be reset 8114 8115 Notes: 8116 This routine should be used only with factored matrices formed by in-place 8117 factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE` 8118 format). This option can save memory, for example, when solving nonlinear 8119 systems with a matrix-free Newton-Krylov method and a matrix-based, in-place 8120 ILU(0) preconditioner. 8121 8122 Note that one can specify in-place ILU(0) factorization by calling 8123 .vb 8124 PCType(pc,PCILU); 8125 PCFactorSeUseInPlace(pc); 8126 .ve 8127 or by using the options -pc_type ilu -pc_factor_in_place 8128 8129 In-place factorization ILU(0) can also be used as a local 8130 solver for the blocks within the block Jacobi or additive Schwarz 8131 methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc 8132 for details on setting local solver options. 8133 8134 Most users should employ the `KSP` interface for linear solvers 8135 instead of working directly with matrix algebra routines such as this. 8136 See, e.g., `KSPCreate()`. 8137 8138 Level: developer 8139 8140 .seealso: `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()` 8141 @*/ 8142 PetscErrorCode MatSetUnfactored(Mat mat) 8143 { 8144 PetscFunctionBegin; 8145 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8146 PetscValidType(mat, 1); 8147 MatCheckPreallocated(mat, 1); 8148 mat->factortype = MAT_FACTOR_NONE; 8149 if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS); 8150 PetscUseTypeMethod(mat, setunfactored); 8151 PetscFunctionReturn(PETSC_SUCCESS); 8152 } 8153 8154 /*MC 8155 MatDenseGetArrayF90 - Accesses a matrix array from Fortran 8156 8157 Synopsis: 8158 MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8159 8160 Not collective 8161 8162 Input Parameter: 8163 . x - matrix 8164 8165 Output Parameters: 8166 + xx_v - the Fortran pointer to the array 8167 - ierr - error code 8168 8169 Example of Usage: 8170 .vb 8171 PetscScalar, pointer xx_v(:,:) 8172 .... 8173 call MatDenseGetArrayF90(x,xx_v,ierr) 8174 a = xx_v(3) 8175 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8176 .ve 8177 8178 Level: advanced 8179 8180 .seealso: `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()` 8181 8182 M*/ 8183 8184 /*MC 8185 MatDenseRestoreArrayF90 - Restores a matrix array that has been 8186 accessed with `MatDenseGetArrayF90()`. 8187 8188 Synopsis: 8189 MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8190 8191 Not collective 8192 8193 Input Parameters: 8194 + x - matrix 8195 - xx_v - the Fortran90 pointer to the array 8196 8197 Output Parameter: 8198 . ierr - error code 8199 8200 Example of Usage: 8201 .vb 8202 PetscScalar, pointer xx_v(:,:) 8203 .... 8204 call MatDenseGetArrayF90(x,xx_v,ierr) 8205 a = xx_v(3) 8206 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8207 .ve 8208 8209 Level: advanced 8210 8211 .seealso: `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()` 8212 8213 M*/ 8214 8215 /*MC 8216 MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran. 8217 8218 Synopsis: 8219 MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8220 8221 Not collective 8222 8223 Input Parameter: 8224 . x - matrix 8225 8226 Output Parameters: 8227 + xx_v - the Fortran pointer to the array 8228 - ierr - error code 8229 8230 Example of Usage: 8231 .vb 8232 PetscScalar, pointer xx_v(:) 8233 .... 8234 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8235 a = xx_v(3) 8236 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8237 .ve 8238 8239 Level: advanced 8240 8241 .seealso: `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()` 8242 8243 M*/ 8244 8245 /*MC 8246 MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been 8247 accessed with `MatSeqAIJGetArrayF90()`. 8248 8249 Synopsis: 8250 MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8251 8252 Not collective 8253 8254 Input Parameters: 8255 + x - matrix 8256 - xx_v - the Fortran90 pointer to the array 8257 8258 Output Parameter: 8259 . ierr - error code 8260 8261 Example of Usage: 8262 .vb 8263 PetscScalar, pointer xx_v(:) 8264 .... 8265 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8266 a = xx_v(3) 8267 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8268 .ve 8269 8270 Level: advanced 8271 8272 .seealso: `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()` 8273 8274 M*/ 8275 8276 /*@ 8277 MatCreateSubMatrix - Gets a single submatrix on the same number of processors 8278 as the original matrix. 8279 8280 Collective 8281 8282 Input Parameters: 8283 + mat - the original matrix 8284 . isrow - parallel IS containing the rows this processor should obtain 8285 . 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. 8286 - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 8287 8288 Output Parameter: 8289 . newmat - the new submatrix, of the same type as the old 8290 8291 Level: advanced 8292 8293 Notes: 8294 The submatrix will be able to be multiplied with vectors using the same layout as iscol. 8295 8296 Some matrix types place restrictions on the row and column indices, such 8297 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; 8298 for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row. 8299 8300 The index sets may not have duplicate entries. 8301 8302 The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`, 8303 the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls 8304 to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX` 8305 will reuse the matrix generated the first time. You should call `MatDestroy()` on newmat when 8306 you are finished using it. 8307 8308 The communicator of the newly obtained matrix is ALWAYS the same as the communicator of 8309 the input matrix. 8310 8311 If iscol is NULL then all columns are obtained (not supported in Fortran). 8312 8313 Example usage: 8314 Consider the following 8x8 matrix with 34 non-zero values, that is 8315 assembled across 3 processors. Let's assume that proc0 owns 3 rows, 8316 proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 8317 as follows: 8318 8319 .vb 8320 1 2 0 | 0 3 0 | 0 4 8321 Proc0 0 5 6 | 7 0 0 | 8 0 8322 9 0 10 | 11 0 0 | 12 0 8323 ------------------------------------- 8324 13 0 14 | 15 16 17 | 0 0 8325 Proc1 0 18 0 | 19 20 21 | 0 0 8326 0 0 0 | 22 23 0 | 24 0 8327 ------------------------------------- 8328 Proc2 25 26 27 | 0 0 28 | 29 0 8329 30 0 0 | 31 32 33 | 0 34 8330 .ve 8331 8332 Suppose isrow = [0 1 | 4 | 6 7] and iscol = [1 2 | 3 4 5 | 6]. The resulting submatrix is 8333 8334 .vb 8335 2 0 | 0 3 0 | 0 8336 Proc0 5 6 | 7 0 0 | 8 8337 ------------------------------- 8338 Proc1 18 0 | 19 20 21 | 0 8339 ------------------------------- 8340 Proc2 26 27 | 0 0 28 | 29 8341 0 0 | 31 32 33 | 0 8342 .ve 8343 8344 .seealso: `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()` 8345 @*/ 8346 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat) 8347 { 8348 PetscMPIInt size; 8349 Mat *local; 8350 IS iscoltmp; 8351 PetscBool flg; 8352 8353 PetscFunctionBegin; 8354 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8355 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 8356 if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 8357 PetscValidPointer(newmat, 5); 8358 if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5); 8359 PetscValidType(mat, 1); 8360 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8361 PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX"); 8362 8363 MatCheckPreallocated(mat, 1); 8364 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8365 8366 if (!iscol || isrow == iscol) { 8367 PetscBool stride; 8368 PetscMPIInt grabentirematrix = 0, grab; 8369 PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride)); 8370 if (stride) { 8371 PetscInt first, step, n, rstart, rend; 8372 PetscCall(ISStrideGetInfo(isrow, &first, &step)); 8373 if (step == 1) { 8374 PetscCall(MatGetOwnershipRange(mat, &rstart, &rend)); 8375 if (rstart == first) { 8376 PetscCall(ISGetLocalSize(isrow, &n)); 8377 if (n == rend - rstart) grabentirematrix = 1; 8378 } 8379 } 8380 } 8381 PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat))); 8382 if (grab) { 8383 PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n")); 8384 if (cll == MAT_INITIAL_MATRIX) { 8385 *newmat = mat; 8386 PetscCall(PetscObjectReference((PetscObject)mat)); 8387 } 8388 PetscFunctionReturn(PETSC_SUCCESS); 8389 } 8390 } 8391 8392 if (!iscol) { 8393 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp)); 8394 } else { 8395 iscoltmp = iscol; 8396 } 8397 8398 /* if original matrix is on just one processor then use submatrix generated */ 8399 if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) { 8400 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat)); 8401 goto setproperties; 8402 } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) { 8403 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local)); 8404 *newmat = *local; 8405 PetscCall(PetscFree(local)); 8406 goto setproperties; 8407 } else if (!mat->ops->createsubmatrix) { 8408 /* Create a new matrix type that implements the operation using the full matrix */ 8409 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8410 switch (cll) { 8411 case MAT_INITIAL_MATRIX: 8412 PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat)); 8413 break; 8414 case MAT_REUSE_MATRIX: 8415 PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp)); 8416 break; 8417 default: 8418 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX"); 8419 } 8420 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8421 goto setproperties; 8422 } 8423 8424 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8425 PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat); 8426 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8427 8428 setproperties: 8429 PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg)); 8430 if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat)); 8431 if (!iscol) PetscCall(ISDestroy(&iscoltmp)); 8432 if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat)); 8433 PetscFunctionReturn(PETSC_SUCCESS); 8434 } 8435 8436 /*@ 8437 MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix 8438 8439 Not Collective 8440 8441 Input Parameters: 8442 + A - the matrix we wish to propagate options from 8443 - B - the matrix we wish to propagate options to 8444 8445 Level: beginner 8446 8447 Note: 8448 Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL` 8449 8450 .seealso: `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, MatIsStructurallySymmetricKnown()` 8451 @*/ 8452 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B) 8453 { 8454 PetscFunctionBegin; 8455 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8456 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 8457 B->symmetry_eternal = A->symmetry_eternal; 8458 B->structural_symmetry_eternal = A->structural_symmetry_eternal; 8459 B->symmetric = A->symmetric; 8460 B->structurally_symmetric = A->structurally_symmetric; 8461 B->spd = A->spd; 8462 B->hermitian = A->hermitian; 8463 PetscFunctionReturn(PETSC_SUCCESS); 8464 } 8465 8466 /*@ 8467 MatStashSetInitialSize - sets the sizes of the matrix stash, that is 8468 used during the assembly process to store values that belong to 8469 other processors. 8470 8471 Not Collective 8472 8473 Input Parameters: 8474 + mat - the matrix 8475 . size - the initial size of the stash. 8476 - bsize - the initial size of the block-stash(if used). 8477 8478 Options Database Keys: 8479 + -matstash_initial_size <size> or <size0,size1,...sizep-1> 8480 - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1> 8481 8482 Level: intermediate 8483 8484 Notes: 8485 The block-stash is used for values set with `MatSetValuesBlocked()` while 8486 the stash is used for values set with `MatSetValues()` 8487 8488 Run with the option -info and look for output of the form 8489 MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs. 8490 to determine the appropriate value, MM, to use for size and 8491 MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs. 8492 to determine the value, BMM to use for bsize 8493 8494 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()` 8495 @*/ 8496 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize) 8497 { 8498 PetscFunctionBegin; 8499 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8500 PetscValidType(mat, 1); 8501 PetscCall(MatStashSetInitialSize_Private(&mat->stash, size)); 8502 PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize)); 8503 PetscFunctionReturn(PETSC_SUCCESS); 8504 } 8505 8506 /*@ 8507 MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of 8508 the matrix 8509 8510 Neighbor-wise Collective 8511 8512 Input Parameters: 8513 + mat - the matrix 8514 . x,y - the vectors 8515 - w - where the result is stored 8516 8517 Level: intermediate 8518 8519 Notes: 8520 w may be the same vector as y. 8521 8522 This allows one to use either the restriction or interpolation (its transpose) 8523 matrix to do the interpolation 8524 8525 .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8526 @*/ 8527 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w) 8528 { 8529 PetscInt M, N, Ny; 8530 8531 PetscFunctionBegin; 8532 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8533 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8534 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8535 PetscValidHeaderSpecific(w, VEC_CLASSID, 4); 8536 PetscCall(MatGetSize(A, &M, &N)); 8537 PetscCall(VecGetSize(y, &Ny)); 8538 if (M == Ny) { 8539 PetscCall(MatMultAdd(A, x, y, w)); 8540 } else { 8541 PetscCall(MatMultTransposeAdd(A, x, y, w)); 8542 } 8543 PetscFunctionReturn(PETSC_SUCCESS); 8544 } 8545 8546 /*@ 8547 MatInterpolate - y = A*x or A'*x depending on the shape of 8548 the matrix 8549 8550 Neighbor-wise Collective 8551 8552 Input Parameters: 8553 + mat - the matrix 8554 - x,y - the vectors 8555 8556 Level: intermediate 8557 8558 Note: 8559 This allows one to use either the restriction or interpolation (its transpose) 8560 matrix to do the interpolation 8561 8562 .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8563 @*/ 8564 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y) 8565 { 8566 PetscInt M, N, Ny; 8567 8568 PetscFunctionBegin; 8569 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8570 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8571 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8572 PetscCall(MatGetSize(A, &M, &N)); 8573 PetscCall(VecGetSize(y, &Ny)); 8574 if (M == Ny) { 8575 PetscCall(MatMult(A, x, y)); 8576 } else { 8577 PetscCall(MatMultTranspose(A, x, y)); 8578 } 8579 PetscFunctionReturn(PETSC_SUCCESS); 8580 } 8581 8582 /*@ 8583 MatRestrict - y = A*x or A'*x 8584 8585 Neighbor-wise Collective on Mat 8586 8587 Input Parameters: 8588 + mat - the matrix 8589 - x,y - the vectors 8590 8591 Level: intermediate 8592 8593 Note: 8594 This allows one to use either the restriction or interpolation (its transpose) 8595 matrix to do the restriction 8596 8597 .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG` 8598 @*/ 8599 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y) 8600 { 8601 PetscInt M, N, Ny; 8602 8603 PetscFunctionBegin; 8604 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8605 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8606 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8607 PetscCall(MatGetSize(A, &M, &N)); 8608 PetscCall(VecGetSize(y, &Ny)); 8609 if (M == Ny) { 8610 PetscCall(MatMult(A, x, y)); 8611 } else { 8612 PetscCall(MatMultTranspose(A, x, y)); 8613 } 8614 PetscFunctionReturn(PETSC_SUCCESS); 8615 } 8616 8617 /*@ 8618 MatMatInterpolateAdd - Y = W + A*X or W + A'*X 8619 8620 Neighbor-wise Collective on Mat 8621 8622 Input Parameters: 8623 + mat - the matrix 8624 - w, x - the input dense matrices 8625 8626 Output Parameters: 8627 . y - the output dense matrix 8628 8629 Level: intermediate 8630 8631 Note: 8632 This allows one to use either the restriction or interpolation (its transpose) 8633 matrix to do the interpolation. y matrix can be reused if already created with the proper sizes, 8634 otherwise it will be recreated. y must be initialized to NULL if not supplied. 8635 8636 .seealso: `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG` 8637 @*/ 8638 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y) 8639 { 8640 PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0; 8641 PetscBool trans = PETSC_TRUE; 8642 MatReuse reuse = MAT_INITIAL_MATRIX; 8643 8644 PetscFunctionBegin; 8645 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8646 PetscValidHeaderSpecific(x, MAT_CLASSID, 2); 8647 PetscValidType(x, 2); 8648 if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3); 8649 if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4); 8650 PetscCall(MatGetSize(A, &M, &N)); 8651 PetscCall(MatGetSize(x, &Mx, &Nx)); 8652 if (N == Mx) trans = PETSC_FALSE; 8653 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); 8654 Mo = trans ? N : M; 8655 if (*y) { 8656 PetscCall(MatGetSize(*y, &My, &Ny)); 8657 if (Mo == My && Nx == Ny) { 8658 reuse = MAT_REUSE_MATRIX; 8659 } else { 8660 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); 8661 PetscCall(MatDestroy(y)); 8662 } 8663 } 8664 8665 if (w && *y == w) { /* this is to minimize changes in PCMG */ 8666 PetscBool flg; 8667 8668 PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w)); 8669 if (w) { 8670 PetscInt My, Ny, Mw, Nw; 8671 8672 PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg)); 8673 PetscCall(MatGetSize(*y, &My, &Ny)); 8674 PetscCall(MatGetSize(w, &Mw, &Nw)); 8675 if (!flg || My != Mw || Ny != Nw) w = NULL; 8676 } 8677 if (!w) { 8678 PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w)); 8679 PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w)); 8680 PetscCall(PetscObjectDereference((PetscObject)w)); 8681 } else { 8682 PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN)); 8683 } 8684 } 8685 if (!trans) { 8686 PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8687 } else { 8688 PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8689 } 8690 if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN)); 8691 PetscFunctionReturn(PETSC_SUCCESS); 8692 } 8693 8694 /*@ 8695 MatMatInterpolate - Y = A*X or A'*X 8696 8697 Neighbor-wise Collective on Mat 8698 8699 Input Parameters: 8700 + mat - the matrix 8701 - x - the input dense matrix 8702 8703 Output Parameters: 8704 . y - the output dense matrix 8705 8706 Level: intermediate 8707 8708 Note: 8709 This allows one to use either the restriction or interpolation (its transpose) 8710 matrix to do the interpolation. y matrix can be reused if already created with the proper sizes, 8711 otherwise it will be recreated. y must be initialized to NULL if not supplied. 8712 8713 .seealso: `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG` 8714 @*/ 8715 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y) 8716 { 8717 PetscFunctionBegin; 8718 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8719 PetscFunctionReturn(PETSC_SUCCESS); 8720 } 8721 8722 /*@ 8723 MatMatRestrict - Y = A*X or A'*X 8724 8725 Neighbor-wise Collective on Mat 8726 8727 Input Parameters: 8728 + mat - the matrix 8729 - x - the input dense matrix 8730 8731 Output Parameters: 8732 . y - the output dense matrix 8733 8734 Level: intermediate 8735 8736 Note: 8737 This allows one to use either the restriction or interpolation (its transpose) 8738 matrix to do the restriction. y matrix can be reused if already created with the proper sizes, 8739 otherwise it will be recreated. y must be initialized to NULL if not supplied. 8740 8741 .seealso: `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG` 8742 @*/ 8743 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y) 8744 { 8745 PetscFunctionBegin; 8746 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8747 PetscFunctionReturn(PETSC_SUCCESS); 8748 } 8749 8750 /*@ 8751 MatGetNullSpace - retrieves the null space of a matrix. 8752 8753 Logically Collective 8754 8755 Input Parameters: 8756 + mat - the matrix 8757 - nullsp - the null space object 8758 8759 Level: developer 8760 8761 .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace` 8762 @*/ 8763 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp) 8764 { 8765 PetscFunctionBegin; 8766 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8767 PetscValidPointer(nullsp, 2); 8768 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp; 8769 PetscFunctionReturn(PETSC_SUCCESS); 8770 } 8771 8772 /*@ 8773 MatSetNullSpace - attaches a null space to a matrix. 8774 8775 Logically Collective 8776 8777 Input Parameters: 8778 + mat - the matrix 8779 - nullsp - the null space object 8780 8781 Level: advanced 8782 8783 Notes: 8784 This null space is used by the `KSP` linear solvers to solve singular systems. 8785 8786 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 8787 8788 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 8789 to zero but the linear system will still be solved in a least squares sense. 8790 8791 The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that 8792 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). 8793 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 8794 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 8795 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). 8796 This \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix. 8797 8798 If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called 8799 `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this 8800 routine also automatically calls `MatSetTransposeNullSpace()`. 8801 8802 The user should call `MatNullSpaceDestroy()`. 8803 8804 .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, 8805 `KSPSetPCSide()` 8806 @*/ 8807 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp) 8808 { 8809 PetscFunctionBegin; 8810 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8811 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8812 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8813 PetscCall(MatNullSpaceDestroy(&mat->nullsp)); 8814 mat->nullsp = nullsp; 8815 if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp)); 8816 PetscFunctionReturn(PETSC_SUCCESS); 8817 } 8818 8819 /*@ 8820 MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix. 8821 8822 Logically Collective 8823 8824 Input Parameters: 8825 + mat - the matrix 8826 - nullsp - the null space object 8827 8828 Level: developer 8829 8830 .seealso: `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()` 8831 @*/ 8832 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp) 8833 { 8834 PetscFunctionBegin; 8835 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8836 PetscValidType(mat, 1); 8837 PetscValidPointer(nullsp, 2); 8838 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp; 8839 PetscFunctionReturn(PETSC_SUCCESS); 8840 } 8841 8842 /*@ 8843 MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix 8844 8845 Logically Collective 8846 8847 Input Parameters: 8848 + mat - the matrix 8849 - nullsp - the null space object 8850 8851 Level: advanced 8852 8853 Notes: 8854 This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning. 8855 8856 See `MatSetNullSpace()` 8857 8858 .seealso: `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()` 8859 @*/ 8860 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp) 8861 { 8862 PetscFunctionBegin; 8863 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8864 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8865 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8866 PetscCall(MatNullSpaceDestroy(&mat->transnullsp)); 8867 mat->transnullsp = nullsp; 8868 PetscFunctionReturn(PETSC_SUCCESS); 8869 } 8870 8871 /*@ 8872 MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions 8873 This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix. 8874 8875 Logically Collective 8876 8877 Input Parameters: 8878 + mat - the matrix 8879 - nullsp - the null space object 8880 8881 Level: advanced 8882 8883 Notes: 8884 Overwrites any previous near null space that may have been attached 8885 8886 You can remove the null space by calling this routine with an nullsp of NULL 8887 8888 .seealso: `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()` 8889 @*/ 8890 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp) 8891 { 8892 PetscFunctionBegin; 8893 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8894 PetscValidType(mat, 1); 8895 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8896 MatCheckPreallocated(mat, 1); 8897 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8898 PetscCall(MatNullSpaceDestroy(&mat->nearnullsp)); 8899 mat->nearnullsp = nullsp; 8900 PetscFunctionReturn(PETSC_SUCCESS); 8901 } 8902 8903 /*@ 8904 MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()` 8905 8906 Not Collective 8907 8908 Input Parameter: 8909 . mat - the matrix 8910 8911 Output Parameter: 8912 . nullsp - the null space object, NULL if not set 8913 8914 Level: advanced 8915 8916 .seealso: `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()` 8917 @*/ 8918 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp) 8919 { 8920 PetscFunctionBegin; 8921 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8922 PetscValidType(mat, 1); 8923 PetscValidPointer(nullsp, 2); 8924 MatCheckPreallocated(mat, 1); 8925 *nullsp = mat->nearnullsp; 8926 PetscFunctionReturn(PETSC_SUCCESS); 8927 } 8928 8929 /*@C 8930 MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix. 8931 8932 Collective 8933 8934 Input Parameters: 8935 + mat - the matrix 8936 . row - row/column permutation 8937 . fill - expected fill factor >= 1.0 8938 - level - level of fill, for ICC(k) 8939 8940 Notes: 8941 Probably really in-place only when level of fill is zero, otherwise allocates 8942 new space to store factored matrix and deletes previous memory. 8943 8944 Most users should employ the `KSP` interface for linear solvers 8945 instead of working directly with matrix algebra routines such as this. 8946 See, e.g., `KSPCreate()`. 8947 8948 Level: developer 8949 8950 Developer Note: 8951 The Fortran interface is not autogenerated as the 8952 interface definition cannot be generated correctly [due to `MatFactorInfo`] 8953 8954 .seealso: `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 8955 @*/ 8956 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info) 8957 { 8958 PetscFunctionBegin; 8959 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8960 PetscValidType(mat, 1); 8961 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 8962 PetscValidPointer(info, 3); 8963 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 8964 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 8965 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8966 MatCheckPreallocated(mat, 1); 8967 PetscUseTypeMethod(mat, iccfactor, row, info); 8968 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 8969 PetscFunctionReturn(PETSC_SUCCESS); 8970 } 8971 8972 /*@ 8973 MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the 8974 ghosted ones. 8975 8976 Not Collective 8977 8978 Input Parameters: 8979 + mat - the matrix 8980 - diag - the diagonal values, including ghost ones 8981 8982 Level: developer 8983 8984 Notes: 8985 Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices 8986 8987 This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()` 8988 8989 .seealso: `MatDiagonalScale()` 8990 @*/ 8991 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag) 8992 { 8993 PetscMPIInt size; 8994 8995 PetscFunctionBegin; 8996 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8997 PetscValidHeaderSpecific(diag, VEC_CLASSID, 2); 8998 PetscValidType(mat, 1); 8999 9000 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled"); 9001 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 9002 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 9003 if (size == 1) { 9004 PetscInt n, m; 9005 PetscCall(VecGetSize(diag, &n)); 9006 PetscCall(MatGetSize(mat, NULL, &m)); 9007 PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions"); 9008 PetscCall(MatDiagonalScale(mat, NULL, diag)); 9009 } else { 9010 PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag)); 9011 } 9012 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 9013 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9014 PetscFunctionReturn(PETSC_SUCCESS); 9015 } 9016 9017 /*@ 9018 MatGetInertia - Gets the inertia from a factored matrix 9019 9020 Collective 9021 9022 Input Parameter: 9023 . mat - the matrix 9024 9025 Output Parameters: 9026 + nneg - number of negative eigenvalues 9027 . nzero - number of zero eigenvalues 9028 - npos - number of positive eigenvalues 9029 9030 Level: advanced 9031 9032 Note: 9033 Matrix must have been factored by `MatCholeskyFactor()` 9034 9035 .seealso: `MatGetFactor()`, `MatCholeskyFactor()` 9036 @*/ 9037 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos) 9038 { 9039 PetscFunctionBegin; 9040 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9041 PetscValidType(mat, 1); 9042 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9043 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled"); 9044 PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos); 9045 PetscFunctionReturn(PETSC_SUCCESS); 9046 } 9047 9048 /* ----------------------------------------------------------------*/ 9049 /*@C 9050 MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors 9051 9052 Neighbor-wise Collective 9053 9054 Input Parameters: 9055 + mat - the factored matrix obtained with `MatGetFactor()` 9056 - b - the right-hand-side vectors 9057 9058 Output Parameter: 9059 . x - the result vectors 9060 9061 Note: 9062 The vectors b and x cannot be the same. I.e., one cannot 9063 call `MatSolves`(A,x,x). 9064 9065 Level: developer 9066 9067 .seealso: `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()` 9068 @*/ 9069 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x) 9070 { 9071 PetscFunctionBegin; 9072 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9073 PetscValidType(mat, 1); 9074 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 9075 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9076 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 9077 9078 MatCheckPreallocated(mat, 1); 9079 PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0)); 9080 PetscUseTypeMethod(mat, solves, b, x); 9081 PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0)); 9082 PetscFunctionReturn(PETSC_SUCCESS); 9083 } 9084 9085 /*@ 9086 MatIsSymmetric - Test whether a matrix is symmetric 9087 9088 Collective 9089 9090 Input Parameters: 9091 + A - the matrix to test 9092 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose) 9093 9094 Output Parameters: 9095 . flg - the result 9096 9097 Notes: 9098 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9099 9100 If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()` 9101 9102 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9103 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9104 9105 Level: intermediate 9106 9107 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`, 9108 `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()` 9109 @*/ 9110 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg) 9111 { 9112 PetscFunctionBegin; 9113 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9114 PetscValidBoolPointer(flg, 3); 9115 9116 if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE; 9117 else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE; 9118 else { 9119 if (!A->ops->issymmetric) { 9120 MatType mattype; 9121 PetscCall(MatGetType(A, &mattype)); 9122 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for symmetric", mattype); 9123 } 9124 PetscUseTypeMethod(A, issymmetric, tol, flg); 9125 if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg)); 9126 } 9127 PetscFunctionReturn(PETSC_SUCCESS); 9128 } 9129 9130 /*@ 9131 MatIsHermitian - Test whether a matrix is Hermitian 9132 9133 Collective on Mat 9134 9135 Input Parameters: 9136 + A - the matrix to test 9137 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian) 9138 9139 Output Parameters: 9140 . flg - the result 9141 9142 Level: intermediate 9143 9144 Notes: 9145 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9146 9147 If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()` 9148 9149 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9150 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`) 9151 9152 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, 9153 `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()` 9154 @*/ 9155 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg) 9156 { 9157 PetscFunctionBegin; 9158 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9159 PetscValidBoolPointer(flg, 3); 9160 9161 if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE; 9162 else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE; 9163 else { 9164 if (!A->ops->ishermitian) { 9165 MatType mattype; 9166 PetscCall(MatGetType(A, &mattype)); 9167 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for hermitian", mattype); 9168 } 9169 PetscUseTypeMethod(A, ishermitian, tol, flg); 9170 if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg)); 9171 } 9172 PetscFunctionReturn(PETSC_SUCCESS); 9173 } 9174 9175 /*@ 9176 MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state 9177 9178 Not Collective 9179 9180 Input Parameter: 9181 . A - the matrix to check 9182 9183 Output Parameters: 9184 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid) 9185 - flg - the result (only valid if set is `PETSC_TRUE`) 9186 9187 Level: advanced 9188 9189 Notes: 9190 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()` 9191 if you want it explicitly checked 9192 9193 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9194 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9195 9196 .seealso: `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9197 @*/ 9198 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9199 { 9200 PetscFunctionBegin; 9201 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9202 PetscValidBoolPointer(set, 2); 9203 PetscValidBoolPointer(flg, 3); 9204 if (A->symmetric != PETSC_BOOL3_UNKNOWN) { 9205 *set = PETSC_TRUE; 9206 *flg = PetscBool3ToBool(A->symmetric); 9207 } else { 9208 *set = PETSC_FALSE; 9209 } 9210 PetscFunctionReturn(PETSC_SUCCESS); 9211 } 9212 9213 /*@ 9214 MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state 9215 9216 Not Collective 9217 9218 Input Parameter: 9219 . A - the matrix to check 9220 9221 Output Parameters: 9222 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid) 9223 - flg - the result (only valid if set is `PETSC_TRUE`) 9224 9225 Level: advanced 9226 9227 Notes: 9228 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). 9229 9230 One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD 9231 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`) 9232 9233 .seealso: `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9234 @*/ 9235 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg) 9236 { 9237 PetscFunctionBegin; 9238 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9239 PetscValidBoolPointer(set, 2); 9240 PetscValidBoolPointer(flg, 3); 9241 if (A->spd != PETSC_BOOL3_UNKNOWN) { 9242 *set = PETSC_TRUE; 9243 *flg = PetscBool3ToBool(A->spd); 9244 } else { 9245 *set = PETSC_FALSE; 9246 } 9247 PetscFunctionReturn(PETSC_SUCCESS); 9248 } 9249 9250 /*@ 9251 MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state 9252 9253 Not Collective 9254 9255 Input Parameter: 9256 . A - the matrix to check 9257 9258 Output Parameters: 9259 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid) 9260 - flg - the result (only valid if set is `PETSC_TRUE`) 9261 9262 Level: advanced 9263 9264 Notes: 9265 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()` 9266 if you want it explicitly checked 9267 9268 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9269 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9270 9271 .seealso: `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()` 9272 @*/ 9273 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg) 9274 { 9275 PetscFunctionBegin; 9276 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9277 PetscValidBoolPointer(set, 2); 9278 PetscValidBoolPointer(flg, 3); 9279 if (A->hermitian != PETSC_BOOL3_UNKNOWN) { 9280 *set = PETSC_TRUE; 9281 *flg = PetscBool3ToBool(A->hermitian); 9282 } else { 9283 *set = PETSC_FALSE; 9284 } 9285 PetscFunctionReturn(PETSC_SUCCESS); 9286 } 9287 9288 /*@ 9289 MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric 9290 9291 Collective on Mat 9292 9293 Input Parameter: 9294 . A - the matrix to test 9295 9296 Output Parameters: 9297 . flg - the result 9298 9299 Notes: 9300 If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()` 9301 9302 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 9303 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9304 9305 Level: intermediate 9306 9307 .seealso: `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()` 9308 @*/ 9309 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg) 9310 { 9311 PetscFunctionBegin; 9312 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9313 PetscValidBoolPointer(flg, 2); 9314 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9315 *flg = PetscBool3ToBool(A->structurally_symmetric); 9316 } else { 9317 PetscUseTypeMethod(A, isstructurallysymmetric, flg); 9318 PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg)); 9319 } 9320 PetscFunctionReturn(PETSC_SUCCESS); 9321 } 9322 9323 /*@ 9324 MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state 9325 9326 Not Collective 9327 9328 Input Parameter: 9329 . A - the matrix to check 9330 9331 Output Parameters: 9332 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid) 9333 - flg - the result (only valid if set is PETSC_TRUE) 9334 9335 Level: advanced 9336 9337 Notes: 9338 One can declare that a matrix is structurally symmetric with `MatSetOption`(mat,`MAT_STRUCTURALLY_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain structurally 9339 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9340 9341 Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation) 9342 9343 .seealso: `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9344 @*/ 9345 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9346 { 9347 PetscFunctionBegin; 9348 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9349 PetscValidBoolPointer(set, 2); 9350 PetscValidBoolPointer(flg, 3); 9351 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9352 *set = PETSC_TRUE; 9353 *flg = PetscBool3ToBool(A->structurally_symmetric); 9354 } else { 9355 *set = PETSC_FALSE; 9356 } 9357 PetscFunctionReturn(PETSC_SUCCESS); 9358 } 9359 9360 /*@ 9361 MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need 9362 to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process 9363 9364 Not collective 9365 9366 Input Parameter: 9367 . mat - the matrix 9368 9369 Output Parameters: 9370 + nstash - the size of the stash 9371 . reallocs - the number of additional mallocs incurred. 9372 . bnstash - the size of the block stash 9373 - breallocs - the number of additional mallocs incurred.in the block stash 9374 9375 Level: advanced 9376 9377 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()` 9378 @*/ 9379 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs) 9380 { 9381 PetscFunctionBegin; 9382 PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs)); 9383 PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs)); 9384 PetscFunctionReturn(PETSC_SUCCESS); 9385 } 9386 9387 /*@C 9388 MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same 9389 parallel layout, `PetscLayout` for rows and columns 9390 9391 Collective 9392 9393 Input Parameter: 9394 . mat - the matrix 9395 9396 Output Parameters: 9397 + right - (optional) vector that the matrix can be multiplied against 9398 - left - (optional) vector that the matrix vector product can be stored in 9399 9400 Notes: 9401 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()`. 9402 9403 These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed 9404 9405 Level: advanced 9406 9407 .seealso: `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()` 9408 @*/ 9409 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left) 9410 { 9411 PetscFunctionBegin; 9412 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9413 PetscValidType(mat, 1); 9414 if (mat->ops->getvecs) { 9415 PetscUseTypeMethod(mat, getvecs, right, left); 9416 } else { 9417 PetscInt rbs, cbs; 9418 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 9419 if (right) { 9420 PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup"); 9421 PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), right)); 9422 PetscCall(VecSetSizes(*right, mat->cmap->n, PETSC_DETERMINE)); 9423 PetscCall(VecSetBlockSize(*right, cbs)); 9424 PetscCall(VecSetType(*right, mat->defaultvectype)); 9425 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9426 if (mat->boundtocpu && mat->bindingpropagates) { 9427 PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE)); 9428 PetscCall(VecBindToCPU(*right, PETSC_TRUE)); 9429 } 9430 #endif 9431 PetscCall(PetscLayoutReference(mat->cmap, &(*right)->map)); 9432 } 9433 if (left) { 9434 PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup"); 9435 PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), left)); 9436 PetscCall(VecSetSizes(*left, mat->rmap->n, PETSC_DETERMINE)); 9437 PetscCall(VecSetBlockSize(*left, rbs)); 9438 PetscCall(VecSetType(*left, mat->defaultvectype)); 9439 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9440 if (mat->boundtocpu && mat->bindingpropagates) { 9441 PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE)); 9442 PetscCall(VecBindToCPU(*left, PETSC_TRUE)); 9443 } 9444 #endif 9445 PetscCall(PetscLayoutReference(mat->rmap, &(*left)->map)); 9446 } 9447 } 9448 PetscFunctionReturn(PETSC_SUCCESS); 9449 } 9450 9451 /*@C 9452 MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure 9453 with default values. 9454 9455 Not Collective 9456 9457 Input Parameters: 9458 . info - the `MatFactorInfo` data structure 9459 9460 Notes: 9461 The solvers are generally used through the `KSP` and `PC` objects, for example 9462 `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC` 9463 9464 Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed 9465 9466 Level: developer 9467 9468 Developer Note: 9469 The Fortran interface is not autogenerated as the 9470 interface definition cannot be generated correctly [due to `MatFactorInfo`] 9471 9472 .seealso: `MatGetFactor()`, `MatFactorInfo` 9473 @*/ 9474 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info) 9475 { 9476 PetscFunctionBegin; 9477 PetscCall(PetscMemzero(info, sizeof(MatFactorInfo))); 9478 PetscFunctionReturn(PETSC_SUCCESS); 9479 } 9480 9481 /*@ 9482 MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed 9483 9484 Collective 9485 9486 Input Parameters: 9487 + mat - the factored matrix 9488 - is - the index set defining the Schur indices (0-based) 9489 9490 Notes: 9491 Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system. 9492 9493 You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call. 9494 9495 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9496 9497 Level: advanced 9498 9499 .seealso: `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`, 9500 `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9501 9502 @*/ 9503 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is) 9504 { 9505 PetscErrorCode (*f)(Mat, IS); 9506 9507 PetscFunctionBegin; 9508 PetscValidType(mat, 1); 9509 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9510 PetscValidType(is, 2); 9511 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 9512 PetscCheckSameComm(mat, 1, is, 2); 9513 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 9514 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f)); 9515 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO"); 9516 PetscCall(MatDestroy(&mat->schur)); 9517 PetscCall((*f)(mat, is)); 9518 PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created"); 9519 PetscFunctionReturn(PETSC_SUCCESS); 9520 } 9521 9522 /*@ 9523 MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step 9524 9525 Logically Collective 9526 9527 Input Parameters: 9528 + F - the factored matrix obtained by calling `MatGetFactor()` 9529 . S - location where to return the Schur complement, can be NULL 9530 - status - the status of the Schur complement matrix, can be NULL 9531 9532 Notes: 9533 You must call `MatFactorSetSchurIS()` before calling this routine. 9534 9535 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9536 9537 The routine provides a copy of the Schur matrix stored within the solver data structures. 9538 The caller must destroy the object when it is no longer needed. 9539 If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse. 9540 9541 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) 9542 9543 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9544 9545 Developer Note: 9546 The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc 9547 matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix. 9548 9549 Level: advanced 9550 9551 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9552 @*/ 9553 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9554 { 9555 PetscFunctionBegin; 9556 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9557 if (S) PetscValidPointer(S, 2); 9558 if (status) PetscValidPointer(status, 3); 9559 if (S) { 9560 PetscErrorCode (*f)(Mat, Mat *); 9561 9562 PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f)); 9563 if (f) { 9564 PetscCall((*f)(F, S)); 9565 } else { 9566 PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S)); 9567 } 9568 } 9569 if (status) *status = F->schur_status; 9570 PetscFunctionReturn(PETSC_SUCCESS); 9571 } 9572 9573 /*@ 9574 MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix 9575 9576 Logically Collective 9577 9578 Input Parameters: 9579 + F - the factored matrix obtained by calling `MatGetFactor()` 9580 . *S - location where to return the Schur complement, can be NULL 9581 - status - the status of the Schur complement matrix, can be NULL 9582 9583 Notes: 9584 You must call `MatFactorSetSchurIS()` before calling this routine. 9585 9586 Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS` 9587 9588 The routine returns a the Schur Complement stored within the data structures of the solver. 9589 9590 If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement. 9591 9592 The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed. 9593 9594 Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix 9595 9596 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9597 9598 Level: advanced 9599 9600 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9601 @*/ 9602 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9603 { 9604 PetscFunctionBegin; 9605 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9606 if (S) PetscValidPointer(S, 2); 9607 if (status) PetscValidPointer(status, 3); 9608 if (S) *S = F->schur; 9609 if (status) *status = F->schur_status; 9610 PetscFunctionReturn(PETSC_SUCCESS); 9611 } 9612 9613 /*@ 9614 MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()` 9615 9616 Logically Collective 9617 9618 Input Parameters: 9619 + F - the factored matrix obtained by calling `MatGetFactor()` 9620 . *S - location where the Schur complement is stored 9621 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`) 9622 9623 Level: advanced 9624 9625 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9626 @*/ 9627 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status) 9628 { 9629 PetscFunctionBegin; 9630 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9631 if (S) { 9632 PetscValidHeaderSpecific(*S, MAT_CLASSID, 2); 9633 *S = NULL; 9634 } 9635 F->schur_status = status; 9636 PetscCall(MatFactorUpdateSchurStatus_Private(F)); 9637 PetscFunctionReturn(PETSC_SUCCESS); 9638 } 9639 9640 /*@ 9641 MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step 9642 9643 Logically Collective 9644 9645 Input Parameters: 9646 + F - the factored matrix obtained by calling `MatGetFactor()` 9647 . rhs - location where the right hand side of the Schur complement system is stored 9648 - sol - location where the solution of the Schur complement system has to be returned 9649 9650 Notes: 9651 The sizes of the vectors should match the size of the Schur complement 9652 9653 Must be called after `MatFactorSetSchurIS()` 9654 9655 Level: advanced 9656 9657 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()` 9658 @*/ 9659 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol) 9660 { 9661 PetscFunctionBegin; 9662 PetscValidType(F, 1); 9663 PetscValidType(rhs, 2); 9664 PetscValidType(sol, 3); 9665 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9666 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9667 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9668 PetscCheckSameComm(F, 1, rhs, 2); 9669 PetscCheckSameComm(F, 1, sol, 3); 9670 PetscCall(MatFactorFactorizeSchurComplement(F)); 9671 switch (F->schur_status) { 9672 case MAT_FACTOR_SCHUR_FACTORED: 9673 PetscCall(MatSolveTranspose(F->schur, rhs, sol)); 9674 break; 9675 case MAT_FACTOR_SCHUR_INVERTED: 9676 PetscCall(MatMultTranspose(F->schur, rhs, sol)); 9677 break; 9678 default: 9679 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9680 } 9681 PetscFunctionReturn(PETSC_SUCCESS); 9682 } 9683 9684 /*@ 9685 MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step 9686 9687 Logically Collective 9688 9689 Input Parameters: 9690 + F - the factored matrix obtained by calling `MatGetFactor()` 9691 . rhs - location where the right hand side of the Schur complement system is stored 9692 - sol - location where the solution of the Schur complement system has to be returned 9693 9694 Notes: 9695 The sizes of the vectors should match the size of the Schur complement 9696 9697 Must be called after `MatFactorSetSchurIS()` 9698 9699 Level: advanced 9700 9701 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()` 9702 @*/ 9703 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol) 9704 { 9705 PetscFunctionBegin; 9706 PetscValidType(F, 1); 9707 PetscValidType(rhs, 2); 9708 PetscValidType(sol, 3); 9709 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9710 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9711 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9712 PetscCheckSameComm(F, 1, rhs, 2); 9713 PetscCheckSameComm(F, 1, sol, 3); 9714 PetscCall(MatFactorFactorizeSchurComplement(F)); 9715 switch (F->schur_status) { 9716 case MAT_FACTOR_SCHUR_FACTORED: 9717 PetscCall(MatSolve(F->schur, rhs, sol)); 9718 break; 9719 case MAT_FACTOR_SCHUR_INVERTED: 9720 PetscCall(MatMult(F->schur, rhs, sol)); 9721 break; 9722 default: 9723 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9724 } 9725 PetscFunctionReturn(PETSC_SUCCESS); 9726 } 9727 9728 /*@ 9729 MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step 9730 9731 Logically Collective on F 9732 9733 Input Parameters: 9734 . F - the factored matrix obtained by calling `MatGetFactor()` 9735 9736 Notes: 9737 Must be called after `MatFactorSetSchurIS()`. 9738 9739 Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it. 9740 9741 Level: advanced 9742 9743 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()` 9744 @*/ 9745 PetscErrorCode MatFactorInvertSchurComplement(Mat F) 9746 { 9747 PetscFunctionBegin; 9748 PetscValidType(F, 1); 9749 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9750 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS); 9751 PetscCall(MatFactorFactorizeSchurComplement(F)); 9752 PetscCall(MatFactorInvertSchurComplement_Private(F)); 9753 F->schur_status = MAT_FACTOR_SCHUR_INVERTED; 9754 PetscFunctionReturn(PETSC_SUCCESS); 9755 } 9756 9757 /*@ 9758 MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step 9759 9760 Logically Collective 9761 9762 Input Parameters: 9763 . F - the factored matrix obtained by calling `MatGetFactor()` 9764 9765 Note: 9766 Must be called after `MatFactorSetSchurIS()` 9767 9768 Level: advanced 9769 9770 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()` 9771 @*/ 9772 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F) 9773 { 9774 PetscFunctionBegin; 9775 PetscValidType(F, 1); 9776 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9777 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS); 9778 PetscCall(MatFactorFactorizeSchurComplement_Private(F)); 9779 F->schur_status = MAT_FACTOR_SCHUR_FACTORED; 9780 PetscFunctionReturn(PETSC_SUCCESS); 9781 } 9782 9783 /*@ 9784 MatPtAP - Creates the matrix product C = P^T * A * P 9785 9786 Neighbor-wise Collective on A 9787 9788 Input Parameters: 9789 + A - the matrix 9790 . P - the projection matrix 9791 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9792 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate 9793 if the result is a dense matrix this is irrelevant 9794 9795 Output Parameters: 9796 . C - the product matrix 9797 9798 Notes: 9799 C will be created and must be destroyed by the user with `MatDestroy()`. 9800 9801 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9802 9803 Developer Note: 9804 For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`. 9805 9806 Level: intermediate 9807 9808 .seealso: `MatProductCreate()`, `MatMatMult()`, `MatRARt()` 9809 @*/ 9810 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C) 9811 { 9812 PetscFunctionBegin; 9813 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 9814 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9815 9816 if (scall == MAT_INITIAL_MATRIX) { 9817 PetscCall(MatProductCreate(A, P, NULL, C)); 9818 PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP)); 9819 PetscCall(MatProductSetAlgorithm(*C, "default")); 9820 PetscCall(MatProductSetFill(*C, fill)); 9821 9822 (*C)->product->api_user = PETSC_TRUE; 9823 PetscCall(MatProductSetFromOptions(*C)); 9824 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); 9825 PetscCall(MatProductSymbolic(*C)); 9826 } else { /* scall == MAT_REUSE_MATRIX */ 9827 PetscCall(MatProductReplaceMats(A, P, NULL, *C)); 9828 } 9829 9830 PetscCall(MatProductNumeric(*C)); 9831 (*C)->symmetric = A->symmetric; 9832 (*C)->spd = A->spd; 9833 PetscFunctionReturn(PETSC_SUCCESS); 9834 } 9835 9836 /*@ 9837 MatRARt - Creates the matrix product C = R * A * R^T 9838 9839 Neighbor-wise Collective on A 9840 9841 Input Parameters: 9842 + A - the matrix 9843 . R - the projection matrix 9844 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9845 - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate 9846 if the result is a dense matrix this is irrelevant 9847 9848 Output Parameters: 9849 . C - the product matrix 9850 9851 Notes: 9852 C will be created and must be destroyed by the user with `MatDestroy()`. 9853 9854 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9855 9856 This routine is currently only implemented for pairs of `MATAIJ` matrices and classes 9857 which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes, 9858 parallel MatRARt is implemented via explicit transpose of R, which could be very expensive. 9859 We recommend using MatPtAP(). 9860 9861 Level: intermediate 9862 9863 .seealso: `MatProductCreate()`, `MatMatMult()`, `MatPtAP()` 9864 @*/ 9865 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C) 9866 { 9867 PetscFunctionBegin; 9868 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 9869 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9870 9871 if (scall == MAT_INITIAL_MATRIX) { 9872 PetscCall(MatProductCreate(A, R, NULL, C)); 9873 PetscCall(MatProductSetType(*C, MATPRODUCT_RARt)); 9874 PetscCall(MatProductSetAlgorithm(*C, "default")); 9875 PetscCall(MatProductSetFill(*C, fill)); 9876 9877 (*C)->product->api_user = PETSC_TRUE; 9878 PetscCall(MatProductSetFromOptions(*C)); 9879 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); 9880 PetscCall(MatProductSymbolic(*C)); 9881 } else { /* scall == MAT_REUSE_MATRIX */ 9882 PetscCall(MatProductReplaceMats(A, R, NULL, *C)); 9883 } 9884 9885 PetscCall(MatProductNumeric(*C)); 9886 if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 9887 PetscFunctionReturn(PETSC_SUCCESS); 9888 } 9889 9890 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C) 9891 { 9892 PetscFunctionBegin; 9893 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9894 9895 if (scall == MAT_INITIAL_MATRIX) { 9896 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype])); 9897 PetscCall(MatProductCreate(A, B, NULL, C)); 9898 PetscCall(MatProductSetType(*C, ptype)); 9899 PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT)); 9900 PetscCall(MatProductSetFill(*C, fill)); 9901 9902 (*C)->product->api_user = PETSC_TRUE; 9903 PetscCall(MatProductSetFromOptions(*C)); 9904 PetscCall(MatProductSymbolic(*C)); 9905 } else { /* scall == MAT_REUSE_MATRIX */ 9906 Mat_Product *product = (*C)->product; 9907 PetscBool isdense; 9908 9909 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, "")); 9910 if (isdense && product && product->type != ptype) { 9911 PetscCall(MatProductClear(*C)); 9912 product = NULL; 9913 } 9914 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype])); 9915 if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */ 9916 PetscCheck(isdense, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first"); 9917 PetscCall(MatProductCreate_Private(A, B, NULL, *C)); 9918 product = (*C)->product; 9919 product->fill = fill; 9920 product->api_user = PETSC_TRUE; 9921 product->clear = PETSC_TRUE; 9922 9923 PetscCall(MatProductSetType(*C, ptype)); 9924 PetscCall(MatProductSetFromOptions(*C)); 9925 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); 9926 PetscCall(MatProductSymbolic(*C)); 9927 } else { /* user may change input matrices A or B when REUSE */ 9928 PetscCall(MatProductReplaceMats(A, B, NULL, *C)); 9929 } 9930 } 9931 PetscCall(MatProductNumeric(*C)); 9932 PetscFunctionReturn(PETSC_SUCCESS); 9933 } 9934 9935 /*@ 9936 MatMatMult - Performs matrix-matrix multiplication C=A*B. 9937 9938 Neighbor-wise Collective on A 9939 9940 Input Parameters: 9941 + A - the left matrix 9942 . B - the right matrix 9943 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9944 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate 9945 if the result is a dense matrix this is irrelevant 9946 9947 Output Parameters: 9948 . C - the product matrix 9949 9950 Notes: 9951 Unless scall is `MAT_REUSE_MATRIX` C will be created. 9952 9953 `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 9954 call to this function with `MAT_INITIAL_MATRIX`. 9955 9956 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed. 9957 9958 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`, 9959 rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse. 9960 9961 Example of Usage: 9962 .vb 9963 MatProductCreate(A,B,NULL,&C); 9964 MatProductSetType(C,MATPRODUCT_AB); 9965 MatProductSymbolic(C); 9966 MatProductNumeric(C); // compute C=A * B 9967 MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1 9968 MatProductNumeric(C); 9969 MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1 9970 MatProductNumeric(C); 9971 .ve 9972 9973 Level: intermediate 9974 9975 .seealso: `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()` 9976 @*/ 9977 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 9978 { 9979 PetscFunctionBegin; 9980 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C)); 9981 PetscFunctionReturn(PETSC_SUCCESS); 9982 } 9983 9984 /*@ 9985 MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T. 9986 9987 Neighbor-wise Collective on A 9988 9989 Input Parameters: 9990 + A - the left matrix 9991 . B - the right matrix 9992 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9993 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 9994 9995 Output Parameters: 9996 . C - the product matrix 9997 9998 Notes: 9999 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10000 10001 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call 10002 10003 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10004 actually needed. 10005 10006 This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class, 10007 and for pairs of `MATMPIDENSE` matrices. 10008 10009 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt` 10010 10011 Options Database Keys: 10012 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the 10013 first redundantly copies the transposed B matrix on each process and requiers O(log P) communication complexity; 10014 the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity. 10015 10016 Level: intermediate 10017 10018 .seealso: `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductCreate()`, `MatProductAlgorithm`, `MatProductType`, `MATPRODUCT_ABt` 10019 @*/ 10020 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10021 { 10022 PetscFunctionBegin; 10023 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C)); 10024 if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10025 PetscFunctionReturn(PETSC_SUCCESS); 10026 } 10027 10028 /*@ 10029 MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B. 10030 10031 Neighbor-wise Collective on A 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 Parameters: 10040 . C - the product matrix 10041 10042 Notes: 10043 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10044 10045 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call. 10046 10047 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB` 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 implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes 10053 which inherit from `MATSEQAIJ`. C will be of the same type as the input matrices. 10054 10055 Level: intermediate 10056 10057 .seealso: `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()` 10058 @*/ 10059 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10060 { 10061 PetscFunctionBegin; 10062 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C)); 10063 PetscFunctionReturn(PETSC_SUCCESS); 10064 } 10065 10066 /*@ 10067 MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C. 10068 10069 Neighbor-wise Collective on A 10070 10071 Input Parameters: 10072 + A - the left matrix 10073 . B - the middle matrix 10074 . C - the right matrix 10075 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10076 - 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 10077 if the result is a dense matrix this is irrelevant 10078 10079 Output Parameters: 10080 . D - the product matrix 10081 10082 Notes: 10083 Unless scall is `MAT_REUSE_MATRIX` D will be created. 10084 10085 `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call 10086 10087 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC` 10088 10089 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10090 actually needed. 10091 10092 If you have many matrices with the same non-zero structure to multiply, you 10093 should use `MAT_REUSE_MATRIX` in all calls but the first 10094 10095 Level: intermediate 10096 10097 .seealso: `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()` 10098 @*/ 10099 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D) 10100 { 10101 PetscFunctionBegin; 10102 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6); 10103 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10104 10105 if (scall == MAT_INITIAL_MATRIX) { 10106 PetscCall(MatProductCreate(A, B, C, D)); 10107 PetscCall(MatProductSetType(*D, MATPRODUCT_ABC)); 10108 PetscCall(MatProductSetAlgorithm(*D, "default")); 10109 PetscCall(MatProductSetFill(*D, fill)); 10110 10111 (*D)->product->api_user = PETSC_TRUE; 10112 PetscCall(MatProductSetFromOptions(*D)); 10113 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, 10114 ((PetscObject)C)->type_name); 10115 PetscCall(MatProductSymbolic(*D)); 10116 } else { /* user may change input matrices when REUSE */ 10117 PetscCall(MatProductReplaceMats(A, B, C, *D)); 10118 } 10119 PetscCall(MatProductNumeric(*D)); 10120 PetscFunctionReturn(PETSC_SUCCESS); 10121 } 10122 10123 /*@ 10124 MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators. 10125 10126 Collective 10127 10128 Input Parameters: 10129 + mat - the matrix 10130 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices) 10131 . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used) 10132 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10133 10134 Output Parameter: 10135 . matredundant - redundant matrix 10136 10137 Notes: 10138 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 10139 original matrix has not changed from that last call to MatCreateRedundantMatrix(). 10140 10141 This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before 10142 calling it. 10143 10144 `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be. 10145 10146 Level: advanced 10147 10148 .seealso: `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubComm` 10149 @*/ 10150 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant) 10151 { 10152 MPI_Comm comm; 10153 PetscMPIInt size; 10154 PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs; 10155 Mat_Redundant *redund = NULL; 10156 PetscSubcomm psubcomm = NULL; 10157 MPI_Comm subcomm_in = subcomm; 10158 Mat *matseq; 10159 IS isrow, iscol; 10160 PetscBool newsubcomm = PETSC_FALSE; 10161 10162 PetscFunctionBegin; 10163 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10164 if (nsubcomm && reuse == MAT_REUSE_MATRIX) { 10165 PetscValidPointer(*matredundant, 5); 10166 PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5); 10167 } 10168 10169 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10170 if (size == 1 || nsubcomm == 1) { 10171 if (reuse == MAT_INITIAL_MATRIX) { 10172 PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant)); 10173 } else { 10174 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"); 10175 PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN)); 10176 } 10177 PetscFunctionReturn(PETSC_SUCCESS); 10178 } 10179 10180 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10181 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10182 MatCheckPreallocated(mat, 1); 10183 10184 PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0)); 10185 if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */ 10186 /* create psubcomm, then get subcomm */ 10187 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10188 PetscCallMPI(MPI_Comm_size(comm, &size)); 10189 PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size); 10190 10191 PetscCall(PetscSubcommCreate(comm, &psubcomm)); 10192 PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm)); 10193 PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS)); 10194 PetscCall(PetscSubcommSetFromOptions(psubcomm)); 10195 PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL)); 10196 newsubcomm = PETSC_TRUE; 10197 PetscCall(PetscSubcommDestroy(&psubcomm)); 10198 } 10199 10200 /* get isrow, iscol and a local sequential matrix matseq[0] */ 10201 if (reuse == MAT_INITIAL_MATRIX) { 10202 mloc_sub = PETSC_DECIDE; 10203 nloc_sub = PETSC_DECIDE; 10204 if (bs < 1) { 10205 PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M)); 10206 PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N)); 10207 } else { 10208 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M)); 10209 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N)); 10210 } 10211 PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm)); 10212 rstart = rend - mloc_sub; 10213 PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow)); 10214 PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol)); 10215 } else { /* reuse == MAT_REUSE_MATRIX */ 10216 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"); 10217 /* retrieve subcomm */ 10218 PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm)); 10219 redund = (*matredundant)->redundant; 10220 isrow = redund->isrow; 10221 iscol = redund->iscol; 10222 matseq = redund->matseq; 10223 } 10224 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq)); 10225 10226 /* get matredundant over subcomm */ 10227 if (reuse == MAT_INITIAL_MATRIX) { 10228 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant)); 10229 10230 /* create a supporting struct and attach it to C for reuse */ 10231 PetscCall(PetscNew(&redund)); 10232 (*matredundant)->redundant = redund; 10233 redund->isrow = isrow; 10234 redund->iscol = iscol; 10235 redund->matseq = matseq; 10236 if (newsubcomm) { 10237 redund->subcomm = subcomm; 10238 } else { 10239 redund->subcomm = MPI_COMM_NULL; 10240 } 10241 } else { 10242 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant)); 10243 } 10244 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 10245 if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) { 10246 PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE)); 10247 PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE)); 10248 } 10249 #endif 10250 PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0)); 10251 PetscFunctionReturn(PETSC_SUCCESS); 10252 } 10253 10254 /*@C 10255 MatGetMultiProcBlock - Create multiple 'parallel submatrices' from 10256 a given `Mat`. Each submatrix can span multiple procs. 10257 10258 Collective 10259 10260 Input Parameters: 10261 + mat - the matrix 10262 . subcomm - the subcommunicator obtained by MPI_Com_split(comm) 10263 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10264 10265 Output Parameter: 10266 . subMat - 'parallel submatrices each spans a given subcomm 10267 10268 Notes: 10269 The submatrix partition across processors is dictated by 'subComm' a 10270 communicator obtained by MPI_comm_split() or via `PetscSubcommCreate()`. The subComm 10271 is not restricted to be grouped with consecutive original ranks. 10272 10273 Due the MPI_Comm_split() usage, the parallel layout of the submatrices 10274 map directly to the layout of the original matrix [wrt the local 10275 row,col partitioning]. So the original 'DiagonalMat' naturally maps 10276 into the 'DiagonalMat' of the subMat, hence it is used directly from 10277 the subMat. However the offDiagMat looses some columns - and this is 10278 reconstructed with `MatSetValues()` 10279 10280 This is used by `PCBJACOBI` when a single block spans multiple MPI ranks 10281 10282 Level: advanced 10283 10284 .seealso: `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI` 10285 @*/ 10286 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) 10287 { 10288 PetscMPIInt commsize, subCommSize; 10289 10290 PetscFunctionBegin; 10291 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize)); 10292 PetscCallMPI(MPI_Comm_size(subComm, &subCommSize)); 10293 PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize); 10294 10295 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"); 10296 PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10297 PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat); 10298 PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10299 PetscFunctionReturn(PETSC_SUCCESS); 10300 } 10301 10302 /*@ 10303 MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering 10304 10305 Not Collective 10306 10307 Input Parameters: 10308 + mat - matrix to extract local submatrix from 10309 . isrow - local row indices for submatrix 10310 - iscol - local column indices for submatrix 10311 10312 Output Parameter: 10313 . submat - the submatrix 10314 10315 Level: intermediate 10316 10317 Notes: 10318 The submat should be returned with `MatRestoreLocalSubMatrix()`. 10319 10320 Depending on the format of mat, the returned submat may not implement `MatMult()`. Its communicator may be 10321 the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of mat's. 10322 10323 The submat always implements `MatSetValuesLocal()`. If isrow and iscol have the same block size, then 10324 `MatSetValuesBlockedLocal()` will also be implemented. 10325 10326 The mat must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`. 10327 Matrices obtained with DMCreateMatrix() generally already have the local to global mapping provided. 10328 10329 .seealso: `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()` 10330 @*/ 10331 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10332 { 10333 PetscFunctionBegin; 10334 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10335 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10336 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10337 PetscCheckSameComm(isrow, 2, iscol, 3); 10338 PetscValidPointer(submat, 4); 10339 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call"); 10340 10341 if (mat->ops->getlocalsubmatrix) { 10342 PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat); 10343 } else { 10344 PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat)); 10345 } 10346 PetscFunctionReturn(PETSC_SUCCESS); 10347 } 10348 10349 /*@ 10350 MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()` 10351 10352 Not Collective 10353 10354 Input Parameters: 10355 + mat - matrix to extract local submatrix from 10356 . isrow - local row indices for submatrix 10357 . iscol - local column indices for submatrix 10358 - submat - the submatrix 10359 10360 Level: intermediate 10361 10362 .seealso: `MatGetLocalSubMatrix()` 10363 @*/ 10364 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10365 { 10366 PetscFunctionBegin; 10367 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10368 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10369 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10370 PetscCheckSameComm(isrow, 2, iscol, 3); 10371 PetscValidPointer(submat, 4); 10372 if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4); 10373 10374 if (mat->ops->restorelocalsubmatrix) { 10375 PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat); 10376 } else { 10377 PetscCall(MatDestroy(submat)); 10378 } 10379 *submat = NULL; 10380 PetscFunctionReturn(PETSC_SUCCESS); 10381 } 10382 10383 /* --------------------------------------------------------*/ 10384 /*@ 10385 MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix 10386 10387 Collective 10388 10389 Input Parameter: 10390 . mat - the matrix 10391 10392 Output Parameter: 10393 . is - if any rows have zero diagonals this contains the list of them 10394 10395 Level: developer 10396 10397 .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10398 @*/ 10399 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is) 10400 { 10401 PetscFunctionBegin; 10402 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10403 PetscValidType(mat, 1); 10404 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10405 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10406 10407 if (!mat->ops->findzerodiagonals) { 10408 Vec diag; 10409 const PetscScalar *a; 10410 PetscInt *rows; 10411 PetscInt rStart, rEnd, r, nrow = 0; 10412 10413 PetscCall(MatCreateVecs(mat, &diag, NULL)); 10414 PetscCall(MatGetDiagonal(mat, diag)); 10415 PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd)); 10416 PetscCall(VecGetArrayRead(diag, &a)); 10417 for (r = 0; r < rEnd - rStart; ++r) 10418 if (a[r] == 0.0) ++nrow; 10419 PetscCall(PetscMalloc1(nrow, &rows)); 10420 nrow = 0; 10421 for (r = 0; r < rEnd - rStart; ++r) 10422 if (a[r] == 0.0) rows[nrow++] = r + rStart; 10423 PetscCall(VecRestoreArrayRead(diag, &a)); 10424 PetscCall(VecDestroy(&diag)); 10425 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is)); 10426 } else { 10427 PetscUseTypeMethod(mat, findzerodiagonals, is); 10428 } 10429 PetscFunctionReturn(PETSC_SUCCESS); 10430 } 10431 10432 /*@ 10433 MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size) 10434 10435 Collective 10436 10437 Input Parameter: 10438 . mat - the matrix 10439 10440 Output Parameter: 10441 . is - contains the list of rows with off block diagonal entries 10442 10443 Level: developer 10444 10445 .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10446 @*/ 10447 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is) 10448 { 10449 PetscFunctionBegin; 10450 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10451 PetscValidType(mat, 1); 10452 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10453 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10454 10455 PetscUseTypeMethod(mat, findoffblockdiagonalentries, is); 10456 PetscFunctionReturn(PETSC_SUCCESS); 10457 } 10458 10459 /*@C 10460 MatInvertBlockDiagonal - Inverts the block diagonal entries. 10461 10462 Collective; No Fortran Support 10463 10464 Input Parameters: 10465 . mat - the matrix 10466 10467 Output Parameters: 10468 . values - the block inverses in column major order (FORTRAN-like) 10469 10470 Level: advanced 10471 10472 Notes: 10473 The size of the blocks is determined by the block size of the matrix. 10474 10475 The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case 10476 10477 The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size 10478 10479 .seealso: `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()` 10480 @*/ 10481 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values) 10482 { 10483 PetscFunctionBegin; 10484 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10485 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10486 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10487 PetscUseTypeMethod(mat, invertblockdiagonal, values); 10488 PetscFunctionReturn(PETSC_SUCCESS); 10489 } 10490 10491 /*@C 10492 MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries. 10493 10494 Collective; No Fortran Support 10495 10496 Input Parameters: 10497 + mat - the matrix 10498 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()` 10499 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()` 10500 10501 Output Parameters: 10502 . values - the block inverses in column major order (FORTRAN-like) 10503 10504 Level: advanced 10505 10506 Notes: 10507 Use `MatInvertBlockDiagonal()` if all blocks have the same size 10508 10509 The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case 10510 10511 .seealso: `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()` 10512 @*/ 10513 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values) 10514 { 10515 PetscFunctionBegin; 10516 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10517 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10518 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10519 PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values); 10520 PetscFunctionReturn(PETSC_SUCCESS); 10521 } 10522 10523 /*@ 10524 MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A 10525 10526 Collective on Mat 10527 10528 Input Parameters: 10529 + A - the matrix 10530 - C - matrix with inverted block diagonal of A. This matrix should be created and may have its type set. 10531 10532 Note: 10533 The blocksize of the matrix is used to determine the blocks on the diagonal of C 10534 10535 Level: advanced 10536 10537 .seealso: `MatInvertBlockDiagonal()` 10538 @*/ 10539 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C) 10540 { 10541 const PetscScalar *vals; 10542 PetscInt *dnnz; 10543 PetscInt m, rstart, rend, bs, i, j; 10544 10545 PetscFunctionBegin; 10546 PetscCall(MatInvertBlockDiagonal(A, &vals)); 10547 PetscCall(MatGetBlockSize(A, &bs)); 10548 PetscCall(MatGetLocalSize(A, &m, NULL)); 10549 PetscCall(MatSetLayouts(C, A->rmap, A->cmap)); 10550 PetscCall(PetscMalloc1(m / bs, &dnnz)); 10551 for (j = 0; j < m / bs; j++) dnnz[j] = 1; 10552 PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL)); 10553 PetscCall(PetscFree(dnnz)); 10554 PetscCall(MatGetOwnershipRange(C, &rstart, &rend)); 10555 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE)); 10556 for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES)); 10557 PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 10558 PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 10559 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE)); 10560 PetscFunctionReturn(PETSC_SUCCESS); 10561 } 10562 10563 /*@C 10564 MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created 10565 via `MatTransposeColoringCreate()`. 10566 10567 Collective on c 10568 10569 Input Parameter: 10570 . c - coloring context 10571 10572 Level: intermediate 10573 10574 .seealso: `MatTransposeColoringCreate()` 10575 @*/ 10576 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c) 10577 { 10578 MatTransposeColoring matcolor = *c; 10579 10580 PetscFunctionBegin; 10581 if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS); 10582 if (--((PetscObject)matcolor)->refct > 0) { 10583 matcolor = NULL; 10584 PetscFunctionReturn(PETSC_SUCCESS); 10585 } 10586 10587 PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow)); 10588 PetscCall(PetscFree(matcolor->rows)); 10589 PetscCall(PetscFree(matcolor->den2sp)); 10590 PetscCall(PetscFree(matcolor->colorforcol)); 10591 PetscCall(PetscFree(matcolor->columns)); 10592 if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart)); 10593 PetscCall(PetscHeaderDestroy(c)); 10594 PetscFunctionReturn(PETSC_SUCCESS); 10595 } 10596 10597 /*@C 10598 MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which 10599 a `MatTransposeColoring` context has been created, computes a dense B^T by applying 10600 `MatTransposeColoring` to sparse B. 10601 10602 Collective on coloring 10603 10604 Input Parameters: 10605 + B - sparse matrix B 10606 . Btdense - symbolic dense matrix B^T 10607 - coloring - coloring context created with `MatTransposeColoringCreate()` 10608 10609 Output Parameter: 10610 . Btdense - dense matrix B^T 10611 10612 Level: developer 10613 10614 Note: 10615 These are used internally for some implementations of `MatRARt()` 10616 10617 .seealso: `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()` 10618 10619 @*/ 10620 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense) 10621 { 10622 PetscFunctionBegin; 10623 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 10624 PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3); 10625 PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10626 10627 PetscCall((B->ops->transcoloringapplysptoden)(coloring, B, Btdense)); 10628 PetscFunctionReturn(PETSC_SUCCESS); 10629 } 10630 10631 /*@C 10632 MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which 10633 a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense 10634 in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix 10635 Csp from Cden. 10636 10637 Collective 10638 10639 Input Parameters: 10640 + coloring - coloring context created with `MatTransposeColoringCreate()` 10641 - Cden - matrix product of a sparse matrix and a dense matrix Btdense 10642 10643 Output Parameter: 10644 . Csp - sparse matrix 10645 10646 Level: developer 10647 10648 Note: 10649 These are used internally for some implementations of `MatRARt()` 10650 10651 .seealso: `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()` 10652 10653 @*/ 10654 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp) 10655 { 10656 PetscFunctionBegin; 10657 PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10658 PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2); 10659 PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3); 10660 10661 PetscCall((Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp)); 10662 PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY)); 10663 PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY)); 10664 PetscFunctionReturn(PETSC_SUCCESS); 10665 } 10666 10667 /*@C 10668 MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T. 10669 10670 Collective 10671 10672 Input Parameters: 10673 + mat - the matrix product C 10674 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()` 10675 10676 Output Parameter: 10677 . color - the new coloring context 10678 10679 Level: intermediate 10680 10681 .seealso: `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`, 10682 `MatTransColoringApplyDenToSp()` 10683 @*/ 10684 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color) 10685 { 10686 MatTransposeColoring c; 10687 MPI_Comm comm; 10688 10689 PetscFunctionBegin; 10690 PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10691 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10692 PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL)); 10693 10694 c->ctype = iscoloring->ctype; 10695 PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c); 10696 10697 *color = c; 10698 PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10699 PetscFunctionReturn(PETSC_SUCCESS); 10700 } 10701 10702 /*@ 10703 MatGetNonzeroState - Returns a 64 bit integer representing the current state of nonzeros in the matrix. If the 10704 matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the 10705 same, otherwise it will be larger 10706 10707 Not Collective 10708 10709 Input Parameter: 10710 . A - the matrix 10711 10712 Output Parameter: 10713 . state - the current state 10714 10715 Notes: 10716 You can only compare states from two different calls to the SAME matrix, you cannot compare calls between 10717 different matrices 10718 10719 Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix 10720 10721 Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers. 10722 10723 Level: intermediate 10724 10725 .seealso: `PetscObjectStateGet()`, `PetscObjectGetId()` 10726 @*/ 10727 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state) 10728 { 10729 PetscFunctionBegin; 10730 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10731 *state = mat->nonzerostate; 10732 PetscFunctionReturn(PETSC_SUCCESS); 10733 } 10734 10735 /*@ 10736 MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential 10737 matrices from each processor 10738 10739 Collective 10740 10741 Input Parameters: 10742 + comm - the communicators the parallel matrix will live on 10743 . seqmat - the input sequential matrices 10744 . n - number of local columns (or `PETSC_DECIDE`) 10745 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10746 10747 Output Parameter: 10748 . mpimat - the parallel matrix generated 10749 10750 Level: developer 10751 10752 Note: 10753 The number of columns of the matrix in EACH processor MUST be the same. 10754 10755 .seealso: `Mat` 10756 @*/ 10757 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat) 10758 { 10759 PetscMPIInt size; 10760 10761 PetscFunctionBegin; 10762 PetscCallMPI(MPI_Comm_size(comm, &size)); 10763 if (size == 1) { 10764 if (reuse == MAT_INITIAL_MATRIX) { 10765 PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat)); 10766 } else { 10767 PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN)); 10768 } 10769 PetscFunctionReturn(PETSC_SUCCESS); 10770 } 10771 10772 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"); 10773 10774 PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0)); 10775 PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat)); 10776 PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0)); 10777 PetscFunctionReturn(PETSC_SUCCESS); 10778 } 10779 10780 /*@ 10781 MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent ranks' ownership ranges. 10782 10783 Collective on A 10784 10785 Input Parameters: 10786 + A - the matrix to create subdomains from 10787 - N - requested number of subdomains 10788 10789 Output Parameters: 10790 + n - number of subdomains resulting on this rank 10791 - iss - `IS` list with indices of subdomains on this rank 10792 10793 Level: advanced 10794 10795 Note: 10796 The number of subdomains must be smaller than the communicator size 10797 10798 .seealso: `Mat`, `IS` 10799 @*/ 10800 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[]) 10801 { 10802 MPI_Comm comm, subcomm; 10803 PetscMPIInt size, rank, color; 10804 PetscInt rstart, rend, k; 10805 10806 PetscFunctionBegin; 10807 PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 10808 PetscCallMPI(MPI_Comm_size(comm, &size)); 10809 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 10810 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); 10811 *n = 1; 10812 k = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */ 10813 color = rank / k; 10814 PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm)); 10815 PetscCall(PetscMalloc1(1, iss)); 10816 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 10817 PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0])); 10818 PetscCallMPI(MPI_Comm_free(&subcomm)); 10819 PetscFunctionReturn(PETSC_SUCCESS); 10820 } 10821 10822 /*@ 10823 MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection. 10824 10825 If the interpolation and restriction operators are the same, uses `MatPtAP()`. 10826 If they are not the same, uses `MatMatMatMult()`. 10827 10828 Once the coarse grid problem is constructed, correct for interpolation operators 10829 that are not of full rank, which can legitimately happen in the case of non-nested 10830 geometric multigrid. 10831 10832 Input Parameters: 10833 + restrct - restriction operator 10834 . dA - fine grid matrix 10835 . interpolate - interpolation operator 10836 . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10837 - fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate 10838 10839 Output Parameters: 10840 . A - the Galerkin coarse matrix 10841 10842 Options Database Key: 10843 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used 10844 10845 Level: developer 10846 10847 .seealso: `MatPtAP()`, `MatMatMatMult()` 10848 @*/ 10849 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A) 10850 { 10851 IS zerorows; 10852 Vec diag; 10853 10854 PetscFunctionBegin; 10855 PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10856 /* Construct the coarse grid matrix */ 10857 if (interpolate == restrct) { 10858 PetscCall(MatPtAP(dA, interpolate, reuse, fill, A)); 10859 } else { 10860 PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A)); 10861 } 10862 10863 /* If the interpolation matrix is not of full rank, A will have zero rows. 10864 This can legitimately happen in the case of non-nested geometric multigrid. 10865 In that event, we set the rows of the matrix to the rows of the identity, 10866 ignoring the equations (as the RHS will also be zero). */ 10867 10868 PetscCall(MatFindZeroRows(*A, &zerorows)); 10869 10870 if (zerorows != NULL) { /* if there are any zero rows */ 10871 PetscCall(MatCreateVecs(*A, &diag, NULL)); 10872 PetscCall(MatGetDiagonal(*A, diag)); 10873 PetscCall(VecISSet(diag, zerorows, 1.0)); 10874 PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES)); 10875 PetscCall(VecDestroy(&diag)); 10876 PetscCall(ISDestroy(&zerorows)); 10877 } 10878 PetscFunctionReturn(PETSC_SUCCESS); 10879 } 10880 10881 /*@C 10882 MatSetOperation - Allows user to set a matrix operation for any matrix type 10883 10884 Logically Collective 10885 10886 Input Parameters: 10887 + mat - the matrix 10888 . op - the name of the operation 10889 - f - the function that provides the operation 10890 10891 Level: developer 10892 10893 Usage: 10894 $ extern PetscErrorCode usermult(Mat,Vec,Vec); 10895 $ PetscCall(MatCreateXXX(comm,...&A); 10896 $ PetscCall(MatSetOperation(A,MATOP_MULT,(void(*)(void))usermult); 10897 10898 Notes: 10899 See the file include/petscmat.h for a complete list of matrix 10900 operations, which all have the form MATOP_<OPERATION>, where 10901 <OPERATION> is the name (in all capital letters) of the 10902 user interface routine (e.g., MatMult() -> MATOP_MULT). 10903 10904 All user-provided functions (except for `MATOP_DESTROY`) should have the same calling 10905 sequence as the usual matrix interface routines, since they 10906 are intended to be accessed via the usual matrix interface 10907 routines, e.g., 10908 $ MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec) 10909 10910 In particular each function MUST return an error code of 0 on success and 10911 nonzero on failure. 10912 10913 This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type. 10914 10915 .seealso: `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()` 10916 @*/ 10917 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void)) 10918 { 10919 PetscFunctionBegin; 10920 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10921 if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view; 10922 (((void (**)(void))mat->ops)[op]) = f; 10923 PetscFunctionReturn(PETSC_SUCCESS); 10924 } 10925 10926 /*@C 10927 MatGetOperation - Gets a matrix operation for any matrix type. 10928 10929 Not Collective 10930 10931 Input Parameters: 10932 + mat - the matrix 10933 - op - the name of the operation 10934 10935 Output Parameter: 10936 . f - the function that provides the operation 10937 10938 Level: developer 10939 10940 Usage: 10941 $ PetscErrorCode (*usermult)(Mat,Vec,Vec); 10942 $ MatGetOperation(A,MATOP_MULT,(void(**)(void))&usermult); 10943 10944 Notes: 10945 See the file include/petscmat.h for a complete list of matrix 10946 operations, which all have the form MATOP_<OPERATION>, where 10947 <OPERATION> is the name (in all capital letters) of the 10948 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 10949 10950 This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type. 10951 10952 .seealso: `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()` 10953 @*/ 10954 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void)) 10955 { 10956 PetscFunctionBegin; 10957 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10958 *f = (((void (**)(void))mat->ops)[op]); 10959 PetscFunctionReturn(PETSC_SUCCESS); 10960 } 10961 10962 /*@ 10963 MatHasOperation - Determines whether the given matrix supports the particular operation. 10964 10965 Not Collective 10966 10967 Input Parameters: 10968 + mat - the matrix 10969 - op - the operation, for example, `MATOP_GET_DIAGONAL` 10970 10971 Output Parameter: 10972 . has - either `PETSC_TRUE` or `PETSC_FALSE` 10973 10974 Level: advanced 10975 10976 Note: 10977 See the file include/petscmat.h for a complete list of matrix 10978 operations, which all have the form MATOP_<OPERATION>, where 10979 <OPERATION> is the name (in all capital letters) of the 10980 user-level routine. E.g., `MatNorm()` -> `MATOP_NORM`. 10981 10982 .seealso: `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()` 10983 @*/ 10984 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has) 10985 { 10986 PetscFunctionBegin; 10987 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10988 PetscValidBoolPointer(has, 3); 10989 if (mat->ops->hasoperation) { 10990 PetscUseTypeMethod(mat, hasoperation, op, has); 10991 } else { 10992 if (((void **)mat->ops)[op]) *has = PETSC_TRUE; 10993 else { 10994 *has = PETSC_FALSE; 10995 if (op == MATOP_CREATE_SUBMATRIX) { 10996 PetscMPIInt size; 10997 10998 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10999 if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has)); 11000 } 11001 } 11002 } 11003 PetscFunctionReturn(PETSC_SUCCESS); 11004 } 11005 11006 /*@ 11007 MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent 11008 11009 Collective 11010 11011 Input Parameters: 11012 . mat - the matrix 11013 11014 Output Parameter: 11015 . cong - either `PETSC_TRUE` or `PETSC_FALSE` 11016 11017 Level: beginner 11018 11019 .seealso: `MatCreate()`, `MatSetSizes()`, `PetscLayout` 11020 @*/ 11021 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong) 11022 { 11023 PetscFunctionBegin; 11024 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11025 PetscValidType(mat, 1); 11026 PetscValidBoolPointer(cong, 2); 11027 if (!mat->rmap || !mat->cmap) { 11028 *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE; 11029 PetscFunctionReturn(PETSC_SUCCESS); 11030 } 11031 if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */ 11032 PetscCall(PetscLayoutSetUp(mat->rmap)); 11033 PetscCall(PetscLayoutSetUp(mat->cmap)); 11034 PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong)); 11035 if (*cong) mat->congruentlayouts = 1; 11036 else mat->congruentlayouts = 0; 11037 } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE; 11038 PetscFunctionReturn(PETSC_SUCCESS); 11039 } 11040 11041 PetscErrorCode MatSetInf(Mat A) 11042 { 11043 PetscFunctionBegin; 11044 PetscUseTypeMethod(A, setinf); 11045 PetscFunctionReturn(PETSC_SUCCESS); 11046 } 11047 11048 /*@C 11049 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 11050 and possibly removes small values from the graph structure. 11051 11052 Collective 11053 11054 Input Parameters: 11055 + A - the matrix 11056 . sym - `PETSC_TRUE` indicates that the graph should be symmetrized 11057 . scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry 11058 - filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value 11059 11060 Output Parameter: 11061 . graph - the resulting graph 11062 11063 Level: advanced 11064 11065 .seealso: `MatCreate()`, `PCGAMG` 11066 @*/ 11067 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph) 11068 { 11069 PetscFunctionBegin; 11070 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11071 PetscValidType(A, 1); 11072 PetscValidLogicalCollectiveBool(A, scale, 3); 11073 PetscValidPointer(graph, 5); 11074 PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph); 11075 PetscFunctionReturn(PETSC_SUCCESS); 11076 } 11077 11078 /*@ 11079 MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place, 11080 meaning the same memory is used for the matrix, and no new memory is allocated. 11081 11082 Collective on mat 11083 11084 Input Parameter: 11085 . A - the matrix 11086 11087 Output Parameter: 11088 . A - the matrix 11089 11090 Level: intermediate 11091 11092 .seealso: `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatChop()` 11093 @*/ 11094 PetscErrorCode MatEliminateZeros(Mat A) 11095 { 11096 PetscFunctionBegin; 11097 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11098 PetscUseTypeMethod(A, eliminatezeros); 11099 PetscFunctionReturn(PETSC_SUCCESS); 11100 } 11101