1 /* 2 This is where the abstract matrix operations are defined 3 Portions of this code are under: 4 Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved. 5 */ 6 7 #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/ 8 #include <petsc/private/isimpl.h> 9 #include <petsc/private/vecimpl.h> 10 11 /* Logging support */ 12 PetscClassId MAT_CLASSID; 13 PetscClassId MAT_COLORING_CLASSID; 14 PetscClassId MAT_FDCOLORING_CLASSID; 15 PetscClassId MAT_TRANSPOSECOLORING_CLASSID; 16 17 PetscLogEvent MAT_Mult, MAT_Mults, MAT_MultAdd, MAT_MultTranspose; 18 PetscLogEvent MAT_MultTransposeAdd, MAT_Solve, MAT_Solves, MAT_SolveAdd, MAT_SolveTranspose, MAT_MatSolve, MAT_MatTrSolve; 19 PetscLogEvent MAT_SolveTransposeAdd, MAT_SOR, MAT_ForwardSolve, MAT_BackwardSolve, MAT_LUFactor, MAT_LUFactorSymbolic; 20 PetscLogEvent MAT_LUFactorNumeric, MAT_CholeskyFactor, MAT_CholeskyFactorSymbolic, MAT_CholeskyFactorNumeric, MAT_ILUFactor; 21 PetscLogEvent MAT_ILUFactorSymbolic, MAT_ICCFactorSymbolic, MAT_Copy, MAT_Convert, MAT_Scale, MAT_AssemblyBegin; 22 PetscLogEvent MAT_QRFactorNumeric, MAT_QRFactorSymbolic, MAT_QRFactor; 23 PetscLogEvent MAT_AssemblyEnd, MAT_SetValues, MAT_GetValues, MAT_GetRow, MAT_GetRowIJ, MAT_CreateSubMats, MAT_GetOrdering, MAT_RedundantMat, MAT_GetSeqNonzeroStructure; 24 PetscLogEvent MAT_IncreaseOverlap, MAT_Partitioning, MAT_PartitioningND, MAT_Coarsen, MAT_ZeroEntries, MAT_Load, MAT_View, MAT_AXPY, MAT_FDColoringCreate; 25 PetscLogEvent MAT_FDColoringSetUp, MAT_FDColoringApply, MAT_Transpose, MAT_FDColoringFunction, MAT_CreateSubMat; 26 PetscLogEvent MAT_TransposeColoringCreate; 27 PetscLogEvent MAT_MatMult, MAT_MatMultSymbolic, MAT_MatMultNumeric; 28 PetscLogEvent MAT_PtAP, MAT_PtAPSymbolic, MAT_PtAPNumeric, MAT_RARt, MAT_RARtSymbolic, MAT_RARtNumeric; 29 PetscLogEvent MAT_MatTransposeMult, MAT_MatTransposeMultSymbolic, MAT_MatTransposeMultNumeric; 30 PetscLogEvent MAT_TransposeMatMult, MAT_TransposeMatMultSymbolic, MAT_TransposeMatMultNumeric; 31 PetscLogEvent MAT_MatMatMult, MAT_MatMatMultSymbolic, MAT_MatMatMultNumeric; 32 PetscLogEvent MAT_MultHermitianTranspose, MAT_MultHermitianTransposeAdd; 33 PetscLogEvent MAT_Getsymtranspose, MAT_Getsymtransreduced, MAT_GetBrowsOfAcols; 34 PetscLogEvent MAT_GetBrowsOfAocols, MAT_Getlocalmat, MAT_Getlocalmatcondensed, MAT_Seqstompi, MAT_Seqstompinum, MAT_Seqstompisym; 35 PetscLogEvent MAT_Applypapt, MAT_Applypapt_numeric, MAT_Applypapt_symbolic, MAT_GetSequentialNonzeroStructure; 36 PetscLogEvent MAT_GetMultiProcBlock; 37 PetscLogEvent MAT_CUSPARSECopyToGPU, MAT_CUSPARSECopyFromGPU, MAT_CUSPARSEGenerateTranspose, MAT_CUSPARSESolveAnalysis; 38 PetscLogEvent MAT_HIPSPARSECopyToGPU, MAT_HIPSPARSECopyFromGPU, MAT_HIPSPARSEGenerateTranspose, MAT_HIPSPARSESolveAnalysis; 39 PetscLogEvent MAT_PreallCOO, MAT_SetVCOO; 40 PetscLogEvent MAT_SetValuesBatch; 41 PetscLogEvent MAT_ViennaCLCopyToGPU; 42 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU; 43 PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom; 44 PetscLogEvent MAT_FactorFactS, MAT_FactorInvS; 45 PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights; 46 PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR; 47 48 const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL}; 49 50 /*@ 51 MatSetRandom - Sets all components of a matrix to random numbers. 52 53 Logically Collective 54 55 Input Parameters: 56 + x - the matrix 57 - rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or `NULL` and 58 it will create one internally. 59 60 Output Parameter: 61 . x - the matrix 62 63 Example of Usage: 64 .vb 65 PetscRandomCreate(PETSC_COMM_WORLD,&rctx); 66 MatSetRandom(x,rctx); 67 PetscRandomDestroy(rctx); 68 .ve 69 70 Level: intermediate 71 72 Note: 73 For sparse matrices that have been preallocated but not been assembled it randomly selects appropriate locations, 74 for sparse matrices that already have locations it fills the locations with random numbers. It generates an error if used on sparse matrices that have 75 not been preallocated. 76 77 .seealso: `Mat`, `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomCreate()`, `PetscRandomDestroy()` 78 @*/ 79 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx) 80 { 81 PetscRandom randObj = NULL; 82 83 PetscFunctionBegin; 84 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 85 if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2); 86 PetscValidType(x, 1); 87 MatCheckPreallocated(x, 1); 88 89 if (!rctx) { 90 MPI_Comm comm; 91 PetscCall(PetscObjectGetComm((PetscObject)x, &comm)); 92 PetscCall(PetscRandomCreate(comm, &randObj)); 93 PetscCall(PetscRandomSetType(randObj, x->defaultrandtype)); 94 PetscCall(PetscRandomSetFromOptions(randObj)); 95 rctx = randObj; 96 } 97 PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0)); 98 PetscUseTypeMethod(x, setrandom, rctx); 99 PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0)); 100 101 PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY)); 102 PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY)); 103 PetscCall(PetscRandomDestroy(&randObj)); 104 PetscFunctionReturn(PETSC_SUCCESS); 105 } 106 107 /*@ 108 MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in 109 110 Logically Collective 111 112 Input Parameter: 113 . mat - the factored matrix 114 115 Output Parameters: 116 + pivot - the pivot value computed 117 - row - the row that the zero pivot occurred. Note that this row must be interpreted carefully due to row reorderings and which processes 118 the share the matrix 119 120 Level: advanced 121 122 Notes: 123 This routine does not work for factorizations done with external packages. 124 125 This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT` 126 127 This can be called on non-factored matrices that come from, for example, matrices used in SOR. 128 129 .seealso: `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, 130 `MAT_FACTOR_NUMERIC_ZEROPIVOT` 131 @*/ 132 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row) 133 { 134 PetscFunctionBegin; 135 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 136 PetscValidRealPointer(pivot, 2); 137 PetscValidIntPointer(row, 3); 138 *pivot = mat->factorerror_zeropivot_value; 139 *row = mat->factorerror_zeropivot_row; 140 PetscFunctionReturn(PETSC_SUCCESS); 141 } 142 143 /*@ 144 MatFactorGetError - gets the error code from a factorization 145 146 Logically Collective 147 148 Input Parameters: 149 . mat - the factored matrix 150 151 Output Parameter: 152 . err - the error code 153 154 Level: advanced 155 156 Note: 157 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 158 159 .seealso: `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, 160 `MatFactorError` 161 @*/ 162 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err) 163 { 164 PetscFunctionBegin; 165 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 166 PetscValidPointer(err, 2); 167 *err = mat->factorerrortype; 168 PetscFunctionReturn(PETSC_SUCCESS); 169 } 170 171 /*@ 172 MatFactorClearError - clears the error code in a factorization 173 174 Logically Collective 175 176 Input Parameter: 177 . mat - the factored matrix 178 179 Level: developer 180 181 Note: 182 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 183 184 .seealso: `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`, 185 `MatGetErrorCode()`, `MatFactorError` 186 @*/ 187 PetscErrorCode MatFactorClearError(Mat mat) 188 { 189 PetscFunctionBegin; 190 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 191 mat->factorerrortype = MAT_FACTOR_NOERROR; 192 mat->factorerror_zeropivot_value = 0.0; 193 mat->factorerror_zeropivot_row = 0; 194 PetscFunctionReturn(PETSC_SUCCESS); 195 } 196 197 PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero) 198 { 199 Vec r, l; 200 const PetscScalar *al; 201 PetscInt i, nz, gnz, N, n; 202 203 PetscFunctionBegin; 204 PetscCall(MatCreateVecs(mat, &r, &l)); 205 if (!cols) { /* nonzero rows */ 206 PetscCall(MatGetSize(mat, &N, NULL)); 207 PetscCall(MatGetLocalSize(mat, &n, NULL)); 208 PetscCall(VecSet(l, 0.0)); 209 PetscCall(VecSetRandom(r, NULL)); 210 PetscCall(MatMult(mat, r, l)); 211 PetscCall(VecGetArrayRead(l, &al)); 212 } else { /* nonzero columns */ 213 PetscCall(MatGetSize(mat, NULL, &N)); 214 PetscCall(MatGetLocalSize(mat, NULL, &n)); 215 PetscCall(VecSet(r, 0.0)); 216 PetscCall(VecSetRandom(l, NULL)); 217 PetscCall(MatMultTranspose(mat, l, r)); 218 PetscCall(VecGetArrayRead(r, &al)); 219 } 220 if (tol <= 0.0) { 221 for (i = 0, nz = 0; i < n; i++) 222 if (al[i] != 0.0) nz++; 223 } else { 224 for (i = 0, nz = 0; i < n; i++) 225 if (PetscAbsScalar(al[i]) > tol) nz++; 226 } 227 PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 228 if (gnz != N) { 229 PetscInt *nzr; 230 PetscCall(PetscMalloc1(nz, &nzr)); 231 if (nz) { 232 if (tol < 0) { 233 for (i = 0, nz = 0; i < n; i++) 234 if (al[i] != 0.0) nzr[nz++] = i; 235 } else { 236 for (i = 0, nz = 0; i < n; i++) 237 if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i; 238 } 239 } 240 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero)); 241 } else *nonzero = NULL; 242 if (!cols) { /* nonzero rows */ 243 PetscCall(VecRestoreArrayRead(l, &al)); 244 } else { 245 PetscCall(VecRestoreArrayRead(r, &al)); 246 } 247 PetscCall(VecDestroy(&l)); 248 PetscCall(VecDestroy(&r)); 249 PetscFunctionReturn(PETSC_SUCCESS); 250 } 251 252 /*@ 253 MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix 254 255 Input Parameter: 256 . A - the matrix 257 258 Output Parameter: 259 . keptrows - the rows that are not completely zero 260 261 Level: intermediate 262 263 Note: 264 `keptrows` is set to `NULL` if all rows are nonzero. 265 266 .seealso: `Mat`, `MatFindZeroRows()` 267 @*/ 268 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows) 269 { 270 PetscFunctionBegin; 271 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 272 PetscValidType(mat, 1); 273 PetscValidPointer(keptrows, 2); 274 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 275 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 276 if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows); 277 else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows)); 278 PetscFunctionReturn(PETSC_SUCCESS); 279 } 280 281 /*@ 282 MatFindZeroRows - Locate all rows that are completely zero in the matrix 283 284 Input Parameter: 285 . A - the matrix 286 287 Output Parameter: 288 . zerorows - the rows that are completely zero 289 290 Level: intermediate 291 292 Note: 293 `zerorows` is set to `NULL` if no rows are zero. 294 295 .seealso: `Mat`, `MatFindNonzeroRows()` 296 @*/ 297 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows) 298 { 299 IS keptrows; 300 PetscInt m, n; 301 302 PetscFunctionBegin; 303 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 304 PetscValidType(mat, 1); 305 PetscValidPointer(zerorows, 2); 306 PetscCall(MatFindNonzeroRows(mat, &keptrows)); 307 /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows. 308 In keeping with this convention, we set zerorows to NULL if there are no zero 309 rows. */ 310 if (keptrows == NULL) { 311 *zerorows = NULL; 312 } else { 313 PetscCall(MatGetOwnershipRange(mat, &m, &n)); 314 PetscCall(ISComplement(keptrows, m, n, zerorows)); 315 PetscCall(ISDestroy(&keptrows)); 316 } 317 PetscFunctionReturn(PETSC_SUCCESS); 318 } 319 320 /*@ 321 MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling 322 323 Not Collective 324 325 Input Parameters: 326 . A - the matrix 327 328 Output Parameters: 329 . a - the diagonal part (which is a SEQUENTIAL matrix) 330 331 Level: advanced 332 333 Notes: 334 See the manual page for `MatCreateAIJ()` for more information on the "diagonal part" of the matrix. 335 336 Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation. 337 338 .seealso: `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ` 339 @*/ 340 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a) 341 { 342 PetscFunctionBegin; 343 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 344 PetscValidType(A, 1); 345 PetscValidPointer(a, 2); 346 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 347 if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a); 348 else { 349 PetscMPIInt size; 350 351 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 352 PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name); 353 *a = A; 354 } 355 PetscFunctionReturn(PETSC_SUCCESS); 356 } 357 358 /*@ 359 MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries. 360 361 Collective 362 363 Input Parameters: 364 . mat - the matrix 365 366 Output Parameter: 367 . trace - the sum of the diagonal entries 368 369 Level: advanced 370 371 .seealso: `Mat` 372 @*/ 373 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace) 374 { 375 Vec diag; 376 377 PetscFunctionBegin; 378 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 379 PetscValidScalarPointer(trace, 2); 380 PetscCall(MatCreateVecs(mat, &diag, NULL)); 381 PetscCall(MatGetDiagonal(mat, diag)); 382 PetscCall(VecSum(diag, trace)); 383 PetscCall(VecDestroy(&diag)); 384 PetscFunctionReturn(PETSC_SUCCESS); 385 } 386 387 /*@ 388 MatRealPart - Zeros out the imaginary part of the matrix 389 390 Logically Collective 391 392 Input Parameters: 393 . mat - the matrix 394 395 Level: advanced 396 397 .seealso: `Mat`, `MatImaginaryPart()` 398 @*/ 399 PetscErrorCode MatRealPart(Mat mat) 400 { 401 PetscFunctionBegin; 402 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 403 PetscValidType(mat, 1); 404 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 405 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 406 MatCheckPreallocated(mat, 1); 407 PetscUseTypeMethod(mat, realpart); 408 PetscFunctionReturn(PETSC_SUCCESS); 409 } 410 411 /*@C 412 MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix 413 414 Collective 415 416 Input Parameter: 417 . mat - the matrix 418 419 Output Parameters: 420 + nghosts - number of ghosts (note for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each block) 421 - ghosts - the global indices of the ghost points 422 423 Level: advanced 424 425 Note: 426 `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()` 427 428 .seealso: `Mat`, `VecCreateGhost()` 429 @*/ 430 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[]) 431 { 432 PetscFunctionBegin; 433 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 434 PetscValidType(mat, 1); 435 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 436 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 437 if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts); 438 else { 439 if (nghosts) *nghosts = 0; 440 if (ghosts) *ghosts = NULL; 441 } 442 PetscFunctionReturn(PETSC_SUCCESS); 443 } 444 445 /*@ 446 MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part 447 448 Logically Collective 449 450 Input Parameters: 451 . mat - the matrix 452 453 Level: advanced 454 455 .seealso: `Mat`, `MatRealPart()` 456 @*/ 457 PetscErrorCode MatImaginaryPart(Mat mat) 458 { 459 PetscFunctionBegin; 460 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 461 PetscValidType(mat, 1); 462 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 463 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 464 MatCheckPreallocated(mat, 1); 465 PetscUseTypeMethod(mat, imaginarypart); 466 PetscFunctionReturn(PETSC_SUCCESS); 467 } 468 469 /*@ 470 MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices) 471 472 Not Collective 473 474 Input Parameter: 475 . mat - the matrix 476 477 Output Parameters: 478 + missing - is any diagonal missing 479 - dd - first diagonal entry that is missing (optional) on this process 480 481 Level: advanced 482 483 .seealso: `Mat` 484 @*/ 485 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd) 486 { 487 PetscFunctionBegin; 488 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 489 PetscValidType(mat, 1); 490 PetscValidBoolPointer(missing, 2); 491 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name); 492 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 493 PetscUseTypeMethod(mat, missingdiagonal, missing, dd); 494 PetscFunctionReturn(PETSC_SUCCESS); 495 } 496 497 /*@C 498 MatGetRow - Gets a row of a matrix. You MUST call `MatRestoreRow()` 499 for each row that you get to ensure that your application does 500 not bleed memory. 501 502 Not Collective 503 504 Input Parameters: 505 + mat - the matrix 506 - row - the row to get 507 508 Output Parameters: 509 + ncols - if not `NULL`, the number of nonzeros in the row 510 . cols - if not `NULL`, the column numbers 511 - vals - if not `NULL`, the values 512 513 Level: advanced 514 515 Notes: 516 This routine is provided for people who need to have direct access 517 to the structure of a matrix. We hope that we provide enough 518 high-level matrix routines that few users will need it. 519 520 `MatGetRow()` always returns 0-based column indices, regardless of 521 whether the internal representation is 0-based (default) or 1-based. 522 523 For better efficiency, set cols and/or vals to `NULL` if you do 524 not wish to extract these quantities. 525 526 The user can only examine the values extracted with `MatGetRow()`; 527 the values cannot be altered. To change the matrix entries, one 528 must use `MatSetValues()`. 529 530 You can only have one call to `MatGetRow()` outstanding for a particular 531 matrix at a time, per processor. `MatGetRow()` can only obtain rows 532 associated with the given processor, it cannot get rows from the 533 other processors; for that we suggest using `MatCreateSubMatrices()`, then 534 MatGetRow() on the submatrix. The row index passed to `MatGetRow()` 535 is in the global number of rows. 536 537 Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix. 538 539 Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly. 540 541 Fortran Note: 542 The calling sequence is 543 .vb 544 MatGetRow(matrix,row,ncols,cols,values,ierr) 545 Mat matrix (input) 546 integer row (input) 547 integer ncols (output) 548 integer cols(maxcols) (output) 549 double precision (or double complex) values(maxcols) output 550 .ve 551 where maxcols >= maximum nonzeros in any row of the matrix. 552 553 Caution: 554 Do not try to change the contents of the output arrays (cols and vals). 555 In some cases, this may corrupt the matrix. 556 557 .seealso: `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()` 558 @*/ 559 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 560 { 561 PetscInt incols; 562 563 PetscFunctionBegin; 564 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 565 PetscValidType(mat, 1); 566 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 567 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 568 MatCheckPreallocated(mat, 1); 569 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); 570 PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0)); 571 PetscCall((*mat->ops->getrow)(mat, row, &incols, (PetscInt **)cols, (PetscScalar **)vals)); 572 if (ncols) *ncols = incols; 573 PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0)); 574 PetscFunctionReturn(PETSC_SUCCESS); 575 } 576 577 /*@ 578 MatConjugate - replaces the matrix values with their complex conjugates 579 580 Logically Collective 581 582 Input Parameters: 583 . mat - the matrix 584 585 Level: advanced 586 587 .seealso: `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()` 588 @*/ 589 PetscErrorCode MatConjugate(Mat mat) 590 { 591 PetscFunctionBegin; 592 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 593 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 594 if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) { 595 PetscUseTypeMethod(mat, conjugate); 596 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 597 } 598 PetscFunctionReturn(PETSC_SUCCESS); 599 } 600 601 /*@C 602 MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`. 603 604 Not Collective 605 606 Input Parameters: 607 + mat - the matrix 608 . row - the row to get 609 . ncols, cols - the number of nonzeros and their columns 610 - vals - if nonzero the column values 611 612 Level: advanced 613 614 Notes: 615 This routine should be called after you have finished examining the entries. 616 617 This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental 618 us of the array after it has been restored. If you pass `NULL`, it will 619 not zero the pointers. Use of `cols` or `vals` after `MatRestoreRow()` is invalid. 620 621 Fortran Notes: 622 The calling sequence is 623 .vb 624 MatRestoreRow(matrix,row,ncols,cols,values,ierr) 625 Mat matrix (input) 626 integer row (input) 627 integer ncols (output) 628 integer cols(maxcols) (output) 629 double precision (or double complex) values(maxcols) output 630 .ve 631 Where maxcols >= maximum nonzeros in any row of the matrix. 632 633 In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()` 634 before another call to `MatGetRow()` can be made. 635 636 .seealso: `Mat`, `MatGetRow()` 637 @*/ 638 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 639 { 640 PetscFunctionBegin; 641 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 642 if (ncols) PetscValidIntPointer(ncols, 3); 643 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 644 if (!mat->ops->restorerow) PetscFunctionReturn(PETSC_SUCCESS); 645 PetscCall((*mat->ops->restorerow)(mat, row, ncols, (PetscInt **)cols, (PetscScalar **)vals)); 646 if (ncols) *ncols = 0; 647 if (cols) *cols = NULL; 648 if (vals) *vals = NULL; 649 PetscFunctionReturn(PETSC_SUCCESS); 650 } 651 652 /*@ 653 MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 654 You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag. 655 656 Not Collective 657 658 Input Parameters: 659 . mat - the matrix 660 661 Level: advanced 662 663 Note: 664 The flag is to ensure that users are aware that `MatGetRow()` only provides the upper triangular part of the row for the matrices in `MATSBAIJ` format. 665 666 .seealso: `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()` 667 @*/ 668 PetscErrorCode MatGetRowUpperTriangular(Mat mat) 669 { 670 PetscFunctionBegin; 671 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 672 PetscValidType(mat, 1); 673 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 674 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 675 MatCheckPreallocated(mat, 1); 676 if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS); 677 PetscUseTypeMethod(mat, getrowuppertriangular); 678 PetscFunctionReturn(PETSC_SUCCESS); 679 } 680 681 /*@ 682 MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 683 684 Not Collective 685 686 Input Parameters: 687 . mat - the matrix 688 689 Level: advanced 690 691 Note: 692 This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`. 693 694 .seealso: `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()` 695 @*/ 696 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat) 697 { 698 PetscFunctionBegin; 699 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 700 PetscValidType(mat, 1); 701 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 702 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 703 MatCheckPreallocated(mat, 1); 704 if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS); 705 PetscUseTypeMethod(mat, restorerowuppertriangular); 706 PetscFunctionReturn(PETSC_SUCCESS); 707 } 708 709 /*@C 710 MatSetOptionsPrefix - Sets the prefix used for searching for all 711 `Mat` options in the database. 712 713 Logically Collective 714 715 Input Parameters: 716 + A - the matrix 717 - prefix - the prefix to prepend to all option names 718 719 Level: advanced 720 721 Notes: 722 A hyphen (-) must NOT be given at the beginning of the prefix name. 723 The first character of all runtime options is AUTOMATICALLY the hyphen. 724 725 This is NOT used for options for the factorization of the matrix. Normally the 726 prefix is automatically passed in from the PC calling the factorization. To set 727 it directly use `MatSetOptionsPrefixFactor()` 728 729 .seealso: `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()` 730 @*/ 731 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[]) 732 { 733 PetscFunctionBegin; 734 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 735 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix)); 736 PetscFunctionReturn(PETSC_SUCCESS); 737 } 738 739 /*@C 740 MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for 741 for matrices created with `MatGetFactor()` 742 743 Logically Collective 744 745 Input Parameters: 746 + A - the matrix 747 - prefix - the prefix to prepend to all option names for the factored matrix 748 749 Level: developer 750 751 Notes: 752 A hyphen (-) must NOT be given at the beginning of the prefix name. 753 The first character of all runtime options is AUTOMATICALLY the hyphen. 754 755 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 756 it directly when not using `KSP`/`PC` use `MatSetOptionsPrefixFactor()` 757 758 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()` 759 @*/ 760 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[]) 761 { 762 PetscFunctionBegin; 763 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 764 if (prefix) { 765 PetscValidCharPointer(prefix, 2); 766 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 767 if (prefix != A->factorprefix) { 768 PetscCall(PetscFree(A->factorprefix)); 769 PetscCall(PetscStrallocpy(prefix, &A->factorprefix)); 770 } 771 } else PetscCall(PetscFree(A->factorprefix)); 772 PetscFunctionReturn(PETSC_SUCCESS); 773 } 774 775 /*@C 776 MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for 777 for matrices created with `MatGetFactor()` 778 779 Logically Collective 780 781 Input Parameters: 782 + A - the matrix 783 - prefix - the prefix to prepend to all option names for the factored matrix 784 785 Level: developer 786 787 Notes: 788 A hyphen (-) must NOT be given at the beginning of the prefix name. 789 The first character of all runtime options is AUTOMATICALLY the hyphen. 790 791 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 792 it directly when not using `KSP`/`PC` use `MatAppendOptionsPrefixFactor()` 793 794 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`, 795 `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`, 796 `MatSetOptionsPrefix()` 797 @*/ 798 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[]) 799 { 800 char *buf = A->factorprefix; 801 size_t len1, len2; 802 803 PetscFunctionBegin; 804 PetscValidHeader(A, 1); 805 if (!prefix) PetscFunctionReturn(PETSC_SUCCESS); 806 if (!buf) { 807 PetscCall(MatSetOptionsPrefixFactor(A, prefix)); 808 PetscFunctionReturn(PETSC_SUCCESS); 809 } 810 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 811 812 PetscCall(PetscStrlen(prefix, &len1)); 813 PetscCall(PetscStrlen(buf, &len2)); 814 PetscCall(PetscMalloc1(1 + len1 + len2, &A->factorprefix)); 815 PetscCall(PetscStrcpy(A->factorprefix, buf)); 816 PetscCall(PetscStrcat(A->factorprefix, prefix)); 817 PetscCall(PetscFree(buf)); 818 PetscFunctionReturn(PETSC_SUCCESS); 819 } 820 821 /*@C 822 MatAppendOptionsPrefix - Appends to the prefix used for searching for all 823 matrix options in the database. 824 825 Logically Collective 826 827 Input Parameters: 828 + A - the matrix 829 - prefix - the prefix to prepend to all option names 830 831 Level: advanced 832 833 Note: 834 A hyphen (-) must NOT be given at the beginning of the prefix name. 835 The first character of all runtime options is AUTOMATICALLY the hyphen. 836 837 .seealso: `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()` 838 @*/ 839 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[]) 840 { 841 PetscFunctionBegin; 842 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 843 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix)); 844 PetscFunctionReturn(PETSC_SUCCESS); 845 } 846 847 /*@C 848 MatGetOptionsPrefix - Gets the prefix used for searching for all 849 matrix options in the database. 850 851 Not Collective 852 853 Input Parameter: 854 . A - the matrix 855 856 Output Parameter: 857 . prefix - pointer to the prefix string used 858 859 Level: advanced 860 861 Fortran Note: 862 On the fortran side, the user should pass in a string `prefix` of 863 sufficient length to hold the prefix. 864 865 .seealso: `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()` 866 @*/ 867 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[]) 868 { 869 PetscFunctionBegin; 870 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 871 PetscValidPointer(prefix, 2); 872 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix)); 873 PetscFunctionReturn(PETSC_SUCCESS); 874 } 875 876 /*@ 877 MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by users. 878 879 Collective 880 881 Input Parameters: 882 . A - the matrix 883 884 Level: beginner 885 886 Notes: 887 The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`. 888 889 Users can reset the preallocation to access the original memory. 890 891 Currently only supported for `MATMPIAIJ` and `MATSEQAIJ` matrices. 892 893 .seealso: `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()` 894 @*/ 895 PetscErrorCode MatResetPreallocation(Mat A) 896 { 897 PetscFunctionBegin; 898 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 899 PetscValidType(A, 1); 900 PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A)); 901 PetscFunctionReturn(PETSC_SUCCESS); 902 } 903 904 /*@ 905 MatSetUp - Sets up the internal matrix data structures for later use. 906 907 Collective 908 909 Input Parameters: 910 . A - the matrix 911 912 Level: intermediate 913 914 Notes: 915 If the user has not set preallocation for this matrix then a default preallocation that is likely to be inefficient is used. 916 917 If a suitable preallocation routine is used, this function does not need to be called. 918 919 See the Performance chapter of the PETSc users manual for how to preallocate matrices 920 921 This routine is called internally by other matrix functions when needed so rarely needs to be called by users 922 923 .seealso: `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()` 924 @*/ 925 PetscErrorCode MatSetUp(Mat A) 926 { 927 PetscFunctionBegin; 928 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 929 if (!((PetscObject)A)->type_name) { 930 PetscMPIInt size; 931 932 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 933 PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ)); 934 } 935 if (!A->preallocated) PetscTryTypeMethod(A, setup); 936 PetscCall(PetscLayoutSetUp(A->rmap)); 937 PetscCall(PetscLayoutSetUp(A->cmap)); 938 A->preallocated = PETSC_TRUE; 939 PetscFunctionReturn(PETSC_SUCCESS); 940 } 941 942 #if defined(PETSC_HAVE_SAWS) 943 #include <petscviewersaws.h> 944 #endif 945 946 /*@C 947 MatViewFromOptions - View properties of the matrix from the options database 948 949 Collective 950 951 Input Parameters: 952 + A - the matrix 953 . obj - optional additional object that provides the options prefix to use 954 - name - command line option 955 956 Options Database Key: 957 . -mat_view [viewertype]:... - the viewer and its options 958 959 Level: intermediate 960 961 Notes: 962 .vb 963 If no value is provided ascii:stdout is used 964 ascii[:[filename][:[format][:append]]] defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab, 965 for example ascii::ascii_info prints just the information about the object not all details 966 unless :append is given filename opens in write mode, overwriting what was already there 967 binary[:[filename][:[format][:append]]] defaults to the file binaryoutput 968 draw[:drawtype[:filename]] for example, draw:tikz, draw:tikz:figure.tex or draw:x 969 socket[:port] defaults to the standard output port 970 saws[:communicatorname] publishes object to the Scientific Application Webserver (SAWs) 971 .ve 972 973 .seealso: `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()` 974 @*/ 975 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[]) 976 { 977 PetscFunctionBegin; 978 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 979 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 980 PetscFunctionReturn(PETSC_SUCCESS); 981 } 982 983 /*@C 984 MatView - display information about a matrix in a variety ways 985 986 Collective 987 988 Input Parameters: 989 + mat - the matrix 990 - viewer - visualization context 991 992 Notes: 993 The available visualization contexts include 994 + `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices 995 . `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD` 996 . `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm 997 - `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure 998 999 The user can open alternative visualization contexts with 1000 + `PetscViewerASCIIOpen()` - Outputs matrix to a specified file 1001 . `PetscViewerBinaryOpen()` - Outputs matrix in binary to a 1002 specified file; corresponding input uses MatLoad() 1003 . `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to 1004 an X window display 1005 - `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer. 1006 Currently only the sequential dense and AIJ 1007 matrix types support the Socket viewer. 1008 1009 The user can call `PetscViewerPushFormat()` to specify the output 1010 format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`, 1011 `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`). Available formats include 1012 + `PETSC_VIEWER_DEFAULT` - default, prints matrix contents 1013 . `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in Matlab format 1014 . `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros 1015 . `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse 1016 format common among all matrix types 1017 . `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific 1018 format (which is in many cases the same as the default) 1019 . `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix 1020 size and structure (not the matrix entries) 1021 - `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about 1022 the matrix structure 1023 1024 Options Database Keys: 1025 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 1026 . -mat_view ::ascii_info_detail - Prints more detailed info 1027 . -mat_view - Prints matrix in ASCII format 1028 . -mat_view ::ascii_matlab - Prints matrix in Matlab format 1029 . -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 1030 . -display <name> - Sets display name (default is host) 1031 . -draw_pause <sec> - Sets number of seconds to pause after display 1032 . -mat_view socket - Sends matrix to socket, can be accessed from Matlab (see Users-Manual: ch_matlab for details) 1033 . -viewer_socket_machine <machine> - 1034 . -viewer_socket_port <port> - 1035 . -mat_view binary - save matrix to file in binary format 1036 - -viewer_binary_filename <name> - 1037 1038 Level: beginner 1039 1040 Notes: 1041 The ASCII viewers are only recommended for small matrices on at most a moderate number of processes, 1042 the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format. 1043 1044 In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer). 1045 1046 See the manual page for `MatLoad()` for the exact format of the binary file when the binary 1047 viewer is used. 1048 1049 See share/petsc/matlab/PetscBinaryRead.m for a Matlab code that can read in the binary file when the binary 1050 viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python. 1051 1052 One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure, 1053 and then use the following mouse functions. 1054 .vb 1055 left mouse: zoom in 1056 middle mouse: zoom out 1057 right mouse: continue with the simulation 1058 .ve 1059 1060 .seealso: `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`, 1061 `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()` 1062 @*/ 1063 PetscErrorCode MatView(Mat mat, PetscViewer viewer) 1064 { 1065 PetscInt rows, cols, rbs, cbs; 1066 PetscBool isascii, isstring, issaws; 1067 PetscViewerFormat format; 1068 PetscMPIInt size; 1069 1070 PetscFunctionBegin; 1071 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1072 PetscValidType(mat, 1); 1073 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer)); 1074 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1075 PetscCheckSameComm(mat, 1, viewer, 2); 1076 1077 PetscCall(PetscViewerGetFormat(viewer, &format)); 1078 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 1079 if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS); 1080 1081 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 1082 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 1083 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws)); 1084 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"); 1085 1086 PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0)); 1087 if (isascii) { 1088 if (!mat->preallocated) { 1089 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n")); 1090 PetscFunctionReturn(PETSC_SUCCESS); 1091 } 1092 if (!mat->assembled) { 1093 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n")); 1094 PetscFunctionReturn(PETSC_SUCCESS); 1095 } 1096 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer)); 1097 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1098 MatNullSpace nullsp, transnullsp; 1099 1100 PetscCall(PetscViewerASCIIPushTab(viewer)); 1101 PetscCall(MatGetSize(mat, &rows, &cols)); 1102 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1103 if (rbs != 1 || cbs != 1) { 1104 if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs)); 1105 else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs)); 1106 } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols)); 1107 if (mat->factortype) { 1108 MatSolverType solver; 1109 PetscCall(MatFactorGetSolverType(mat, &solver)); 1110 PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver)); 1111 } 1112 if (mat->ops->getinfo) { 1113 MatInfo info; 1114 PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info)); 1115 PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated)); 1116 if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs)); 1117 } 1118 PetscCall(MatGetNullSpace(mat, &nullsp)); 1119 PetscCall(MatGetTransposeNullSpace(mat, &transnullsp)); 1120 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached null space\n")); 1121 if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached transposed null space\n")); 1122 PetscCall(MatGetNearNullSpace(mat, &nullsp)); 1123 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached near null space\n")); 1124 PetscCall(PetscViewerASCIIPushTab(viewer)); 1125 PetscCall(MatProductView(mat, viewer)); 1126 PetscCall(PetscViewerASCIIPopTab(viewer)); 1127 } 1128 } else if (issaws) { 1129 #if defined(PETSC_HAVE_SAWS) 1130 PetscMPIInt rank; 1131 1132 PetscCall(PetscObjectName((PetscObject)mat)); 1133 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 1134 if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer)); 1135 #endif 1136 } else if (isstring) { 1137 const char *type; 1138 PetscCall(MatGetType(mat, &type)); 1139 PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type)); 1140 PetscTryTypeMethod(mat, view, viewer); 1141 } 1142 if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) { 1143 PetscCall(PetscViewerASCIIPushTab(viewer)); 1144 PetscUseTypeMethod(mat, viewnative, viewer); 1145 PetscCall(PetscViewerASCIIPopTab(viewer)); 1146 } else if (mat->ops->view) { 1147 PetscCall(PetscViewerASCIIPushTab(viewer)); 1148 PetscUseTypeMethod(mat, view, viewer); 1149 PetscCall(PetscViewerASCIIPopTab(viewer)); 1150 } 1151 if (isascii) { 1152 PetscCall(PetscViewerGetFormat(viewer, &format)); 1153 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer)); 1154 } 1155 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1156 PetscFunctionReturn(PETSC_SUCCESS); 1157 } 1158 1159 #if defined(PETSC_USE_DEBUG) 1160 #include <../src/sys/totalview/tv_data_display.h> 1161 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat) 1162 { 1163 TV_add_row("Local rows", "int", &mat->rmap->n); 1164 TV_add_row("Local columns", "int", &mat->cmap->n); 1165 TV_add_row("Global rows", "int", &mat->rmap->N); 1166 TV_add_row("Global columns", "int", &mat->cmap->N); 1167 TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name); 1168 return TV_format_OK; 1169 } 1170 #endif 1171 1172 /*@C 1173 MatLoad - Loads a matrix that has been stored in binary/HDF5 format 1174 with `MatView()`. The matrix format is determined from the options database. 1175 Generates a parallel MPI matrix if the communicator has more than one 1176 processor. The default matrix type is `MATAIJ`. 1177 1178 Collective 1179 1180 Input Parameters: 1181 + mat - the newly loaded matrix, this needs to have been created with `MatCreate()` 1182 or some related function before a call to `MatLoad()` 1183 - viewer - binary/HDF5 file viewer 1184 1185 Options Database Keys: 1186 Used with block matrix formats (`MATSEQBAIJ`, ...) to specify 1187 block size 1188 . -matload_block_size <bs> - set block size 1189 1190 Level: beginner 1191 1192 Notes: 1193 If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the 1194 `Mat` before calling this routine if you wish to set it from the options database. 1195 1196 `MatLoad()` automatically loads into the options database any options 1197 given in the file filename.info where filename is the name of the file 1198 that was passed to the `PetscViewerBinaryOpen()`. The options in the info 1199 file will be ignored if you use the -viewer_binary_skip_info option. 1200 1201 If the type or size of mat is not set before a call to `MatLoad()`, PETSc 1202 sets the default matrix type AIJ and sets the local and global sizes. 1203 If type and/or size is already set, then the same are used. 1204 1205 In parallel, each processor can load a subset of rows (or the 1206 entire matrix). This routine is especially useful when a large 1207 matrix is stored on disk and only part of it is desired on each 1208 processor. For example, a parallel solver may access only some of 1209 the rows from each processor. The algorithm used here reads 1210 relatively small blocks of data rather than reading the entire 1211 matrix and then subsetting it. 1212 1213 Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`. 1214 Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`, 1215 or the sequence like 1216 .vb 1217 `PetscViewer` v; 1218 `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v); 1219 `PetscViewerSetType`(v,`PETSCVIEWERBINARY`); 1220 `PetscViewerSetFromOptions`(v); 1221 `PetscViewerFileSetMode`(v,`FILE_MODE_READ`); 1222 `PetscViewerFileSetName`(v,"datafile"); 1223 .ve 1224 The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option 1225 $ -viewer_type {binary,hdf5} 1226 1227 See the example src/ksp/ksp/tutorials/ex27.c with the first approach, 1228 and src/mat/tutorials/ex10.c with the second approach. 1229 1230 Notes about the PETSc binary format: 1231 In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks 1232 is read onto rank 0 and then shipped to its destination rank, one after another. 1233 Multiple objects, both matrices and vectors, can be stored within the same file. 1234 Their PetscObject name is ignored; they are loaded in the order of their storage. 1235 1236 Most users should not need to know the details of the binary storage 1237 format, since `MatLoad()` and `MatView()` completely hide these details. 1238 But for anyone who's interested, the standard binary matrix storage 1239 format is 1240 1241 $ PetscInt MAT_FILE_CLASSID 1242 $ PetscInt number of rows 1243 $ PetscInt number of columns 1244 $ PetscInt total number of nonzeros 1245 $ PetscInt *number nonzeros in each row 1246 $ PetscInt *column indices of all nonzeros (starting index is zero) 1247 $ PetscScalar *values of all nonzeros 1248 1249 PETSc automatically does the byte swapping for 1250 machines that store the bytes reversed, e.g. DEC alpha, freebsd, 1251 Linux, Microsoft Windows and the Intel Paragon; thus if you write your own binary 1252 read/write routines you have to swap the bytes; see `PetscBinaryRead()` 1253 and `PetscBinaryWrite()` to see how this may be done. 1254 1255 Notes about the HDF5 (MATLAB MAT-File Version 7.3) format: 1256 In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used. 1257 Each processor's chunk is loaded independently by its owning rank. 1258 Multiple objects, both matrices and vectors, can be stored within the same file. 1259 They are looked up by their PetscObject name. 1260 1261 As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use 1262 by default the same structure and naming of the AIJ arrays and column count 1263 within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g. 1264 $ save example.mat A b -v7.3 1265 can be directly read by this routine (see Reference 1 for details). 1266 Note that depending on your MATLAB version, this format might be a default, 1267 otherwise you can set it as default in Preferences. 1268 1269 Unless -nocompression flag is used to save the file in MATLAB, 1270 PETSc must be configured with ZLIB package. 1271 1272 See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c 1273 1274 Current HDF5 (MAT-File) limitations: 1275 This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices. 1276 1277 Corresponding `MatView()` is not yet implemented. 1278 1279 The loaded matrix is actually a transpose of the original one in MATLAB, 1280 unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above). 1281 With this format, matrix is automatically transposed by PETSc, 1282 unless the matrix is marked as SPD or symmetric 1283 (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`). 1284 1285 References: 1286 . * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version 1287 1288 .seealso: `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()` 1289 @*/ 1290 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer) 1291 { 1292 PetscBool flg; 1293 1294 PetscFunctionBegin; 1295 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1296 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1297 1298 if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ)); 1299 1300 flg = PETSC_FALSE; 1301 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL)); 1302 if (flg) { 1303 PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE)); 1304 PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE)); 1305 } 1306 flg = PETSC_FALSE; 1307 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL)); 1308 if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE)); 1309 1310 PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0)); 1311 PetscUseTypeMethod(mat, load, viewer); 1312 PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0)); 1313 PetscFunctionReturn(PETSC_SUCCESS); 1314 } 1315 1316 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant) 1317 { 1318 Mat_Redundant *redund = *redundant; 1319 1320 PetscFunctionBegin; 1321 if (redund) { 1322 if (redund->matseq) { /* via MatCreateSubMatrices() */ 1323 PetscCall(ISDestroy(&redund->isrow)); 1324 PetscCall(ISDestroy(&redund->iscol)); 1325 PetscCall(MatDestroySubMatrices(1, &redund->matseq)); 1326 } else { 1327 PetscCall(PetscFree2(redund->send_rank, redund->recv_rank)); 1328 PetscCall(PetscFree(redund->sbuf_j)); 1329 PetscCall(PetscFree(redund->sbuf_a)); 1330 for (PetscInt i = 0; i < redund->nrecvs; i++) { 1331 PetscCall(PetscFree(redund->rbuf_j[i])); 1332 PetscCall(PetscFree(redund->rbuf_a[i])); 1333 } 1334 PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a)); 1335 } 1336 1337 if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm)); 1338 PetscCall(PetscFree(redund)); 1339 } 1340 PetscFunctionReturn(PETSC_SUCCESS); 1341 } 1342 1343 /*@C 1344 MatDestroy - Frees space taken by a matrix. 1345 1346 Collective 1347 1348 Input Parameter: 1349 . A - the matrix 1350 1351 Level: beginner 1352 1353 Developer Note: 1354 Some special arrays of matrices are not destroyed in this routine but instead by the routines called by 1355 `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines. 1356 `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes 1357 if changes are needed here. 1358 1359 .seealso: `Mat`, `MatCreate()` 1360 @*/ 1361 PetscErrorCode MatDestroy(Mat *A) 1362 { 1363 PetscFunctionBegin; 1364 if (!*A) PetscFunctionReturn(PETSC_SUCCESS); 1365 PetscValidHeaderSpecific(*A, MAT_CLASSID, 1); 1366 if (--((PetscObject)(*A))->refct > 0) { 1367 *A = NULL; 1368 PetscFunctionReturn(PETSC_SUCCESS); 1369 } 1370 1371 /* if memory was published with SAWs then destroy it */ 1372 PetscCall(PetscObjectSAWsViewOff((PetscObject)*A)); 1373 PetscTryTypeMethod((*A), destroy); 1374 1375 PetscCall(PetscFree((*A)->factorprefix)); 1376 PetscCall(PetscFree((*A)->defaultvectype)); 1377 PetscCall(PetscFree((*A)->defaultrandtype)); 1378 PetscCall(PetscFree((*A)->bsizes)); 1379 PetscCall(PetscFree((*A)->solvertype)); 1380 for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i])); 1381 if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL; 1382 PetscCall(MatDestroy_Redundant(&(*A)->redundant)); 1383 PetscCall(MatProductClear(*A)); 1384 PetscCall(MatNullSpaceDestroy(&(*A)->nullsp)); 1385 PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp)); 1386 PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp)); 1387 PetscCall(MatDestroy(&(*A)->schur)); 1388 PetscCall(PetscLayoutDestroy(&(*A)->rmap)); 1389 PetscCall(PetscLayoutDestroy(&(*A)->cmap)); 1390 PetscCall(PetscHeaderDestroy(A)); 1391 PetscFunctionReturn(PETSC_SUCCESS); 1392 } 1393 1394 /*@C 1395 MatSetValues - Inserts or adds a block of values into a matrix. 1396 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1397 MUST be called after all calls to `MatSetValues()` have been completed. 1398 1399 Not Collective 1400 1401 Input Parameters: 1402 + mat - the matrix 1403 . v - a logically two-dimensional array of values 1404 . m, idxm - the number of rows and their global indices 1405 . n, idxn - the number of columns and their global indices 1406 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1407 1408 Level: beginner 1409 1410 Notes: 1411 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 1412 `MatSetUp()` before using this routine 1413 1414 By default the values, v, are row-oriented. See `MatSetOption()` for other options. 1415 1416 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1417 options cannot be mixed without intervening calls to the assembly 1418 routines. 1419 1420 `MatSetValues()` uses 0-based row and column numbers in Fortran 1421 as well as in C. 1422 1423 Negative indices may be passed in idxm and idxn, these rows and columns are 1424 simply ignored. This allows easily inserting element stiffness matrices 1425 with homogeneous Dirchlet boundary conditions that you don't want represented 1426 in the matrix. 1427 1428 Efficiency Alert: 1429 The routine `MatSetValuesBlocked()` may offer much better efficiency 1430 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1431 1432 Developer Note: 1433 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1434 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1435 1436 .seealso: `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1437 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1438 @*/ 1439 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1440 { 1441 PetscFunctionBeginHot; 1442 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1443 PetscValidType(mat, 1); 1444 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1445 PetscValidIntPointer(idxm, 3); 1446 PetscValidIntPointer(idxn, 5); 1447 MatCheckPreallocated(mat, 1); 1448 1449 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1450 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1451 1452 if (PetscDefined(USE_DEBUG)) { 1453 PetscInt i, j; 1454 1455 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1456 for (i = 0; i < m; i++) { 1457 for (j = 0; j < n; j++) { 1458 if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j])) 1459 #if defined(PETSC_USE_COMPLEX) 1460 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]); 1461 #else 1462 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]); 1463 #endif 1464 } 1465 } 1466 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); 1467 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); 1468 } 1469 1470 if (mat->assembled) { 1471 mat->was_assembled = PETSC_TRUE; 1472 mat->assembled = PETSC_FALSE; 1473 } 1474 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1475 PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv); 1476 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1477 PetscFunctionReturn(PETSC_SUCCESS); 1478 } 1479 1480 /*@C 1481 MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns 1482 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1483 MUST be called after all calls to `MatSetValues()` have been completed. 1484 1485 Not Collective 1486 1487 Input Parameters: 1488 + mat - the matrix 1489 . v - a logically two-dimensional array of values 1490 . ism - the rows to provide 1491 . isn - the columns to provide 1492 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1493 1494 Level: beginner 1495 1496 Notes: 1497 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 1498 `MatSetUp()` before using this routine 1499 1500 By default the values, v, are row-oriented. See `MatSetOption()` for other options. 1501 1502 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1503 options cannot be mixed without intervening calls to the assembly 1504 routines. 1505 1506 `MatSetValues()` uses 0-based row and column numbers in Fortran 1507 as well as in C. 1508 1509 Negative indices may be passed in ism and isn, these rows and columns are 1510 simply ignored. This allows easily inserting element stiffness matrices 1511 with homogeneous Dirchlet boundary conditions that you don't want represented 1512 in the matrix. 1513 1514 Efficiency Alert: 1515 The routine `MatSetValuesBlocked()` may offer much better efficiency 1516 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1517 1518 This is currently not optimized for any particular `ISType` 1519 1520 Developer Notes: 1521 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1522 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1523 1524 .seealso: `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1525 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()` 1526 @*/ 1527 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv) 1528 { 1529 PetscInt m, n; 1530 const PetscInt *rows, *cols; 1531 1532 PetscFunctionBeginHot; 1533 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1534 PetscCall(ISGetIndices(ism, &rows)); 1535 PetscCall(ISGetIndices(isn, &cols)); 1536 PetscCall(ISGetLocalSize(ism, &m)); 1537 PetscCall(ISGetLocalSize(isn, &n)); 1538 PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv)); 1539 PetscCall(ISRestoreIndices(ism, &rows)); 1540 PetscCall(ISRestoreIndices(isn, &cols)); 1541 PetscFunctionReturn(PETSC_SUCCESS); 1542 } 1543 1544 /*@ 1545 MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1546 values into a matrix 1547 1548 Not Collective 1549 1550 Input Parameters: 1551 + mat - the matrix 1552 . row - the (block) row to set 1553 - v - a logically two-dimensional array of values 1554 1555 Level: intermediate 1556 1557 Notes: 1558 The values, `v`, are column-oriented (for the block version) and sorted 1559 1560 All the nonzeros in the row must be provided 1561 1562 The matrix must have previously had its column indices set 1563 1564 The row must belong to this process 1565 1566 .seealso: `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1567 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()` 1568 @*/ 1569 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[]) 1570 { 1571 PetscInt globalrow; 1572 1573 PetscFunctionBegin; 1574 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1575 PetscValidType(mat, 1); 1576 PetscValidScalarPointer(v, 3); 1577 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow)); 1578 PetscCall(MatSetValuesRow(mat, globalrow, v)); 1579 PetscFunctionReturn(PETSC_SUCCESS); 1580 } 1581 1582 /*@ 1583 MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1584 values into a matrix 1585 1586 Not Collective 1587 1588 Input Parameters: 1589 + mat - the matrix 1590 . row - the (block) row to set 1591 - 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 1592 1593 Level: advanced 1594 1595 Notes: 1596 The values, `v`, are column-oriented for the block version. 1597 1598 All the nonzeros in the row must be provided 1599 1600 THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used. 1601 1602 The row must belong to this process 1603 1604 .seealso: `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1605 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()` 1606 @*/ 1607 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[]) 1608 { 1609 PetscFunctionBeginHot; 1610 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1611 PetscValidType(mat, 1); 1612 MatCheckPreallocated(mat, 1); 1613 PetscValidScalarPointer(v, 3); 1614 PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values"); 1615 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1616 mat->insertmode = INSERT_VALUES; 1617 1618 if (mat->assembled) { 1619 mat->was_assembled = PETSC_TRUE; 1620 mat->assembled = PETSC_FALSE; 1621 } 1622 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1623 PetscUseTypeMethod(mat, setvaluesrow, row, v); 1624 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1625 PetscFunctionReturn(PETSC_SUCCESS); 1626 } 1627 1628 /*@ 1629 MatSetValuesStencil - Inserts or adds a block of values into a matrix. 1630 Using structured grid indexing 1631 1632 Not Collective 1633 1634 Input Parameters: 1635 + mat - the matrix 1636 . m - number of rows being entered 1637 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered 1638 . n - number of columns being entered 1639 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered 1640 . v - a logically two-dimensional array of values 1641 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values 1642 1643 Level: beginner 1644 1645 Notes: 1646 By default the values, `v`, are row-oriented. See `MatSetOption()` for other options. 1647 1648 Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1649 options cannot be mixed without intervening calls to the assembly 1650 routines. 1651 1652 The grid coordinates are across the entire grid, not just the local portion 1653 1654 `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran 1655 as well as in C. 1656 1657 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1658 1659 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1660 or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1661 1662 The columns and rows in the stencil passed in MUST be contained within the 1663 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1664 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1665 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1666 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1667 1668 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 1669 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 1670 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 1671 `DM_BOUNDARY_PERIODIC` boundary type. 1672 1673 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 1674 a single value per point) you can skip filling those indices. 1675 1676 Inspired by the structured grid interface to the HYPRE package 1677 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1678 1679 Efficiency Alert: 1680 The routine `MatSetValuesBlockedStencil()` may offer much better efficiency 1681 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1682 1683 Fortran Note: 1684 In Fortran idxm and idxn should be declared as 1685 $ MatStencil idxm(4,m),idxn(4,n) 1686 and the values inserted using 1687 .vb 1688 idxm(MatStencil_i,1) = i 1689 idxm(MatStencil_j,1) = j 1690 idxm(MatStencil_k,1) = k 1691 idxm(MatStencil_c,1) = c 1692 etc 1693 .ve 1694 1695 .seealso: `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1696 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil` 1697 @*/ 1698 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1699 { 1700 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1701 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1702 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1703 1704 PetscFunctionBegin; 1705 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1706 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1707 PetscValidType(mat, 1); 1708 PetscValidPointer(idxm, 3); 1709 PetscValidPointer(idxn, 5); 1710 1711 if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 1712 jdxm = buf; 1713 jdxn = buf + m; 1714 } else { 1715 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1716 jdxm = bufm; 1717 jdxn = bufn; 1718 } 1719 for (i = 0; i < m; i++) { 1720 for (j = 0; j < 3 - sdim; j++) dxm++; 1721 tmp = *dxm++ - starts[0]; 1722 for (j = 0; j < dim - 1; j++) { 1723 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1724 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1725 } 1726 if (mat->stencil.noc) dxm++; 1727 jdxm[i] = tmp; 1728 } 1729 for (i = 0; i < n; i++) { 1730 for (j = 0; j < 3 - sdim; j++) dxn++; 1731 tmp = *dxn++ - starts[0]; 1732 for (j = 0; j < dim - 1; j++) { 1733 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1734 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1735 } 1736 if (mat->stencil.noc) dxn++; 1737 jdxn[i] = tmp; 1738 } 1739 PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv)); 1740 PetscCall(PetscFree2(bufm, bufn)); 1741 PetscFunctionReturn(PETSC_SUCCESS); 1742 } 1743 1744 /*@ 1745 MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix. 1746 Using structured grid indexing 1747 1748 Not Collective 1749 1750 Input Parameters: 1751 + mat - the matrix 1752 . m - number of rows being entered 1753 . idxm - grid coordinates for matrix rows being entered 1754 . n - number of columns being entered 1755 . idxn - grid coordinates for matrix columns being entered 1756 . v - a logically two-dimensional array of values 1757 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values 1758 1759 Level: beginner 1760 1761 Notes: 1762 By default the values, `v`, are row-oriented and unsorted. 1763 See `MatSetOption()` for other options. 1764 1765 Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1766 options cannot be mixed without intervening calls to the assembly 1767 routines. 1768 1769 The grid coordinates are across the entire grid, not just the local portion 1770 1771 `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran 1772 as well as in C. 1773 1774 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1775 1776 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1777 or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1778 1779 The columns and rows in the stencil passed in MUST be contained within the 1780 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1781 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1782 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1783 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1784 1785 Negative indices may be passed in idxm and idxn, these rows and columns are 1786 simply ignored. This allows easily inserting element stiffness matrices 1787 with homogeneous Dirchlet boundary conditions that you don't want represented 1788 in the matrix. 1789 1790 Inspired by the structured grid interface to the HYPRE package 1791 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1792 1793 Fortran Note: 1794 In Fortran idxm and idxn should be declared as 1795 $ MatStencil idxm(4,m),idxn(4,n) 1796 and the values inserted using 1797 .vb 1798 idxm(MatStencil_i,1) = i 1799 idxm(MatStencil_j,1) = j 1800 idxm(MatStencil_k,1) = k 1801 etc 1802 .ve 1803 1804 .seealso: `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1805 `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`, 1806 `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` 1807 @*/ 1808 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1809 { 1810 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1811 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1812 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1813 1814 PetscFunctionBegin; 1815 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1816 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1817 PetscValidType(mat, 1); 1818 PetscValidPointer(idxm, 3); 1819 PetscValidPointer(idxn, 5); 1820 PetscValidScalarPointer(v, 6); 1821 1822 if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 1823 jdxm = buf; 1824 jdxn = buf + m; 1825 } else { 1826 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1827 jdxm = bufm; 1828 jdxn = bufn; 1829 } 1830 for (i = 0; i < m; i++) { 1831 for (j = 0; j < 3 - sdim; j++) dxm++; 1832 tmp = *dxm++ - starts[0]; 1833 for (j = 0; j < sdim - 1; j++) { 1834 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1835 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1836 } 1837 dxm++; 1838 jdxm[i] = tmp; 1839 } 1840 for (i = 0; i < n; i++) { 1841 for (j = 0; j < 3 - sdim; j++) dxn++; 1842 tmp = *dxn++ - starts[0]; 1843 for (j = 0; j < sdim - 1; j++) { 1844 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1845 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1846 } 1847 dxn++; 1848 jdxn[i] = tmp; 1849 } 1850 PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv)); 1851 PetscCall(PetscFree2(bufm, bufn)); 1852 PetscFunctionReturn(PETSC_SUCCESS); 1853 } 1854 1855 /*@ 1856 MatSetStencil - Sets the grid information for setting values into a matrix via 1857 `MatSetValuesStencil()` 1858 1859 Not Collective 1860 1861 Input Parameters: 1862 + mat - the matrix 1863 . dim - dimension of the grid 1, 2, or 3 1864 . dims - number of grid points in x, y, and z direction, including ghost points on your processor 1865 . starts - starting point of ghost nodes on your processor in x, y, and z direction 1866 - dof - number of degrees of freedom per node 1867 1868 Level: beginner 1869 1870 Notes: 1871 Inspired by the structured grid interface to the HYPRE package 1872 (www.llnl.gov/CASC/hyper) 1873 1874 For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the 1875 user. 1876 1877 .seealso: `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1878 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()` 1879 @*/ 1880 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof) 1881 { 1882 PetscFunctionBegin; 1883 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1884 PetscValidIntPointer(dims, 3); 1885 PetscValidIntPointer(starts, 4); 1886 1887 mat->stencil.dim = dim + (dof > 1); 1888 for (PetscInt i = 0; i < dim; i++) { 1889 mat->stencil.dims[i] = dims[dim - i - 1]; /* copy the values in backwards */ 1890 mat->stencil.starts[i] = starts[dim - i - 1]; 1891 } 1892 mat->stencil.dims[dim] = dof; 1893 mat->stencil.starts[dim] = 0; 1894 mat->stencil.noc = (PetscBool)(dof == 1); 1895 PetscFunctionReturn(PETSC_SUCCESS); 1896 } 1897 1898 /*@C 1899 MatSetValuesBlocked - Inserts or adds a block of values into a matrix. 1900 1901 Not Collective 1902 1903 Input Parameters: 1904 + mat - the matrix 1905 . v - a logically two-dimensional array of values 1906 . m - the number of block rows 1907 . idxm - the global block indices 1908 . n - the number of block columns 1909 . idxn - the global block indices 1910 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values 1911 1912 Level: intermediate 1913 1914 Notes: 1915 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call 1916 MatXXXXSetPreallocation() or `MatSetUp()` before using this routine. 1917 1918 The `m` and `n` count the NUMBER of blocks in the row direction and column direction, 1919 NOT the total number of rows/columns; for example, if the block size is 2 and 1920 you are passing in values for rows 2,3,4,5 then m would be 2 (not 4). 1921 The values in idxm would be 1 2; that is the first index for each block divided by 1922 the block size. 1923 1924 Note that you must call `MatSetBlockSize()` when constructing this matrix (before 1925 preallocating it). 1926 1927 By default the values, `v`, are row-oriented, so the layout of 1928 `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options. 1929 1930 Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES` 1931 options cannot be mixed without intervening calls to the assembly 1932 routines. 1933 1934 `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran 1935 as well as in C. 1936 1937 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1938 simply ignored. This allows easily inserting element stiffness matrices 1939 with homogeneous Dirchlet boundary conditions that you don't want represented 1940 in the matrix. 1941 1942 Each time an entry is set within a sparse matrix via `MatSetValues()`, 1943 internal searching must be done to determine where to place the 1944 data in the matrix storage space. By instead inserting blocks of 1945 entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is 1946 reduced. 1947 1948 Example: 1949 .vb 1950 Suppose m=n=2 and block size(bs) = 2 The array is 1951 1952 1 2 | 3 4 1953 5 6 | 7 8 1954 - - - | - - - 1955 9 10 | 11 12 1956 13 14 | 15 16 1957 1958 v[] should be passed in like 1959 v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] 1960 1961 If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then 1962 v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16] 1963 .ve 1964 1965 .seealso: `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()` 1966 @*/ 1967 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1968 { 1969 PetscFunctionBeginHot; 1970 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1971 PetscValidType(mat, 1); 1972 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1973 PetscValidIntPointer(idxm, 3); 1974 PetscValidIntPointer(idxn, 5); 1975 MatCheckPreallocated(mat, 1); 1976 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1977 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1978 if (PetscDefined(USE_DEBUG)) { 1979 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1980 PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 1981 } 1982 if (PetscDefined(USE_DEBUG)) { 1983 PetscInt rbs, cbs, M, N, i; 1984 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1985 PetscCall(MatGetSize(mat, &M, &N)); 1986 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); 1987 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); 1988 } 1989 if (mat->assembled) { 1990 mat->was_assembled = PETSC_TRUE; 1991 mat->assembled = PETSC_FALSE; 1992 } 1993 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1994 if (mat->ops->setvaluesblocked) { 1995 PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv); 1996 } else { 1997 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn; 1998 PetscInt i, j, bs, cbs; 1999 2000 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 2001 if (m * bs + n * cbs <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2002 iidxm = buf; 2003 iidxn = buf + m * bs; 2004 } else { 2005 PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc)); 2006 iidxm = bufr; 2007 iidxn = bufc; 2008 } 2009 for (i = 0; i < m; i++) { 2010 for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j; 2011 } 2012 if (m != n || bs != cbs || idxm != idxn) { 2013 for (i = 0; i < n; i++) { 2014 for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j; 2015 } 2016 } else iidxn = iidxm; 2017 PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv)); 2018 PetscCall(PetscFree2(bufr, bufc)); 2019 } 2020 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2021 PetscFunctionReturn(PETSC_SUCCESS); 2022 } 2023 2024 /*@C 2025 MatGetValues - Gets a block of local values from a matrix. 2026 2027 Not Collective; can only return values that are owned by the give process 2028 2029 Input Parameters: 2030 + mat - the matrix 2031 . v - a logically two-dimensional array for storing the values 2032 . m - the number of rows 2033 . idxm - the global indices of the rows 2034 . n - the number of columns 2035 - idxn - the global indices of the columns 2036 2037 Level: advanced 2038 2039 Notes: 2040 The user must allocate space (m*n `PetscScalar`s) for the values, `v`. 2041 The values, `v`, are then returned in a row-oriented format, 2042 analogous to that used by default in `MatSetValues()`. 2043 2044 `MatGetValues()` uses 0-based row and column numbers in 2045 Fortran as well as in C. 2046 2047 `MatGetValues()` requires that the matrix has been assembled 2048 with `MatAssemblyBegin()`/`MatAssemblyEnd()`. Thus, calls to 2049 `MatSetValues()` and `MatGetValues()` CANNOT be made in succession 2050 without intermediate matrix assembly. 2051 2052 Negative row or column indices will be ignored and those locations in `v` will be 2053 left unchanged. 2054 2055 For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI rank. 2056 That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable 2057 from `MatGetOwnershipRange`(mat,&rstart,&rend). 2058 2059 .seealso: `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()` 2060 @*/ 2061 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) 2062 { 2063 PetscFunctionBegin; 2064 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2065 PetscValidType(mat, 1); 2066 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); 2067 PetscValidIntPointer(idxm, 3); 2068 PetscValidIntPointer(idxn, 5); 2069 PetscValidScalarPointer(v, 6); 2070 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2071 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2072 MatCheckPreallocated(mat, 1); 2073 2074 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2075 PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v); 2076 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2077 PetscFunctionReturn(PETSC_SUCCESS); 2078 } 2079 2080 /*@C 2081 MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices 2082 defined previously by `MatSetLocalToGlobalMapping()` 2083 2084 Not Collective 2085 2086 Input Parameters: 2087 + mat - the matrix 2088 . nrow - number of rows 2089 . irow - the row local indices 2090 . ncol - number of columns 2091 - icol - the column local indices 2092 2093 Output Parameter: 2094 . y - a logically two-dimensional array of values 2095 2096 Level: advanced 2097 2098 Notes: 2099 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine. 2100 2101 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, 2102 are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can 2103 determine if the resulting global row associated with the local row r is owned by the requesting MPI rank by applying the `ISLocalToGlobalMapping` set 2104 with `MatSetLocalToGlobalMapping()`. 2105 2106 Developer Note: 2107 This is labelled with C so does not automatically generate Fortran stubs and interfaces 2108 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2109 2110 .seealso: `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2111 `MatSetValuesLocal()`, `MatGetValues()` 2112 @*/ 2113 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[]) 2114 { 2115 PetscFunctionBeginHot; 2116 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2117 PetscValidType(mat, 1); 2118 MatCheckPreallocated(mat, 1); 2119 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */ 2120 PetscValidIntPointer(irow, 3); 2121 PetscValidIntPointer(icol, 5); 2122 if (PetscDefined(USE_DEBUG)) { 2123 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2124 PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2125 } 2126 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2127 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2128 if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y); 2129 else { 2130 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm; 2131 if ((nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2132 irowm = buf; 2133 icolm = buf + nrow; 2134 } else { 2135 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2136 irowm = bufr; 2137 icolm = bufc; 2138 } 2139 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping())."); 2140 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping())."); 2141 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm)); 2142 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm)); 2143 PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y)); 2144 PetscCall(PetscFree2(bufr, bufc)); 2145 } 2146 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2147 PetscFunctionReturn(PETSC_SUCCESS); 2148 } 2149 2150 /*@ 2151 MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and 2152 the same size. Currently, this can only be called once and creates the given matrix. 2153 2154 Not Collective 2155 2156 Input Parameters: 2157 + mat - the matrix 2158 . nb - the number of blocks 2159 . bs - the number of rows (and columns) in each block 2160 . rows - a concatenation of the rows for each block 2161 - v - a concatenation of logically two-dimensional arrays of values 2162 2163 Level: advanced 2164 2165 Note: 2166 `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values 2167 2168 In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix. 2169 2170 .seealso: `Mat`, `Mat`MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 2171 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()` 2172 @*/ 2173 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[]) 2174 { 2175 PetscFunctionBegin; 2176 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2177 PetscValidType(mat, 1); 2178 PetscValidIntPointer(rows, 4); 2179 PetscValidScalarPointer(v, 5); 2180 PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2181 2182 PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0)); 2183 if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v); 2184 else { 2185 for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES)); 2186 } 2187 PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0)); 2188 PetscFunctionReturn(PETSC_SUCCESS); 2189 } 2190 2191 /*@ 2192 MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by 2193 the routine `MatSetValuesLocal()` to allow users to insert matrix entries 2194 using a local (per-processor) numbering. 2195 2196 Not Collective 2197 2198 Input Parameters: 2199 + x - the matrix 2200 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()` 2201 - cmapping - column mapping 2202 2203 Level: intermediate 2204 2205 Note: 2206 If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix 2207 2208 .seealso: `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()` 2209 @*/ 2210 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping) 2211 { 2212 PetscFunctionBegin; 2213 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 2214 PetscValidType(x, 1); 2215 if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2); 2216 if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3); 2217 if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping); 2218 else { 2219 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping)); 2220 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping)); 2221 } 2222 PetscFunctionReturn(PETSC_SUCCESS); 2223 } 2224 2225 /*@ 2226 MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()` 2227 2228 Not Collective 2229 2230 Input Parameter: 2231 . A - the matrix 2232 2233 Output Parameters: 2234 + rmapping - row mapping 2235 - cmapping - column mapping 2236 2237 Level: advanced 2238 2239 .seealso: `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()` 2240 @*/ 2241 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping) 2242 { 2243 PetscFunctionBegin; 2244 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2245 PetscValidType(A, 1); 2246 if (rmapping) { 2247 PetscValidPointer(rmapping, 2); 2248 *rmapping = A->rmap->mapping; 2249 } 2250 if (cmapping) { 2251 PetscValidPointer(cmapping, 3); 2252 *cmapping = A->cmap->mapping; 2253 } 2254 PetscFunctionReturn(PETSC_SUCCESS); 2255 } 2256 2257 /*@ 2258 MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix 2259 2260 Logically Collective 2261 2262 Input Parameters: 2263 + A - the matrix 2264 . rmap - row layout 2265 - cmap - column layout 2266 2267 Level: advanced 2268 2269 Note: 2270 The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called. 2271 2272 .seealso: `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()` 2273 @*/ 2274 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap) 2275 { 2276 PetscFunctionBegin; 2277 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2278 PetscCall(PetscLayoutReference(rmap, &A->rmap)); 2279 PetscCall(PetscLayoutReference(cmap, &A->cmap)); 2280 PetscFunctionReturn(PETSC_SUCCESS); 2281 } 2282 2283 /*@ 2284 MatGetLayouts - Gets the `PetscLayout` objects for rows and columns 2285 2286 Not Collective 2287 2288 Input Parameter: 2289 . A - the matrix 2290 2291 Output Parameters: 2292 + rmap - row layout 2293 - cmap - column layout 2294 2295 Level: advanced 2296 2297 .seealso: `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()` 2298 @*/ 2299 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap) 2300 { 2301 PetscFunctionBegin; 2302 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2303 PetscValidType(A, 1); 2304 if (rmap) { 2305 PetscValidPointer(rmap, 2); 2306 *rmap = A->rmap; 2307 } 2308 if (cmap) { 2309 PetscValidPointer(cmap, 3); 2310 *cmap = A->cmap; 2311 } 2312 PetscFunctionReturn(PETSC_SUCCESS); 2313 } 2314 2315 /*@C 2316 MatSetValuesLocal - Inserts or adds values into certain locations of a matrix, 2317 using a local numbering of the nodes. 2318 2319 Not Collective 2320 2321 Input Parameters: 2322 + mat - the matrix 2323 . nrow - number of rows 2324 . irow - the row local indices 2325 . ncol - number of columns 2326 . icol - the column local indices 2327 . y - a logically two-dimensional array of values 2328 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2329 2330 Level: intermediate 2331 2332 Notes: 2333 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 2334 `MatSetUp()` before using this routine 2335 2336 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine 2337 2338 Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2339 options cannot be mixed without intervening calls to the assembly 2340 routines. 2341 2342 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2343 MUST be called after all calls to `MatSetValuesLocal()` have been completed. 2344 2345 Developer Note: 2346 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2347 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2348 2349 .seealso: `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2350 `MatGetValuesLocal()` 2351 @*/ 2352 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2353 { 2354 PetscFunctionBeginHot; 2355 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2356 PetscValidType(mat, 1); 2357 MatCheckPreallocated(mat, 1); 2358 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2359 PetscValidIntPointer(irow, 3); 2360 PetscValidIntPointer(icol, 5); 2361 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2362 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2363 if (PetscDefined(USE_DEBUG)) { 2364 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2365 PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2366 } 2367 2368 if (mat->assembled) { 2369 mat->was_assembled = PETSC_TRUE; 2370 mat->assembled = PETSC_FALSE; 2371 } 2372 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2373 if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv); 2374 else { 2375 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2376 const PetscInt *irowm, *icolm; 2377 2378 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2379 bufr = buf; 2380 bufc = buf + nrow; 2381 irowm = bufr; 2382 icolm = bufc; 2383 } else { 2384 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2385 irowm = bufr; 2386 icolm = bufc; 2387 } 2388 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr)); 2389 else irowm = irow; 2390 if (mat->cmap->mapping) { 2391 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2392 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc)); 2393 } else icolm = irowm; 2394 } else icolm = icol; 2395 PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv)); 2396 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2397 } 2398 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2399 PetscFunctionReturn(PETSC_SUCCESS); 2400 } 2401 2402 /*@C 2403 MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix, 2404 using a local ordering of the nodes a block at a time. 2405 2406 Not Collective 2407 2408 Input Parameters: 2409 + x - the matrix 2410 . nrow - number of rows 2411 . irow - the row local indices 2412 . ncol - number of columns 2413 . icol - the column local indices 2414 . y - a logically two-dimensional array of values 2415 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2416 2417 Level: intermediate 2418 2419 Notes: 2420 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or 2421 `MatSetUp()` before using this routine 2422 2423 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()` 2424 before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the 2425 2426 Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2427 options cannot be mixed without intervening calls to the assembly 2428 routines. 2429 2430 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2431 MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed. 2432 2433 Developer Note: 2434 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2435 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2436 2437 .seealso: `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, 2438 `MatSetValuesLocal()`, `MatSetValuesBlocked()` 2439 @*/ 2440 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2441 { 2442 PetscFunctionBeginHot; 2443 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2444 PetscValidType(mat, 1); 2445 MatCheckPreallocated(mat, 1); 2446 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2447 PetscValidIntPointer(irow, 3); 2448 PetscValidIntPointer(icol, 5); 2449 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2450 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2451 if (PetscDefined(USE_DEBUG)) { 2452 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2453 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); 2454 } 2455 2456 if (mat->assembled) { 2457 mat->was_assembled = PETSC_TRUE; 2458 mat->assembled = PETSC_FALSE; 2459 } 2460 if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */ 2461 PetscInt irbs, rbs; 2462 PetscCall(MatGetBlockSizes(mat, &rbs, NULL)); 2463 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs)); 2464 PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs); 2465 } 2466 if (PetscUnlikelyDebug(mat->cmap->mapping)) { 2467 PetscInt icbs, cbs; 2468 PetscCall(MatGetBlockSizes(mat, NULL, &cbs)); 2469 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs)); 2470 PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs); 2471 } 2472 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2473 if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv); 2474 else { 2475 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2476 const PetscInt *irowm, *icolm; 2477 2478 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) { 2479 bufr = buf; 2480 bufc = buf + nrow; 2481 irowm = bufr; 2482 icolm = bufc; 2483 } else { 2484 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2485 irowm = bufr; 2486 icolm = bufc; 2487 } 2488 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr)); 2489 else irowm = irow; 2490 if (mat->cmap->mapping) { 2491 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2492 PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc)); 2493 } else icolm = irowm; 2494 } else icolm = icol; 2495 PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv)); 2496 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2497 } 2498 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2499 PetscFunctionReturn(PETSC_SUCCESS); 2500 } 2501 2502 /*@ 2503 MatMultDiagonalBlock - Computes the matrix-vector product, y = Dx. Where D is defined by the inode or block structure of the diagonal 2504 2505 Collective 2506 2507 Input Parameters: 2508 + mat - the matrix 2509 - x - the vector to be multiplied 2510 2511 Output Parameters: 2512 . y - the result 2513 2514 Level: developer 2515 2516 Note: 2517 The vectors `x` and `y` cannot be the same. I.e., one cannot 2518 call `MatMultDiagonalBlock`(A,y,y). 2519 2520 .seealso: `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2521 @*/ 2522 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y) 2523 { 2524 PetscFunctionBegin; 2525 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2526 PetscValidType(mat, 1); 2527 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2528 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2529 2530 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2531 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2532 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2533 MatCheckPreallocated(mat, 1); 2534 2535 PetscUseTypeMethod(mat, multdiagonalblock, x, y); 2536 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2537 PetscFunctionReturn(PETSC_SUCCESS); 2538 } 2539 2540 /*@ 2541 MatMult - Computes the matrix-vector product, y = Ax. 2542 2543 Neighbor-wise Collective 2544 2545 Input Parameters: 2546 + mat - the matrix 2547 - x - the vector to be multiplied 2548 2549 Output Parameters: 2550 . y - the result 2551 2552 Level: beginner 2553 2554 Note: 2555 The vectors `x` and `y` cannot be the same. I.e., one cannot 2556 call `MatMult`(A,y,y). 2557 2558 .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2559 @*/ 2560 PetscErrorCode MatMult(Mat mat, Vec x, Vec y) 2561 { 2562 PetscFunctionBegin; 2563 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2564 PetscValidType(mat, 1); 2565 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2566 VecCheckAssembled(x); 2567 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2568 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2569 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2570 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2571 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); 2572 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); 2573 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); 2574 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); 2575 PetscCall(VecSetErrorIfLocked(y, 3)); 2576 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2577 MatCheckPreallocated(mat, 1); 2578 2579 PetscCall(VecLockReadPush(x)); 2580 PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0)); 2581 PetscUseTypeMethod(mat, mult, x, y); 2582 PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0)); 2583 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2584 PetscCall(VecLockReadPop(x)); 2585 PetscFunctionReturn(PETSC_SUCCESS); 2586 } 2587 2588 /*@ 2589 MatMultTranspose - Computes matrix transpose times a vector y = A^T * x. 2590 2591 Neighbor-wise Collective 2592 2593 Input Parameters: 2594 + mat - the matrix 2595 - x - the vector to be multiplied 2596 2597 Output Parameters: 2598 . y - the result 2599 2600 Level: beginner 2601 2602 Notes: 2603 The vectors `x` and `y` cannot be the same. I.e., one cannot 2604 call `MatMultTranspose`(A,y,y). 2605 2606 For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple, 2607 use `MatMultHermitianTranspose()` 2608 2609 .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()` 2610 @*/ 2611 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y) 2612 { 2613 PetscErrorCode (*op)(Mat, Vec, Vec) = NULL; 2614 2615 PetscFunctionBegin; 2616 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2617 PetscValidType(mat, 1); 2618 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2619 VecCheckAssembled(x); 2620 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2621 2622 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2623 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2624 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2625 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); 2626 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); 2627 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); 2628 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); 2629 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2630 MatCheckPreallocated(mat, 1); 2631 2632 if (!mat->ops->multtranspose) { 2633 if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult; 2634 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); 2635 } else op = mat->ops->multtranspose; 2636 PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0)); 2637 PetscCall(VecLockReadPush(x)); 2638 PetscCall((*op)(mat, x, y)); 2639 PetscCall(VecLockReadPop(x)); 2640 PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0)); 2641 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2642 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2643 PetscFunctionReturn(PETSC_SUCCESS); 2644 } 2645 2646 /*@ 2647 MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector. 2648 2649 Neighbor-wise Collective 2650 2651 Input Parameters: 2652 + mat - the matrix 2653 - x - the vector to be multilplied 2654 2655 Output Parameters: 2656 . y - the result 2657 2658 Level: beginner 2659 2660 Notes: 2661 The vectors `x` and `y` cannot be the same. I.e., one cannot 2662 call `MatMultHermitianTranspose`(A,y,y). 2663 2664 Also called the conjugate transpose, complex conjugate transpose, or adjoint. 2665 2666 For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical. 2667 2668 .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()` 2669 @*/ 2670 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y) 2671 { 2672 PetscFunctionBegin; 2673 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2674 PetscValidType(mat, 1); 2675 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2676 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2677 2678 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2679 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2680 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2681 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); 2682 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); 2683 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); 2684 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); 2685 MatCheckPreallocated(mat, 1); 2686 2687 PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0)); 2688 #if defined(PETSC_USE_COMPLEX) 2689 if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) { 2690 PetscCall(VecLockReadPush(x)); 2691 if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y); 2692 else PetscUseTypeMethod(mat, mult, x, y); 2693 PetscCall(VecLockReadPop(x)); 2694 } else { 2695 Vec w; 2696 PetscCall(VecDuplicate(x, &w)); 2697 PetscCall(VecCopy(x, w)); 2698 PetscCall(VecConjugate(w)); 2699 PetscCall(MatMultTranspose(mat, w, y)); 2700 PetscCall(VecDestroy(&w)); 2701 PetscCall(VecConjugate(y)); 2702 } 2703 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2704 #else 2705 PetscCall(MatMultTranspose(mat, x, y)); 2706 #endif 2707 PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0)); 2708 PetscFunctionReturn(PETSC_SUCCESS); 2709 } 2710 2711 /*@ 2712 MatMultAdd - Computes v3 = v2 + A * v1. 2713 2714 Neighbor-wise Collective 2715 2716 Input Parameters: 2717 + mat - the matrix 2718 - v1, v2 - the vectors 2719 2720 Output Parameters: 2721 . v3 - the result 2722 2723 Level: beginner 2724 2725 Note: 2726 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2727 call `MatMultAdd`(A,v1,v2,v1). 2728 2729 .seealso: `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()` 2730 @*/ 2731 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2732 { 2733 PetscFunctionBegin; 2734 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2735 PetscValidType(mat, 1); 2736 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2737 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2738 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2739 2740 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2741 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2742 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); 2743 /* 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); 2744 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); */ 2745 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); 2746 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); 2747 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2748 MatCheckPreallocated(mat, 1); 2749 2750 PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3)); 2751 PetscCall(VecLockReadPush(v1)); 2752 PetscUseTypeMethod(mat, multadd, v1, v2, v3); 2753 PetscCall(VecLockReadPop(v1)); 2754 PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3)); 2755 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2756 PetscFunctionReturn(PETSC_SUCCESS); 2757 } 2758 2759 /*@ 2760 MatMultTransposeAdd - Computes v3 = v2 + A' * v1. 2761 2762 Neighbor-wise Collective 2763 2764 Input Parameters: 2765 + mat - the matrix 2766 - v1, v2 - the vectors 2767 2768 Output Parameters: 2769 . v3 - the result 2770 2771 Level: beginner 2772 2773 Note: 2774 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2775 call `MatMultTransposeAdd`(A,v1,v2,v1). 2776 2777 .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2778 @*/ 2779 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2780 { 2781 PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd; 2782 2783 PetscFunctionBegin; 2784 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2785 PetscValidType(mat, 1); 2786 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2787 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2788 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2789 2790 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2791 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2792 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); 2793 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); 2794 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); 2795 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2796 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2797 MatCheckPreallocated(mat, 1); 2798 2799 PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2800 PetscCall(VecLockReadPush(v1)); 2801 PetscCall((*op)(mat, v1, v2, v3)); 2802 PetscCall(VecLockReadPop(v1)); 2803 PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2804 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2805 PetscFunctionReturn(PETSC_SUCCESS); 2806 } 2807 2808 /*@ 2809 MatMultHermitianTransposeAdd - Computes v3 = v2 + A^H * v1. 2810 2811 Neighbor-wise Collective 2812 2813 Input Parameters: 2814 + mat - the matrix 2815 - v1, v2 - the vectors 2816 2817 Output Parameters: 2818 . v3 - the result 2819 2820 Level: beginner 2821 2822 Note: 2823 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2824 call `MatMultHermitianTransposeAdd`(A,v1,v2,v1). 2825 2826 .seealso: `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2827 @*/ 2828 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2829 { 2830 PetscFunctionBegin; 2831 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2832 PetscValidType(mat, 1); 2833 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2834 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2835 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2836 2837 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2838 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2839 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2840 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); 2841 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); 2842 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); 2843 MatCheckPreallocated(mat, 1); 2844 2845 PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2846 PetscCall(VecLockReadPush(v1)); 2847 if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3); 2848 else { 2849 Vec w, z; 2850 PetscCall(VecDuplicate(v1, &w)); 2851 PetscCall(VecCopy(v1, w)); 2852 PetscCall(VecConjugate(w)); 2853 PetscCall(VecDuplicate(v3, &z)); 2854 PetscCall(MatMultTranspose(mat, w, z)); 2855 PetscCall(VecDestroy(&w)); 2856 PetscCall(VecConjugate(z)); 2857 if (v2 != v3) { 2858 PetscCall(VecWAXPY(v3, 1.0, v2, z)); 2859 } else { 2860 PetscCall(VecAXPY(v3, 1.0, z)); 2861 } 2862 PetscCall(VecDestroy(&z)); 2863 } 2864 PetscCall(VecLockReadPop(v1)); 2865 PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2866 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2867 PetscFunctionReturn(PETSC_SUCCESS); 2868 } 2869 2870 /*@C 2871 MatGetFactorType - gets the type of factorization it is 2872 2873 Not Collective 2874 2875 Input Parameters: 2876 . mat - the matrix 2877 2878 Output Parameters: 2879 . 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` 2880 2881 Level: intermediate 2882 2883 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2884 `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2885 @*/ 2886 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t) 2887 { 2888 PetscFunctionBegin; 2889 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2890 PetscValidType(mat, 1); 2891 PetscValidPointer(t, 2); 2892 *t = mat->factortype; 2893 PetscFunctionReturn(PETSC_SUCCESS); 2894 } 2895 2896 /*@C 2897 MatSetFactorType - sets the type of factorization it is 2898 2899 Logically Collective 2900 2901 Input Parameters: 2902 + mat - the matrix 2903 - 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` 2904 2905 Level: intermediate 2906 2907 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2908 `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2909 @*/ 2910 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t) 2911 { 2912 PetscFunctionBegin; 2913 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2914 PetscValidType(mat, 1); 2915 mat->factortype = t; 2916 PetscFunctionReturn(PETSC_SUCCESS); 2917 } 2918 2919 /*@C 2920 MatGetInfo - Returns information about matrix storage (number of 2921 nonzeros, memory, etc.). 2922 2923 Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag 2924 2925 Input Parameters: 2926 + mat - the matrix 2927 - flag - flag indicating the type of parameters to be returned (`MAT_LOCAL` - local matrix, `MAT_GLOBAL_MAX` - maximum over all processors, `MAT_GLOBAL_SUM` - sum over all processors) 2928 2929 Output Parameters: 2930 . info - matrix information context 2931 2932 Notes: 2933 The `MatInfo` context contains a variety of matrix data, including 2934 number of nonzeros allocated and used, number of mallocs during 2935 matrix assembly, etc. Additional information for factored matrices 2936 is provided (such as the fill ratio, number of mallocs during 2937 factorization, etc.). Much of this info is printed to `PETSC_STDOUT` 2938 when using the runtime options 2939 $ -info -mat_view ::ascii_info 2940 2941 Example for C/C++ Users: 2942 See the file ${PETSC_DIR}/include/petscmat.h for a complete list of 2943 data within the MatInfo context. For example, 2944 .vb 2945 MatInfo info; 2946 Mat A; 2947 double mal, nz_a, nz_u; 2948 2949 MatGetInfo(A,MAT_LOCAL,&info); 2950 mal = info.mallocs; 2951 nz_a = info.nz_allocated; 2952 .ve 2953 2954 Example for Fortran Users: 2955 Fortran users should declare info as a double precision 2956 array of dimension `MAT_INFO_SIZE`, and then extract the parameters 2957 of interest. See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h 2958 a complete list of parameter names. 2959 .vb 2960 double precision info(MAT_INFO_SIZE) 2961 double precision mal, nz_a 2962 Mat A 2963 integer ierr 2964 2965 call MatGetInfo(A,MAT_LOCAL,info,ierr) 2966 mal = info(MAT_INFO_MALLOCS) 2967 nz_a = info(MAT_INFO_NZ_ALLOCATED) 2968 .ve 2969 2970 Level: intermediate 2971 2972 Developer Note: 2973 Fortran interface is not autogenerated as the 2974 interface definition cannot be generated correctly [due to MatInfo] 2975 2976 .seealso: `Mat`, `MatInfo`, `MatStashGetInfo()` 2977 @*/ 2978 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info) 2979 { 2980 PetscFunctionBegin; 2981 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2982 PetscValidType(mat, 1); 2983 PetscValidPointer(info, 3); 2984 MatCheckPreallocated(mat, 1); 2985 PetscUseTypeMethod(mat, getinfo, flag, info); 2986 PetscFunctionReturn(PETSC_SUCCESS); 2987 } 2988 2989 /* 2990 This is used by external packages where it is not easy to get the info from the actual 2991 matrix factorization. 2992 */ 2993 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info) 2994 { 2995 PetscFunctionBegin; 2996 PetscCall(PetscMemzero(info, sizeof(MatInfo))); 2997 PetscFunctionReturn(PETSC_SUCCESS); 2998 } 2999 3000 /*@C 3001 MatLUFactor - Performs in-place LU factorization of matrix. 3002 3003 Collective 3004 3005 Input Parameters: 3006 + mat - the matrix 3007 . row - row permutation 3008 . col - column permutation 3009 - info - options for factorization, includes 3010 .vb 3011 fill - expected fill as ratio of original fill. 3012 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3013 Run with the option -info to determine an optimal value to use 3014 .ve 3015 Level: developer 3016 3017 Notes: 3018 Most users should employ the `KSP` interface for linear solvers 3019 instead of working directly with matrix algebra routines such as this. 3020 See, e.g., `KSPCreate()`. 3021 3022 This changes the state of the matrix to a factored matrix; it cannot be used 3023 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3024 3025 This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()` 3026 when not using `KSP`. 3027 3028 Developer Note: 3029 The Fortran interface is not autogenerated as the 3030 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3031 3032 .seealso: [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, 3033 `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3034 @*/ 3035 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3036 { 3037 MatFactorInfo tinfo; 3038 3039 PetscFunctionBegin; 3040 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3041 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3042 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3043 if (info) PetscValidPointer(info, 4); 3044 PetscValidType(mat, 1); 3045 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3046 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3047 MatCheckPreallocated(mat, 1); 3048 if (!info) { 3049 PetscCall(MatFactorInfoInitialize(&tinfo)); 3050 info = &tinfo; 3051 } 3052 3053 PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0)); 3054 PetscUseTypeMethod(mat, lufactor, row, col, info); 3055 PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0)); 3056 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3057 PetscFunctionReturn(PETSC_SUCCESS); 3058 } 3059 3060 /*@C 3061 MatILUFactor - Performs in-place ILU factorization of matrix. 3062 3063 Collective 3064 3065 Input Parameters: 3066 + mat - the matrix 3067 . row - row permutation 3068 . col - column permutation 3069 - info - structure containing 3070 .vb 3071 levels - number of levels of fill. 3072 expected fill - as ratio of original fill. 3073 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 3074 missing diagonal entries) 3075 .ve 3076 3077 Level: developer 3078 3079 Notes: 3080 Most users should employ the `KSP` interface for linear solvers 3081 instead of working directly with matrix algebra routines such as this. 3082 See, e.g., `KSPCreate()`. 3083 3084 Probably really in-place only when level of fill is zero, otherwise allocates 3085 new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()` 3086 when not using `KSP`. 3087 3088 Developer Note: 3089 The Fortran interface is not autogenerated as the 3090 interface definition cannot be generated correctly [due to MatFactorInfo] 3091 3092 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 3093 @*/ 3094 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3095 { 3096 PetscFunctionBegin; 3097 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3098 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3099 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3100 PetscValidPointer(info, 4); 3101 PetscValidType(mat, 1); 3102 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 3103 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3104 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3105 MatCheckPreallocated(mat, 1); 3106 3107 PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0)); 3108 PetscUseTypeMethod(mat, ilufactor, row, col, info); 3109 PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0)); 3110 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3111 PetscFunctionReturn(PETSC_SUCCESS); 3112 } 3113 3114 /*@C 3115 MatLUFactorSymbolic - Performs symbolic LU factorization of matrix. 3116 Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`. 3117 3118 Collective on fact 3119 3120 Input Parameters: 3121 + fact - the factor matrix obtained with `MatGetFactor()` 3122 . mat - the matrix 3123 . row, col - row and column permutations 3124 - info - options for factorization, includes 3125 .vb 3126 fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use 3127 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3128 .ve 3129 3130 Level: developer 3131 3132 Notes: 3133 See [Matrix Factorization](sec_matfactor) for additional information about factorizations 3134 3135 Most users should employ the simplified `KSP` interface for linear solvers 3136 instead of working directly with matrix algebra routines such as this. 3137 See, e.g., `KSPCreate()`. 3138 3139 Developer Note: 3140 The Fortran interface is not autogenerated as the 3141 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3142 3143 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3144 @*/ 3145 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 3146 { 3147 MatFactorInfo tinfo; 3148 3149 PetscFunctionBegin; 3150 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3151 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 3152 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 3153 if (info) PetscValidPointer(info, 5); 3154 PetscValidType(mat, 2); 3155 PetscValidPointer(fact, 1); 3156 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3157 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3158 if (!(fact)->ops->lufactorsymbolic) { 3159 MatSolverType stype; 3160 PetscCall(MatFactorGetSolverType(fact, &stype)); 3161 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic LU using solver package %s", ((PetscObject)mat)->type_name, stype); 3162 } 3163 MatCheckPreallocated(mat, 2); 3164 if (!info) { 3165 PetscCall(MatFactorInfoInitialize(&tinfo)); 3166 info = &tinfo; 3167 } 3168 3169 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0)); 3170 PetscCall((fact->ops->lufactorsymbolic)(fact, mat, row, col, info)); 3171 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0)); 3172 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3173 PetscFunctionReturn(PETSC_SUCCESS); 3174 } 3175 3176 /*@C 3177 MatLUFactorNumeric - Performs numeric LU factorization of a matrix. 3178 Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`. 3179 3180 Collective on fact 3181 3182 Input Parameters: 3183 + fact - the factor matrix obtained with `MatGetFactor()` 3184 . mat - the matrix 3185 - info - options for factorization 3186 3187 Level: developer 3188 3189 Notes: 3190 See `MatLUFactor()` for in-place factorization. See 3191 `MatCholeskyFactorNumeric()` for the symmetric, positive definite case. 3192 3193 Most users should employ the `KSP` interface for linear solvers 3194 instead of working directly with matrix algebra routines such as this. 3195 See, e.g., `KSPCreate()`. 3196 3197 Developer Note: 3198 The Fortran interface is not autogenerated as the 3199 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3200 3201 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()` 3202 @*/ 3203 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3204 { 3205 MatFactorInfo tinfo; 3206 3207 PetscFunctionBegin; 3208 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3209 PetscValidType(mat, 2); 3210 PetscValidPointer(fact, 1); 3211 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3212 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3213 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, 3214 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3215 3216 PetscCheck((fact)->ops->lufactornumeric, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s numeric LU", ((PetscObject)mat)->type_name); 3217 MatCheckPreallocated(mat, 2); 3218 if (!info) { 3219 PetscCall(MatFactorInfoInitialize(&tinfo)); 3220 info = &tinfo; 3221 } 3222 3223 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3224 else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0)); 3225 PetscCall((fact->ops->lufactornumeric)(fact, mat, info)); 3226 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3227 else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0)); 3228 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3229 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3230 PetscFunctionReturn(PETSC_SUCCESS); 3231 } 3232 3233 /*@C 3234 MatCholeskyFactor - Performs in-place Cholesky factorization of a 3235 symmetric matrix. 3236 3237 Collective 3238 3239 Input Parameters: 3240 + mat - the matrix 3241 . perm - row and column permutations 3242 - f - expected fill as ratio of original fill 3243 3244 Level: developer 3245 3246 Notes: 3247 See `MatLUFactor()` for the nonsymmetric case. See also `MatGetFactor()`, 3248 `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`. 3249 3250 Most users should employ the `KSP` interface for linear solvers 3251 instead of working directly with matrix algebra routines such as this. 3252 See, e.g., `KSPCreate()`. 3253 3254 Developer Note: 3255 The Fortran interface is not autogenerated as the 3256 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3257 3258 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()` 3259 `MatGetOrdering()` 3260 @*/ 3261 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info) 3262 { 3263 MatFactorInfo tinfo; 3264 3265 PetscFunctionBegin; 3266 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3267 PetscValidType(mat, 1); 3268 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2); 3269 if (info) PetscValidPointer(info, 3); 3270 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3271 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3272 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3273 MatCheckPreallocated(mat, 1); 3274 if (!info) { 3275 PetscCall(MatFactorInfoInitialize(&tinfo)); 3276 info = &tinfo; 3277 } 3278 3279 PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0)); 3280 PetscUseTypeMethod(mat, choleskyfactor, perm, info); 3281 PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0)); 3282 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3283 PetscFunctionReturn(PETSC_SUCCESS); 3284 } 3285 3286 /*@C 3287 MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization 3288 of a symmetric matrix. 3289 3290 Collective on fact 3291 3292 Input Parameters: 3293 + fact - the factor matrix obtained with `MatGetFactor()` 3294 . mat - the matrix 3295 . perm - row and column permutations 3296 - info - options for factorization, includes 3297 .vb 3298 fill - expected fill as ratio of original fill. 3299 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3300 Run with the option -info to determine an optimal value to use 3301 .ve 3302 3303 Level: developer 3304 3305 Notes: 3306 See `MatLUFactorSymbolic()` for the nonsymmetric case. See also 3307 `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`. 3308 3309 Most users should employ the `KSP` interface for linear solvers 3310 instead of working directly with matrix algebra routines such as this. 3311 See, e.g., `KSPCreate()`. 3312 3313 Developer Note: 3314 The Fortran interface is not autogenerated as the 3315 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3316 3317 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()` 3318 `MatGetOrdering()` 3319 @*/ 3320 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 3321 { 3322 MatFactorInfo tinfo; 3323 3324 PetscFunctionBegin; 3325 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3326 PetscValidType(mat, 2); 3327 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 3328 if (info) PetscValidPointer(info, 4); 3329 PetscValidPointer(fact, 1); 3330 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3331 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3332 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3333 if (!(fact)->ops->choleskyfactorsymbolic) { 3334 MatSolverType stype; 3335 PetscCall(MatFactorGetSolverType(fact, &stype)); 3336 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s symbolic factor Cholesky using solver package %s", ((PetscObject)mat)->type_name, stype); 3337 } 3338 MatCheckPreallocated(mat, 2); 3339 if (!info) { 3340 PetscCall(MatFactorInfoInitialize(&tinfo)); 3341 info = &tinfo; 3342 } 3343 3344 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3345 PetscCall((fact->ops->choleskyfactorsymbolic)(fact, mat, perm, info)); 3346 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3347 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3348 PetscFunctionReturn(PETSC_SUCCESS); 3349 } 3350 3351 /*@C 3352 MatCholeskyFactorNumeric - Performs numeric Cholesky factorization 3353 of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and 3354 `MatCholeskyFactorSymbolic()`. 3355 3356 Collective on fact 3357 3358 Input Parameters: 3359 + fact - the factor matrix obtained with `MatGetFactor()` 3360 . mat - the initial matrix 3361 . info - options for factorization 3362 - fact - the symbolic factor of mat 3363 3364 Level: developer 3365 3366 Note: 3367 Most users should employ the `KSP` interface for linear solvers 3368 instead of working directly with matrix algebra routines such as this. 3369 See, e.g., `KSPCreate()`. 3370 3371 Developer Note: 3372 The Fortran interface is not autogenerated as the 3373 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3374 3375 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()` 3376 @*/ 3377 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3378 { 3379 MatFactorInfo tinfo; 3380 3381 PetscFunctionBegin; 3382 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3383 PetscValidType(mat, 2); 3384 PetscValidPointer(fact, 1); 3385 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3386 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3387 PetscCheck((fact)->ops->choleskyfactornumeric, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s numeric factor Cholesky", ((PetscObject)mat)->type_name); 3388 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, 3389 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3390 MatCheckPreallocated(mat, 2); 3391 if (!info) { 3392 PetscCall(MatFactorInfoInitialize(&tinfo)); 3393 info = &tinfo; 3394 } 3395 3396 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3397 else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0)); 3398 PetscCall((fact->ops->choleskyfactornumeric)(fact, mat, info)); 3399 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3400 else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0)); 3401 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3402 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3403 PetscFunctionReturn(PETSC_SUCCESS); 3404 } 3405 3406 /*@ 3407 MatQRFactor - Performs in-place QR factorization of matrix. 3408 3409 Collective 3410 3411 Input Parameters: 3412 + mat - the matrix 3413 . col - column permutation 3414 - info - options for factorization, includes 3415 .vb 3416 fill - expected fill as ratio of original fill. 3417 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3418 Run with the option -info to determine an optimal value to use 3419 .ve 3420 3421 Level: developer 3422 3423 Notes: 3424 Most users should employ the `KSP` interface for linear solvers 3425 instead of working directly with matrix algebra routines such as this. 3426 See, e.g., `KSPCreate()`. 3427 3428 This changes the state of the matrix to a factored matrix; it cannot be used 3429 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3430 3431 Developer Note: 3432 The Fortran interface is not autogenerated as the 3433 interface definition cannot be generated correctly [due to MatFactorInfo] 3434 3435 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`, 3436 `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3437 @*/ 3438 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info) 3439 { 3440 PetscFunctionBegin; 3441 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3442 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2); 3443 if (info) PetscValidPointer(info, 3); 3444 PetscValidType(mat, 1); 3445 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3446 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3447 MatCheckPreallocated(mat, 1); 3448 PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0)); 3449 PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info)); 3450 PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0)); 3451 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3452 PetscFunctionReturn(PETSC_SUCCESS); 3453 } 3454 3455 /*@ 3456 MatQRFactorSymbolic - Performs symbolic QR factorization of matrix. 3457 Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`. 3458 3459 Collective on fact 3460 3461 Input Parameters: 3462 + fact - the factor matrix obtained with `MatGetFactor()` 3463 . mat - the matrix 3464 . col - column permutation 3465 - info - options for factorization, includes 3466 .vb 3467 fill - expected fill as ratio of original fill. 3468 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3469 Run with the option -info to determine an optimal value to use 3470 .ve 3471 3472 Level: developer 3473 3474 Note: 3475 Most users should employ the `KSP` interface for linear solvers 3476 instead of working directly with matrix algebra routines such as this. 3477 See, e.g., `KSPCreate()`. 3478 3479 Developer Note: 3480 The Fortran interface is not autogenerated as the 3481 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3482 3483 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3484 @*/ 3485 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info) 3486 { 3487 MatFactorInfo tinfo; 3488 3489 PetscFunctionBegin; 3490 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3491 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3492 if (info) PetscValidPointer(info, 4); 3493 PetscValidType(mat, 2); 3494 PetscValidPointer(fact, 1); 3495 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3496 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3497 MatCheckPreallocated(mat, 2); 3498 if (!info) { 3499 PetscCall(MatFactorInfoInitialize(&tinfo)); 3500 info = &tinfo; 3501 } 3502 3503 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3504 PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info)); 3505 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3506 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3507 PetscFunctionReturn(PETSC_SUCCESS); 3508 } 3509 3510 /*@ 3511 MatQRFactorNumeric - Performs numeric QR factorization of a matrix. 3512 Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`. 3513 3514 Collective on fact 3515 3516 Input Parameters: 3517 + fact - the factor matrix obtained with `MatGetFactor()` 3518 . mat - the matrix 3519 - info - options for factorization 3520 3521 Level: developer 3522 3523 Notes: 3524 See `MatQRFactor()` for in-place factorization. 3525 3526 Most users should employ the `KSP` interface for linear solvers 3527 instead of working directly with matrix algebra routines such as this. 3528 See, e.g., `KSPCreate()`. 3529 3530 Developer Note: 3531 The Fortran interface is not autogenerated as the 3532 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3533 3534 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()` 3535 @*/ 3536 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3537 { 3538 MatFactorInfo tinfo; 3539 3540 PetscFunctionBegin; 3541 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3542 PetscValidType(mat, 2); 3543 PetscValidPointer(fact, 1); 3544 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3545 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3546 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, 3547 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3548 3549 MatCheckPreallocated(mat, 2); 3550 if (!info) { 3551 PetscCall(MatFactorInfoInitialize(&tinfo)); 3552 info = &tinfo; 3553 } 3554 3555 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3556 else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0)); 3557 PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info)); 3558 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3559 else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0)); 3560 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3561 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3562 PetscFunctionReturn(PETSC_SUCCESS); 3563 } 3564 3565 /*@ 3566 MatSolve - Solves A x = b, given a factored matrix. 3567 3568 Neighbor-wise Collective 3569 3570 Input Parameters: 3571 + mat - the factored matrix 3572 - b - the right-hand-side vector 3573 3574 Output Parameter: 3575 . x - the result vector 3576 3577 Level: developer 3578 3579 Notes: 3580 The vectors `b` and `x` cannot be the same. I.e., one cannot 3581 call `MatSolve`(A,x,x). 3582 3583 Most users should employ the `KSP` interface for linear solvers 3584 instead of working directly with matrix algebra routines such as this. 3585 See, e.g., `KSPCreate()`. 3586 3587 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3588 @*/ 3589 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x) 3590 { 3591 PetscFunctionBegin; 3592 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3593 PetscValidType(mat, 1); 3594 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3595 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3596 PetscCheckSameComm(mat, 1, b, 2); 3597 PetscCheckSameComm(mat, 1, x, 3); 3598 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3599 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); 3600 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); 3601 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); 3602 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3603 MatCheckPreallocated(mat, 1); 3604 3605 PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0)); 3606 if (mat->factorerrortype) { 3607 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3608 PetscCall(VecSetInf(x)); 3609 } else PetscUseTypeMethod(mat, solve, b, x); 3610 PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0)); 3611 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3612 PetscFunctionReturn(PETSC_SUCCESS); 3613 } 3614 3615 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans) 3616 { 3617 Vec b, x; 3618 PetscInt N, i; 3619 PetscErrorCode (*f)(Mat, Vec, Vec); 3620 PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE; 3621 3622 PetscFunctionBegin; 3623 if (A->factorerrortype) { 3624 PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype)); 3625 PetscCall(MatSetInf(X)); 3626 PetscFunctionReturn(PETSC_SUCCESS); 3627 } 3628 f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose; 3629 PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 3630 PetscCall(MatBoundToCPU(A, &Abound)); 3631 if (!Abound) { 3632 PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3633 PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3634 } 3635 #if defined(PETSC_HAVE_CUDA) 3636 if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B)); 3637 if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X)); 3638 #elif (PETSC_HAVE_HIP) 3639 if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B)); 3640 if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X)); 3641 #endif 3642 PetscCall(MatGetSize(B, NULL, &N)); 3643 for (i = 0; i < N; i++) { 3644 PetscCall(MatDenseGetColumnVecRead(B, i, &b)); 3645 PetscCall(MatDenseGetColumnVecWrite(X, i, &x)); 3646 PetscCall((*f)(A, b, x)); 3647 PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x)); 3648 PetscCall(MatDenseRestoreColumnVecRead(B, i, &b)); 3649 } 3650 if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B)); 3651 if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X)); 3652 PetscFunctionReturn(PETSC_SUCCESS); 3653 } 3654 3655 /*@ 3656 MatMatSolve - Solves A X = B, given a factored matrix. 3657 3658 Neighbor-wise Collective 3659 3660 Input Parameters: 3661 + A - the factored matrix 3662 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS) 3663 3664 Output Parameter: 3665 . X - the result matrix (dense matrix) 3666 3667 Level: developer 3668 3669 Note: 3670 If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`; 3671 otherwise, `B` and `X` cannot be the same. 3672 3673 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3674 @*/ 3675 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X) 3676 { 3677 PetscFunctionBegin; 3678 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3679 PetscValidType(A, 1); 3680 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3681 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3682 PetscCheckSameComm(A, 1, B, 2); 3683 PetscCheckSameComm(A, 1, X, 3); 3684 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); 3685 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); 3686 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"); 3687 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3688 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3689 MatCheckPreallocated(A, 1); 3690 3691 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3692 if (!A->ops->matsolve) { 3693 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name)); 3694 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE)); 3695 } else PetscUseTypeMethod(A, matsolve, B, X); 3696 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3697 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3698 PetscFunctionReturn(PETSC_SUCCESS); 3699 } 3700 3701 /*@ 3702 MatMatSolveTranspose - Solves A^T X = B, given a factored matrix. 3703 3704 Neighbor-wise Collective 3705 3706 Input Parameters: 3707 + A - the factored matrix 3708 - B - the right-hand-side matrix (`MATDENSE` matrix) 3709 3710 Output Parameter: 3711 . X - the result matrix (dense matrix) 3712 3713 Level: developer 3714 3715 Note: 3716 The matrices `B` and `X` cannot be the same. I.e., one cannot 3717 call `MatMatSolveTranspose`(A,X,X). 3718 3719 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()` 3720 @*/ 3721 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X) 3722 { 3723 PetscFunctionBegin; 3724 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3725 PetscValidType(A, 1); 3726 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3727 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3728 PetscCheckSameComm(A, 1, B, 2); 3729 PetscCheckSameComm(A, 1, X, 3); 3730 PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3731 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); 3732 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); 3733 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); 3734 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"); 3735 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3736 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3737 MatCheckPreallocated(A, 1); 3738 3739 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3740 if (!A->ops->matsolvetranspose) { 3741 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name)); 3742 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE)); 3743 } else PetscUseTypeMethod(A, matsolvetranspose, B, X); 3744 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3745 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3746 PetscFunctionReturn(PETSC_SUCCESS); 3747 } 3748 3749 /*@ 3750 MatMatTransposeSolve - Solves A X = B^T, given a factored matrix. 3751 3752 Neighbor-wise Collective 3753 3754 Input Parameters: 3755 + A - the factored matrix 3756 - Bt - the transpose of right-hand-side matrix as a `MATDENSE` 3757 3758 Output Parameter: 3759 . X - the result matrix (dense matrix) 3760 3761 Level: developer 3762 3763 Note: 3764 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 3765 format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`. 3766 3767 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3768 @*/ 3769 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X) 3770 { 3771 PetscFunctionBegin; 3772 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3773 PetscValidType(A, 1); 3774 PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2); 3775 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3776 PetscCheckSameComm(A, 1, Bt, 2); 3777 PetscCheckSameComm(A, 1, X, 3); 3778 3779 PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3780 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); 3781 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); 3782 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"); 3783 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3784 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3785 MatCheckPreallocated(A, 1); 3786 3787 PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0)); 3788 PetscUseTypeMethod(A, mattransposesolve, Bt, X); 3789 PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0)); 3790 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3791 PetscFunctionReturn(PETSC_SUCCESS); 3792 } 3793 3794 /*@ 3795 MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or 3796 U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U, 3797 3798 Neighbor-wise Collective 3799 3800 Input Parameters: 3801 + mat - the factored matrix 3802 - b - the right-hand-side vector 3803 3804 Output Parameter: 3805 . x - the result vector 3806 3807 Level: developer 3808 3809 Notes: 3810 `MatSolve()` should be used for most applications, as it performs 3811 a forward solve followed by a backward solve. 3812 3813 The vectors `b` and `x` cannot be the same, i.e., one cannot 3814 call `MatForwardSolve`(A,x,x). 3815 3816 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3817 the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet. 3818 `MatForwardSolve()` solves U^T*D y = b, and 3819 `MatBackwardSolve()` solves U x = y. 3820 Thus they do not provide a symmetric preconditioner. 3821 3822 .seealso: `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatBackwardSolve()` 3823 @*/ 3824 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x) 3825 { 3826 PetscFunctionBegin; 3827 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3828 PetscValidType(mat, 1); 3829 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3830 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3831 PetscCheckSameComm(mat, 1, b, 2); 3832 PetscCheckSameComm(mat, 1, x, 3); 3833 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3834 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); 3835 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); 3836 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); 3837 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3838 MatCheckPreallocated(mat, 1); 3839 3840 PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0)); 3841 PetscUseTypeMethod(mat, forwardsolve, b, x); 3842 PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0)); 3843 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3844 PetscFunctionReturn(PETSC_SUCCESS); 3845 } 3846 3847 /*@ 3848 MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU. 3849 D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U, 3850 3851 Neighbor-wise Collective 3852 3853 Input Parameters: 3854 + mat - the factored matrix 3855 - b - the right-hand-side vector 3856 3857 Output Parameter: 3858 . x - the result vector 3859 3860 Level: developer 3861 3862 Notes: 3863 `MatSolve()` should be used for most applications, as it performs 3864 a forward solve followed by a backward solve. 3865 3866 The vectors `b` and `x` cannot be the same. I.e., one cannot 3867 call `MatBackwardSolve`(A,x,x). 3868 3869 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3870 the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet. 3871 `MatForwardSolve()` solves U^T*D y = b, and 3872 `MatBackwardSolve()` solves U x = y. 3873 Thus they do not provide a symmetric preconditioner. 3874 3875 .seealso: `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatForwardSolve()` 3876 @*/ 3877 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x) 3878 { 3879 PetscFunctionBegin; 3880 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3881 PetscValidType(mat, 1); 3882 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3883 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3884 PetscCheckSameComm(mat, 1, b, 2); 3885 PetscCheckSameComm(mat, 1, x, 3); 3886 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3887 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); 3888 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); 3889 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); 3890 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3891 MatCheckPreallocated(mat, 1); 3892 3893 PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0)); 3894 PetscUseTypeMethod(mat, backwardsolve, b, x); 3895 PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0)); 3896 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3897 PetscFunctionReturn(PETSC_SUCCESS); 3898 } 3899 3900 /*@ 3901 MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix. 3902 3903 Neighbor-wise Collective 3904 3905 Input Parameters: 3906 + mat - the factored matrix 3907 . b - the right-hand-side vector 3908 - y - the vector to be added to 3909 3910 Output Parameter: 3911 . x - the result vector 3912 3913 Level: developer 3914 3915 Note: 3916 The vectors `b` and `x` cannot be the same. I.e., one cannot 3917 call `MatSolveAdd`(A,x,y,x). 3918 3919 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3920 @*/ 3921 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x) 3922 { 3923 PetscScalar one = 1.0; 3924 Vec tmp; 3925 3926 PetscFunctionBegin; 3927 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3928 PetscValidType(mat, 1); 3929 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 3930 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3931 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 3932 PetscCheckSameComm(mat, 1, b, 2); 3933 PetscCheckSameComm(mat, 1, y, 3); 3934 PetscCheckSameComm(mat, 1, x, 4); 3935 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3936 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); 3937 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); 3938 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); 3939 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); 3940 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); 3941 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3942 MatCheckPreallocated(mat, 1); 3943 3944 PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y)); 3945 if (mat->factorerrortype) { 3946 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3947 PetscCall(VecSetInf(x)); 3948 } else if (mat->ops->solveadd) { 3949 PetscUseTypeMethod(mat, solveadd, b, y, x); 3950 } else { 3951 /* do the solve then the add manually */ 3952 if (x != y) { 3953 PetscCall(MatSolve(mat, b, x)); 3954 PetscCall(VecAXPY(x, one, y)); 3955 } else { 3956 PetscCall(VecDuplicate(x, &tmp)); 3957 PetscCall(VecCopy(x, tmp)); 3958 PetscCall(MatSolve(mat, b, x)); 3959 PetscCall(VecAXPY(x, one, tmp)); 3960 PetscCall(VecDestroy(&tmp)); 3961 } 3962 } 3963 PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y)); 3964 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3965 PetscFunctionReturn(PETSC_SUCCESS); 3966 } 3967 3968 /*@ 3969 MatSolveTranspose - Solves A' x = b, given a factored matrix. 3970 3971 Neighbor-wise Collective 3972 3973 Input Parameters: 3974 + mat - the factored matrix 3975 - b - the right-hand-side vector 3976 3977 Output Parameter: 3978 . x - the result vector 3979 3980 Level: developer 3981 3982 Notes: 3983 The vectors `b` and `x` cannot be the same. I.e., one cannot 3984 call `MatSolveTranspose`(A,x,x). 3985 3986 Most users should employ the `KSP` interface for linear solvers 3987 instead of working directly with matrix algebra routines such as this. 3988 See, e.g., `KSPCreate()`. 3989 3990 .seealso: `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()` 3991 @*/ 3992 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x) 3993 { 3994 PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose; 3995 3996 PetscFunctionBegin; 3997 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3998 PetscValidType(mat, 1); 3999 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4000 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 4001 PetscCheckSameComm(mat, 1, b, 2); 4002 PetscCheckSameComm(mat, 1, x, 3); 4003 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4004 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); 4005 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); 4006 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4007 MatCheckPreallocated(mat, 1); 4008 PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0)); 4009 if (mat->factorerrortype) { 4010 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4011 PetscCall(VecSetInf(x)); 4012 } else { 4013 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name); 4014 PetscCall((*f)(mat, b, x)); 4015 } 4016 PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0)); 4017 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4018 PetscFunctionReturn(PETSC_SUCCESS); 4019 } 4020 4021 /*@ 4022 MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a 4023 factored matrix. 4024 4025 Neighbor-wise Collective 4026 4027 Input Parameters: 4028 + mat - the factored matrix 4029 . b - the right-hand-side vector 4030 - y - the vector to be added to 4031 4032 Output Parameter: 4033 . x - the result vector 4034 4035 Level: developer 4036 4037 Note: 4038 The vectors `b` and `x` cannot be the same. I.e., one cannot 4039 call `MatSolveTransposeAdd`(A,x,y,x). 4040 4041 .seealso: `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()` 4042 @*/ 4043 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x) 4044 { 4045 PetscScalar one = 1.0; 4046 Vec tmp; 4047 PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd; 4048 4049 PetscFunctionBegin; 4050 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4051 PetscValidType(mat, 1); 4052 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4053 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4054 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4055 PetscCheckSameComm(mat, 1, b, 2); 4056 PetscCheckSameComm(mat, 1, y, 3); 4057 PetscCheckSameComm(mat, 1, x, 4); 4058 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4059 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); 4060 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); 4061 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); 4062 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); 4063 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4064 MatCheckPreallocated(mat, 1); 4065 4066 PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y)); 4067 if (mat->factorerrortype) { 4068 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4069 PetscCall(VecSetInf(x)); 4070 } else if (f) { 4071 PetscCall((*f)(mat, b, y, x)); 4072 } else { 4073 /* do the solve then the add manually */ 4074 if (x != y) { 4075 PetscCall(MatSolveTranspose(mat, b, x)); 4076 PetscCall(VecAXPY(x, one, y)); 4077 } else { 4078 PetscCall(VecDuplicate(x, &tmp)); 4079 PetscCall(VecCopy(x, tmp)); 4080 PetscCall(MatSolveTranspose(mat, b, x)); 4081 PetscCall(VecAXPY(x, one, tmp)); 4082 PetscCall(VecDestroy(&tmp)); 4083 } 4084 } 4085 PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y)); 4086 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4087 PetscFunctionReturn(PETSC_SUCCESS); 4088 } 4089 4090 /*@ 4091 MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps. 4092 4093 Neighbor-wise Collective 4094 4095 Input Parameters: 4096 + mat - the matrix 4097 . b - the right hand side 4098 . omega - the relaxation factor 4099 . flag - flag indicating the type of SOR (see below) 4100 . shift - diagonal shift 4101 . its - the number of iterations 4102 - lits - the number of local iterations 4103 4104 Output Parameter: 4105 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess) 4106 4107 SOR Flags: 4108 + `SOR_FORWARD_SWEEP` - forward SOR 4109 . `SOR_BACKWARD_SWEEP` - backward SOR 4110 . `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR) 4111 . `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR 4112 . `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR 4113 . `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR 4114 . `SOR_EISENSTAT` - SOR with Eisenstat trick 4115 . `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies 4116 upper/lower triangular part of matrix to 4117 vector (with omega) 4118 - `SOR_ZERO_INITIAL_GUESS` - zero initial guess 4119 4120 Level: developer 4121 4122 Notes: 4123 `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and 4124 `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings 4125 on each processor. 4126 4127 Application programmers will not generally use `MatSOR()` directly, 4128 but instead will employ the `KSP`/`PC` interface. 4129 4130 For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing 4131 4132 Most users should employ the `KSP` interface for linear solvers 4133 instead of working directly with matrix algebra routines such as this. 4134 See, e.g., `KSPCreate()`. 4135 4136 Vectors `x` and `b` CANNOT be the same 4137 4138 Notes for Advanced Users: 4139 The flags are implemented as bitwise inclusive or operations. 4140 For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`) 4141 to specify a zero initial guess for SSOR. 4142 4143 Developer Note: 4144 We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes 4145 4146 .seealso: `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()` 4147 @*/ 4148 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x) 4149 { 4150 PetscFunctionBegin; 4151 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4152 PetscValidType(mat, 1); 4153 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4154 PetscValidHeaderSpecific(x, VEC_CLASSID, 8); 4155 PetscCheckSameComm(mat, 1, b, 2); 4156 PetscCheckSameComm(mat, 1, x, 8); 4157 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4158 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4159 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); 4160 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); 4161 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); 4162 PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its); 4163 PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits); 4164 PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same"); 4165 4166 MatCheckPreallocated(mat, 1); 4167 PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0)); 4168 PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x); 4169 PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0)); 4170 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4171 PetscFunctionReturn(PETSC_SUCCESS); 4172 } 4173 4174 /* 4175 Default matrix copy routine. 4176 */ 4177 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str) 4178 { 4179 PetscInt i, rstart = 0, rend = 0, nz; 4180 const PetscInt *cwork; 4181 const PetscScalar *vwork; 4182 4183 PetscFunctionBegin; 4184 if (B->assembled) PetscCall(MatZeroEntries(B)); 4185 if (str == SAME_NONZERO_PATTERN) { 4186 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 4187 for (i = rstart; i < rend; i++) { 4188 PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork)); 4189 PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES)); 4190 PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork)); 4191 } 4192 } else { 4193 PetscCall(MatAYPX(B, 0.0, A, str)); 4194 } 4195 PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 4196 PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 4197 PetscFunctionReturn(PETSC_SUCCESS); 4198 } 4199 4200 /*@ 4201 MatCopy - Copies a matrix to another matrix. 4202 4203 Collective 4204 4205 Input Parameters: 4206 + A - the matrix 4207 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN` 4208 4209 Output Parameter: 4210 . B - where the copy is put 4211 4212 Level: intermediate 4213 4214 Notes: 4215 If you use `SAME_NONZERO_PATTERN `then the two matrices must have the same nonzero pattern or the routine will crash. 4216 4217 `MatCopy()` copies the matrix entries of a matrix to another existing 4218 matrix (after first zeroing the second matrix). A related routine is 4219 `MatConvert()`, which first creates a new matrix and then copies the data. 4220 4221 .seealso: `Mat`, `MatConvert()`, `MatDuplicate()` 4222 @*/ 4223 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str) 4224 { 4225 PetscInt i; 4226 4227 PetscFunctionBegin; 4228 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 4229 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 4230 PetscValidType(A, 1); 4231 PetscValidType(B, 2); 4232 PetscCheckSameComm(A, 1, B, 2); 4233 MatCheckPreallocated(B, 2); 4234 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4235 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4236 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, 4237 A->cmap->N, B->cmap->N); 4238 MatCheckPreallocated(A, 1); 4239 if (A == B) PetscFunctionReturn(PETSC_SUCCESS); 4240 4241 PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0)); 4242 if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str); 4243 else PetscCall(MatCopy_Basic(A, B, str)); 4244 4245 B->stencil.dim = A->stencil.dim; 4246 B->stencil.noc = A->stencil.noc; 4247 for (i = 0; i <= A->stencil.dim; i++) { 4248 B->stencil.dims[i] = A->stencil.dims[i]; 4249 B->stencil.starts[i] = A->stencil.starts[i]; 4250 } 4251 4252 PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0)); 4253 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4254 PetscFunctionReturn(PETSC_SUCCESS); 4255 } 4256 4257 /*@C 4258 MatConvert - Converts a matrix to another matrix, either of the same 4259 or different type. 4260 4261 Collective 4262 4263 Input Parameters: 4264 + mat - the matrix 4265 . newtype - new matrix type. Use `MATSAME` to create a new matrix of the 4266 same type as the original matrix. 4267 - reuse - denotes if the destination matrix is to be created or reused. 4268 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 4269 `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). 4270 4271 Output Parameter: 4272 . M - pointer to place new matrix 4273 4274 Level: intermediate 4275 4276 Notes: 4277 `MatConvert()` first creates a new matrix and then copies the data from 4278 the first matrix. A related routine is `MatCopy()`, which copies the matrix 4279 entries of one matrix to another already existing matrix context. 4280 4281 Cannot be used to convert a sequential matrix to parallel or parallel to sequential, 4282 the MPI communicator of the generated matrix is always the same as the communicator 4283 of the input matrix. 4284 4285 .seealso: `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 4286 @*/ 4287 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M) 4288 { 4289 PetscBool sametype, issame, flg; 4290 PetscBool3 issymmetric, ishermitian; 4291 char convname[256], mtype[256]; 4292 Mat B; 4293 4294 PetscFunctionBegin; 4295 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4296 PetscValidType(mat, 1); 4297 PetscValidPointer(M, 4); 4298 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4299 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4300 MatCheckPreallocated(mat, 1); 4301 4302 PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg)); 4303 if (flg) newtype = mtype; 4304 4305 PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype)); 4306 PetscCall(PetscStrcmp(newtype, "same", &issame)); 4307 PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix"); 4308 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"); 4309 4310 if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) { 4311 PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4312 PetscFunctionReturn(PETSC_SUCCESS); 4313 } 4314 4315 /* Cache Mat options because some converters use MatHeaderReplace */ 4316 issymmetric = mat->symmetric; 4317 ishermitian = mat->hermitian; 4318 4319 if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) { 4320 PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4321 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4322 } else { 4323 PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL; 4324 const char *prefix[3] = {"seq", "mpi", ""}; 4325 PetscInt i; 4326 /* 4327 Order of precedence: 4328 0) See if newtype is a superclass of the current matrix. 4329 1) See if a specialized converter is known to the current matrix. 4330 2) See if a specialized converter is known to the desired matrix class. 4331 3) See if a good general converter is registered for the desired class 4332 (as of 6/27/03 only MATMPIADJ falls into this category). 4333 4) See if a good general converter is known for the current matrix. 4334 5) Use a really basic converter. 4335 */ 4336 4337 /* 0) See if newtype is a superclass of the current matrix. 4338 i.e mat is mpiaij and newtype is aij */ 4339 for (i = 0; i < 2; i++) { 4340 PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname))); 4341 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4342 PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg)); 4343 PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg)); 4344 if (flg) { 4345 if (reuse == MAT_INPLACE_MATRIX) { 4346 PetscCall(PetscInfo(mat, "Early return\n")); 4347 PetscFunctionReturn(PETSC_SUCCESS); 4348 } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) { 4349 PetscCall(PetscInfo(mat, "Calling MatDuplicate\n")); 4350 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4351 PetscFunctionReturn(PETSC_SUCCESS); 4352 } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) { 4353 PetscCall(PetscInfo(mat, "Calling MatCopy\n")); 4354 PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN)); 4355 PetscFunctionReturn(PETSC_SUCCESS); 4356 } 4357 } 4358 } 4359 /* 1) See if a specialized converter is known to the current matrix and the desired class */ 4360 for (i = 0; i < 3; i++) { 4361 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4362 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4363 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4364 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4365 PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname))); 4366 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4367 PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv)); 4368 PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv)); 4369 if (conv) goto foundconv; 4370 } 4371 4372 /* 2) See if a specialized converter is known to the desired matrix class. */ 4373 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B)); 4374 PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 4375 PetscCall(MatSetType(B, newtype)); 4376 for (i = 0; i < 3; i++) { 4377 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4378 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4379 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4380 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4381 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4382 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4383 PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv)); 4384 PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv)); 4385 if (conv) { 4386 PetscCall(MatDestroy(&B)); 4387 goto foundconv; 4388 } 4389 } 4390 4391 /* 3) See if a good general converter is registered for the desired class */ 4392 conv = B->ops->convertfrom; 4393 PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv)); 4394 PetscCall(MatDestroy(&B)); 4395 if (conv) goto foundconv; 4396 4397 /* 4) See if a good general converter is known for the current matrix */ 4398 if (mat->ops->convert) conv = mat->ops->convert; 4399 PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv)); 4400 if (conv) goto foundconv; 4401 4402 /* 5) Use a really basic converter. */ 4403 PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n")); 4404 conv = MatConvert_Basic; 4405 4406 foundconv: 4407 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4408 PetscCall((*conv)(mat, newtype, reuse, M)); 4409 if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) { 4410 /* the block sizes must be same if the mappings are copied over */ 4411 (*M)->rmap->bs = mat->rmap->bs; 4412 (*M)->cmap->bs = mat->cmap->bs; 4413 PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping)); 4414 PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping)); 4415 (*M)->rmap->mapping = mat->rmap->mapping; 4416 (*M)->cmap->mapping = mat->cmap->mapping; 4417 } 4418 (*M)->stencil.dim = mat->stencil.dim; 4419 (*M)->stencil.noc = mat->stencil.noc; 4420 for (i = 0; i <= mat->stencil.dim; i++) { 4421 (*M)->stencil.dims[i] = mat->stencil.dims[i]; 4422 (*M)->stencil.starts[i] = mat->stencil.starts[i]; 4423 } 4424 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4425 } 4426 PetscCall(PetscObjectStateIncrease((PetscObject)*M)); 4427 4428 /* Copy Mat options */ 4429 if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE)); 4430 else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE)); 4431 if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE)); 4432 else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE)); 4433 PetscFunctionReturn(PETSC_SUCCESS); 4434 } 4435 4436 /*@C 4437 MatFactorGetSolverType - Returns name of the package providing the factorization routines 4438 4439 Not Collective 4440 4441 Input Parameter: 4442 . mat - the matrix, must be a factored matrix 4443 4444 Output Parameter: 4445 . type - the string name of the package (do not free this string) 4446 4447 Level: intermediate 4448 4449 Fortran Note: 4450 Pass in an empty string and the package name will be copied into it. Make sure the string is long enough. 4451 4452 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()` 4453 @*/ 4454 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type) 4455 { 4456 PetscErrorCode (*conv)(Mat, MatSolverType *); 4457 4458 PetscFunctionBegin; 4459 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4460 PetscValidType(mat, 1); 4461 PetscValidPointer(type, 2); 4462 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 4463 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv)); 4464 if (conv) PetscCall((*conv)(mat, type)); 4465 else *type = MATSOLVERPETSC; 4466 PetscFunctionReturn(PETSC_SUCCESS); 4467 } 4468 4469 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType; 4470 struct _MatSolverTypeForSpecifcType { 4471 MatType mtype; 4472 /* no entry for MAT_FACTOR_NONE */ 4473 PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *); 4474 MatSolverTypeForSpecifcType next; 4475 }; 4476 4477 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder; 4478 struct _MatSolverTypeHolder { 4479 char *name; 4480 MatSolverTypeForSpecifcType handlers; 4481 MatSolverTypeHolder next; 4482 }; 4483 4484 static MatSolverTypeHolder MatSolverTypeHolders = NULL; 4485 4486 /*@C 4487 MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type 4488 4489 Input Parameters: 4490 + package - name of the package, for example petsc or superlu 4491 . mtype - the matrix type that works with this package 4492 . ftype - the type of factorization supported by the package 4493 - createfactor - routine that will create the factored matrix ready to be used 4494 4495 Level: developer 4496 4497 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()` 4498 @*/ 4499 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *)) 4500 { 4501 MatSolverTypeHolder next = MatSolverTypeHolders, prev = NULL; 4502 PetscBool flg; 4503 MatSolverTypeForSpecifcType inext, iprev = NULL; 4504 4505 PetscFunctionBegin; 4506 PetscCall(MatInitializePackage()); 4507 if (!next) { 4508 PetscCall(PetscNew(&MatSolverTypeHolders)); 4509 PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name)); 4510 PetscCall(PetscNew(&MatSolverTypeHolders->handlers)); 4511 PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype)); 4512 MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor; 4513 PetscFunctionReturn(PETSC_SUCCESS); 4514 } 4515 while (next) { 4516 PetscCall(PetscStrcasecmp(package, next->name, &flg)); 4517 if (flg) { 4518 PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers"); 4519 inext = next->handlers; 4520 while (inext) { 4521 PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg)); 4522 if (flg) { 4523 inext->createfactor[(int)ftype - 1] = createfactor; 4524 PetscFunctionReturn(PETSC_SUCCESS); 4525 } 4526 iprev = inext; 4527 inext = inext->next; 4528 } 4529 PetscCall(PetscNew(&iprev->next)); 4530 PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype)); 4531 iprev->next->createfactor[(int)ftype - 1] = createfactor; 4532 PetscFunctionReturn(PETSC_SUCCESS); 4533 } 4534 prev = next; 4535 next = next->next; 4536 } 4537 PetscCall(PetscNew(&prev->next)); 4538 PetscCall(PetscStrallocpy(package, &prev->next->name)); 4539 PetscCall(PetscNew(&prev->next->handlers)); 4540 PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype)); 4541 prev->next->handlers->createfactor[(int)ftype - 1] = createfactor; 4542 PetscFunctionReturn(PETSC_SUCCESS); 4543 } 4544 4545 /*@C 4546 MatSolverTypeGet - Gets the function that creates the factor matrix if it exist 4547 4548 Input Parameters: 4549 + type - name of the package, for example petsc or superlu 4550 . ftype - the type of factorization supported by the type 4551 - mtype - the matrix type that works with this type 4552 4553 Output Parameters: 4554 + foundtype - `PETSC_TRUE` if the type was registered 4555 . foundmtype - `PETSC_TRUE` if the type supports the requested mtype 4556 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found 4557 4558 Level: developer 4559 4560 .seealso: `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()` 4561 @*/ 4562 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *)) 4563 { 4564 MatSolverTypeHolder next = MatSolverTypeHolders; 4565 PetscBool flg; 4566 MatSolverTypeForSpecifcType inext; 4567 4568 PetscFunctionBegin; 4569 if (foundtype) *foundtype = PETSC_FALSE; 4570 if (foundmtype) *foundmtype = PETSC_FALSE; 4571 if (createfactor) *createfactor = NULL; 4572 4573 if (type) { 4574 while (next) { 4575 PetscCall(PetscStrcasecmp(type, next->name, &flg)); 4576 if (flg) { 4577 if (foundtype) *foundtype = PETSC_TRUE; 4578 inext = next->handlers; 4579 while (inext) { 4580 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4581 if (flg) { 4582 if (foundmtype) *foundmtype = PETSC_TRUE; 4583 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4584 PetscFunctionReturn(PETSC_SUCCESS); 4585 } 4586 inext = inext->next; 4587 } 4588 } 4589 next = next->next; 4590 } 4591 } else { 4592 while (next) { 4593 inext = next->handlers; 4594 while (inext) { 4595 PetscCall(PetscStrcmp(mtype, inext->mtype, &flg)); 4596 if (flg && inext->createfactor[(int)ftype - 1]) { 4597 if (foundtype) *foundtype = PETSC_TRUE; 4598 if (foundmtype) *foundmtype = PETSC_TRUE; 4599 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4600 PetscFunctionReturn(PETSC_SUCCESS); 4601 } 4602 inext = inext->next; 4603 } 4604 next = next->next; 4605 } 4606 /* try with base classes inext->mtype */ 4607 next = MatSolverTypeHolders; 4608 while (next) { 4609 inext = next->handlers; 4610 while (inext) { 4611 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4612 if (flg && inext->createfactor[(int)ftype - 1]) { 4613 if (foundtype) *foundtype = PETSC_TRUE; 4614 if (foundmtype) *foundmtype = PETSC_TRUE; 4615 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4616 PetscFunctionReturn(PETSC_SUCCESS); 4617 } 4618 inext = inext->next; 4619 } 4620 next = next->next; 4621 } 4622 } 4623 PetscFunctionReturn(PETSC_SUCCESS); 4624 } 4625 4626 PetscErrorCode MatSolverTypeDestroy(void) 4627 { 4628 MatSolverTypeHolder next = MatSolverTypeHolders, prev; 4629 MatSolverTypeForSpecifcType inext, iprev; 4630 4631 PetscFunctionBegin; 4632 while (next) { 4633 PetscCall(PetscFree(next->name)); 4634 inext = next->handlers; 4635 while (inext) { 4636 PetscCall(PetscFree(inext->mtype)); 4637 iprev = inext; 4638 inext = inext->next; 4639 PetscCall(PetscFree(iprev)); 4640 } 4641 prev = next; 4642 next = next->next; 4643 PetscCall(PetscFree(prev)); 4644 } 4645 MatSolverTypeHolders = NULL; 4646 PetscFunctionReturn(PETSC_SUCCESS); 4647 } 4648 4649 /*@C 4650 MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4651 4652 Logically Collective 4653 4654 Input Parameters: 4655 . mat - the matrix 4656 4657 Output Parameters: 4658 . flg - `PETSC_TRUE` if uses the ordering 4659 4660 Level: developer 4661 4662 Note: 4663 Most internal PETSc factorizations use the ordering passed to the factorization routine but external 4664 packages do not, thus we want to skip generating the ordering when it is not needed or used. 4665 4666 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4667 @*/ 4668 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg) 4669 { 4670 PetscFunctionBegin; 4671 *flg = mat->canuseordering; 4672 PetscFunctionReturn(PETSC_SUCCESS); 4673 } 4674 4675 /*@C 4676 MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object 4677 4678 Logically Collective 4679 4680 Input Parameters: 4681 . mat - the matrix obtained with `MatGetFactor()` 4682 4683 Output Parameters: 4684 . otype - the preferred type 4685 4686 Level: developer 4687 4688 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4689 @*/ 4690 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype) 4691 { 4692 PetscFunctionBegin; 4693 *otype = mat->preferredordering[ftype]; 4694 PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering"); 4695 PetscFunctionReturn(PETSC_SUCCESS); 4696 } 4697 4698 /*@C 4699 MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic() 4700 4701 Collective 4702 4703 Input Parameters: 4704 + mat - the matrix 4705 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4706 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4707 4708 Output Parameters: 4709 . f - the factor matrix used with MatXXFactorSymbolic() calls 4710 4711 Options Database Key: 4712 . -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory. 4713 One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices. 4714 4715 Level: intermediate 4716 4717 Notes: 4718 Users usually access the factorization solvers via `KSP` 4719 4720 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4721 such as pastix, superlu, mumps etc. 4722 4723 PETSc must have been ./configure to use the external solver, using the option --download-package 4724 4725 Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption 4726 where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set 4727 call `MatSetOptionsPrefixFactor()` on the originating matrix or `MatSetOptionsPrefix()` on the resulting factor matrix. 4728 4729 Developer Note: 4730 This should actually be called `MatCreateFactor()` since it creates a new factor object 4731 4732 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, 4733 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4734 @*/ 4735 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f) 4736 { 4737 PetscBool foundtype, foundmtype; 4738 PetscErrorCode (*conv)(Mat, MatFactorType, Mat *); 4739 4740 PetscFunctionBegin; 4741 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4742 PetscValidType(mat, 1); 4743 4744 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4745 MatCheckPreallocated(mat, 1); 4746 4747 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv)); 4748 if (!foundtype) { 4749 if (type) { 4750 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], 4751 ((PetscObject)mat)->type_name, type); 4752 } else { 4753 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); 4754 } 4755 } 4756 PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name); 4757 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); 4758 4759 PetscCall((*conv)(mat, ftype, f)); 4760 if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix)); 4761 PetscFunctionReturn(PETSC_SUCCESS); 4762 } 4763 4764 /*@C 4765 MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type 4766 4767 Not Collective 4768 4769 Input Parameters: 4770 + mat - the matrix 4771 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4772 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4773 4774 Output Parameter: 4775 . flg - PETSC_TRUE if the factorization is available 4776 4777 Level: intermediate 4778 4779 Notes: 4780 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4781 such as pastix, superlu, mumps etc. 4782 4783 PETSc must have been ./configure to use the external solver, using the option --download-package 4784 4785 Developer Note: 4786 This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object 4787 4788 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactor()`, `MatSolverTypeRegister()`, 4789 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4790 @*/ 4791 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg) 4792 { 4793 PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *); 4794 4795 PetscFunctionBegin; 4796 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4797 PetscValidType(mat, 1); 4798 PetscValidBoolPointer(flg, 4); 4799 4800 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4801 MatCheckPreallocated(mat, 1); 4802 4803 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv)); 4804 *flg = gconv ? PETSC_TRUE : PETSC_FALSE; 4805 PetscFunctionReturn(PETSC_SUCCESS); 4806 } 4807 4808 /*@ 4809 MatDuplicate - Duplicates a matrix including the non-zero structure. 4810 4811 Collective 4812 4813 Input Parameters: 4814 + mat - the matrix 4815 - op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`. 4816 See the manual page for `MatDuplicateOption()` for an explanation of these options. 4817 4818 Output Parameter: 4819 . M - pointer to place new matrix 4820 4821 Level: intermediate 4822 4823 Notes: 4824 You cannot change the nonzero pattern for the parent or child matrix if you use `MAT_SHARE_NONZERO_PATTERN`. 4825 4826 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. 4827 4828 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 4829 is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated. 4830 User should not use `MatDuplicate()` to create new matrix M if M is intended to be reused as the product of matrix operation. 4831 4832 .seealso: `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption` 4833 @*/ 4834 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M) 4835 { 4836 Mat B; 4837 VecType vtype; 4838 PetscInt i; 4839 PetscObject dm; 4840 void (*viewf)(void); 4841 4842 PetscFunctionBegin; 4843 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4844 PetscValidType(mat, 1); 4845 PetscValidPointer(M, 3); 4846 PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix"); 4847 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4848 MatCheckPreallocated(mat, 1); 4849 4850 *M = NULL; 4851 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4852 PetscUseTypeMethod(mat, duplicate, op, M); 4853 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4854 B = *M; 4855 4856 PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf)); 4857 if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf)); 4858 PetscCall(MatGetVecType(mat, &vtype)); 4859 PetscCall(MatSetVecType(B, vtype)); 4860 4861 B->stencil.dim = mat->stencil.dim; 4862 B->stencil.noc = mat->stencil.noc; 4863 for (i = 0; i <= mat->stencil.dim; i++) { 4864 B->stencil.dims[i] = mat->stencil.dims[i]; 4865 B->stencil.starts[i] = mat->stencil.starts[i]; 4866 } 4867 4868 B->nooffproczerorows = mat->nooffproczerorows; 4869 B->nooffprocentries = mat->nooffprocentries; 4870 4871 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm)); 4872 if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm)); 4873 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4874 PetscFunctionReturn(PETSC_SUCCESS); 4875 } 4876 4877 /*@ 4878 MatGetDiagonal - Gets the diagonal of a matrix as a `Vec` 4879 4880 Logically Collective 4881 4882 Input Parameters: 4883 + mat - the matrix 4884 - v - the vector for storing the diagonal 4885 4886 Output Parameter: 4887 . v - the diagonal of the matrix 4888 4889 Level: intermediate 4890 4891 Note: 4892 Currently only correct in parallel for square matrices. 4893 4894 .seealso: `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()` 4895 @*/ 4896 PetscErrorCode MatGetDiagonal(Mat mat, Vec v) 4897 { 4898 PetscFunctionBegin; 4899 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4900 PetscValidType(mat, 1); 4901 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4902 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4903 MatCheckPreallocated(mat, 1); 4904 4905 PetscUseTypeMethod(mat, getdiagonal, v); 4906 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4907 PetscFunctionReturn(PETSC_SUCCESS); 4908 } 4909 4910 /*@C 4911 MatGetRowMin - Gets the minimum value (of the real part) of each 4912 row of the matrix 4913 4914 Logically Collective 4915 4916 Input Parameter: 4917 . mat - the matrix 4918 4919 Output Parameters: 4920 + v - the vector for storing the maximums 4921 - idx - the indices of the column found for each row (optional) 4922 4923 Level: intermediate 4924 4925 Note: 4926 The result of this call are the same as if one converted the matrix to dense format 4927 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 4928 4929 This code is only implemented for a couple of matrix formats. 4930 4931 .seealso: `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, 4932 `MatGetRowMax()` 4933 @*/ 4934 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[]) 4935 { 4936 PetscFunctionBegin; 4937 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4938 PetscValidType(mat, 1); 4939 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4940 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4941 4942 if (!mat->cmap->N) { 4943 PetscCall(VecSet(v, PETSC_MAX_REAL)); 4944 if (idx) { 4945 PetscInt i, m = mat->rmap->n; 4946 for (i = 0; i < m; i++) idx[i] = -1; 4947 } 4948 } else { 4949 MatCheckPreallocated(mat, 1); 4950 } 4951 PetscUseTypeMethod(mat, getrowmin, v, idx); 4952 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4953 PetscFunctionReturn(PETSC_SUCCESS); 4954 } 4955 4956 /*@C 4957 MatGetRowMinAbs - Gets the minimum value (in absolute value) of each 4958 row of the matrix 4959 4960 Logically Collective 4961 4962 Input Parameter: 4963 . mat - the matrix 4964 4965 Output Parameters: 4966 + v - the vector for storing the minimums 4967 - idx - the indices of the column found for each row (or `NULL` if not needed) 4968 4969 Level: intermediate 4970 4971 Notes: 4972 if a row is completely empty or has only 0.0 values then the idx[] value for that 4973 row is 0 (the first column). 4974 4975 This code is only implemented for a couple of matrix formats. 4976 4977 .seealso: `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()` 4978 @*/ 4979 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[]) 4980 { 4981 PetscFunctionBegin; 4982 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4983 PetscValidType(mat, 1); 4984 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4985 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4986 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4987 4988 if (!mat->cmap->N) { 4989 PetscCall(VecSet(v, 0.0)); 4990 if (idx) { 4991 PetscInt i, m = mat->rmap->n; 4992 for (i = 0; i < m; i++) idx[i] = -1; 4993 } 4994 } else { 4995 MatCheckPreallocated(mat, 1); 4996 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 4997 PetscUseTypeMethod(mat, getrowminabs, v, idx); 4998 } 4999 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5000 PetscFunctionReturn(PETSC_SUCCESS); 5001 } 5002 5003 /*@C 5004 MatGetRowMax - Gets the maximum value (of the real part) of each 5005 row of the matrix 5006 5007 Logically Collective 5008 5009 Input Parameter: 5010 . mat - the matrix 5011 5012 Output Parameters: 5013 + v - the vector for storing the maximums 5014 - idx - the indices of the column found for each row (optional) 5015 5016 Level: intermediate 5017 5018 Notes: 5019 The result of this call are the same as if one converted the matrix to dense format 5020 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5021 5022 This code is only implemented for a couple of matrix formats. 5023 5024 .seealso: `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5025 @*/ 5026 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[]) 5027 { 5028 PetscFunctionBegin; 5029 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5030 PetscValidType(mat, 1); 5031 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5032 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5033 5034 if (!mat->cmap->N) { 5035 PetscCall(VecSet(v, PETSC_MIN_REAL)); 5036 if (idx) { 5037 PetscInt i, m = mat->rmap->n; 5038 for (i = 0; i < m; i++) idx[i] = -1; 5039 } 5040 } else { 5041 MatCheckPreallocated(mat, 1); 5042 PetscUseTypeMethod(mat, getrowmax, v, idx); 5043 } 5044 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5045 PetscFunctionReturn(PETSC_SUCCESS); 5046 } 5047 5048 /*@C 5049 MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each 5050 row of the matrix 5051 5052 Logically Collective 5053 5054 Input Parameter: 5055 . mat - the matrix 5056 5057 Output Parameters: 5058 + v - the vector for storing the maximums 5059 - idx - the indices of the column found for each row (or `NULL` if not needed) 5060 5061 Level: intermediate 5062 5063 Notes: 5064 if a row is completely empty or has only 0.0 values then the idx[] value for that 5065 row is 0 (the first column). 5066 5067 This code is only implemented for a couple of matrix formats. 5068 5069 .seealso: `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5070 @*/ 5071 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[]) 5072 { 5073 PetscFunctionBegin; 5074 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5075 PetscValidType(mat, 1); 5076 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5077 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5078 5079 if (!mat->cmap->N) { 5080 PetscCall(VecSet(v, 0.0)); 5081 if (idx) { 5082 PetscInt i, m = mat->rmap->n; 5083 for (i = 0; i < m; i++) idx[i] = -1; 5084 } 5085 } else { 5086 MatCheckPreallocated(mat, 1); 5087 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5088 PetscUseTypeMethod(mat, getrowmaxabs, v, idx); 5089 } 5090 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5091 PetscFunctionReturn(PETSC_SUCCESS); 5092 } 5093 5094 /*@ 5095 MatGetRowSum - Gets the sum of each row of the matrix 5096 5097 Logically or Neighborhood Collective 5098 5099 Input Parameters: 5100 . mat - the matrix 5101 5102 Output Parameter: 5103 . v - the vector for storing the sum of rows 5104 5105 Level: intermediate 5106 5107 Notes: 5108 This code is slow since it is not currently specialized for different formats 5109 5110 .seealso: `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()` 5111 @*/ 5112 PetscErrorCode MatGetRowSum(Mat mat, Vec v) 5113 { 5114 Vec ones; 5115 5116 PetscFunctionBegin; 5117 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5118 PetscValidType(mat, 1); 5119 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5120 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5121 MatCheckPreallocated(mat, 1); 5122 PetscCall(MatCreateVecs(mat, &ones, NULL)); 5123 PetscCall(VecSet(ones, 1.)); 5124 PetscCall(MatMult(mat, ones, v)); 5125 PetscCall(VecDestroy(&ones)); 5126 PetscFunctionReturn(PETSC_SUCCESS); 5127 } 5128 5129 /*@ 5130 MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) 5131 when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B) 5132 5133 Collective 5134 5135 Input Parameter: 5136 . mat - the matrix to provide the transpose 5137 5138 Output Parameter: 5139 . 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 5140 5141 Level: advanced 5142 5143 Note: 5144 Normally the use of `MatTranspose`(A, `MAT_REUSE_MATRIX`, &B) requires that `B` was obtained with a call to `MatTranspose`(A, `MAT_INITIAL_MATRIX`, &B). This 5145 routine allows bypassing that call. 5146 5147 .seealso: `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5148 @*/ 5149 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B) 5150 { 5151 PetscContainer rB = NULL; 5152 MatParentState *rb = NULL; 5153 5154 PetscFunctionBegin; 5155 PetscCall(PetscNew(&rb)); 5156 rb->id = ((PetscObject)mat)->id; 5157 rb->state = 0; 5158 PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate)); 5159 PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB)); 5160 PetscCall(PetscContainerSetPointer(rB, rb)); 5161 PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault)); 5162 PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB)); 5163 PetscCall(PetscObjectDereference((PetscObject)rB)); 5164 PetscFunctionReturn(PETSC_SUCCESS); 5165 } 5166 5167 /*@ 5168 MatTranspose - Computes an in-place or out-of-place transpose of a matrix. 5169 5170 Collective 5171 5172 Input Parameters: 5173 + mat - the matrix to transpose 5174 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5175 5176 Output Parameter: 5177 . B - the transpose 5178 5179 Level: intermediate 5180 5181 Notes: 5182 If you use `MAT_INPLACE_MATRIX` then you must pass in &mat for B 5183 5184 `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 5185 transpose, call `MatTransposeSetPrecursor`(mat,B) before calling this routine. 5186 5187 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. 5188 5189 Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed. 5190 5191 If mat is unchanged from the last call this function returns immediately without recomputing the result 5192 5193 If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()` 5194 5195 .seealso: `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`, 5196 `MatTransposeSymbolic()`, `MatCreateTranspose()` 5197 @*/ 5198 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B) 5199 { 5200 PetscContainer rB = NULL; 5201 MatParentState *rb = NULL; 5202 5203 PetscFunctionBegin; 5204 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5205 PetscValidType(mat, 1); 5206 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5207 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5208 PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first"); 5209 PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX"); 5210 MatCheckPreallocated(mat, 1); 5211 if (reuse == MAT_REUSE_MATRIX) { 5212 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5213 PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor()."); 5214 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5215 PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5216 if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS); 5217 } 5218 5219 PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0)); 5220 if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) { 5221 PetscUseTypeMethod(mat, transpose, reuse, B); 5222 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5223 } 5224 PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0)); 5225 5226 if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B)); 5227 if (reuse != MAT_INPLACE_MATRIX) { 5228 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5229 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5230 rb->state = ((PetscObject)mat)->state; 5231 rb->nonzerostate = mat->nonzerostate; 5232 } 5233 PetscFunctionReturn(PETSC_SUCCESS); 5234 } 5235 5236 /*@ 5237 MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix. 5238 5239 Collective 5240 5241 Input Parameters: 5242 . A - the matrix to transpose 5243 5244 Output Parameter: 5245 . 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 5246 numerical portion. 5247 5248 Level: intermediate 5249 5250 Note: 5251 This is not supported for many matrix types, use `MatTranspose()` in those cases 5252 5253 .seealso: `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5254 @*/ 5255 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B) 5256 { 5257 PetscFunctionBegin; 5258 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5259 PetscValidType(A, 1); 5260 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5261 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5262 PetscCheck(A->ops->transposesymbolic, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 5263 PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0)); 5264 PetscCall((*A->ops->transposesymbolic)(A, B)); 5265 PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0)); 5266 5267 PetscCall(MatTransposeSetPrecursor(A, *B)); 5268 PetscFunctionReturn(PETSC_SUCCESS); 5269 } 5270 5271 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B) 5272 { 5273 PetscContainer rB; 5274 MatParentState *rb; 5275 5276 PetscFunctionBegin; 5277 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5278 PetscValidType(A, 1); 5279 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5280 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5281 PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB)); 5282 PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()"); 5283 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5284 PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5285 PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure"); 5286 PetscFunctionReturn(PETSC_SUCCESS); 5287 } 5288 5289 /*@ 5290 MatIsTranspose - Test whether a matrix is another one's transpose, 5291 or its own, in which case it tests symmetry. 5292 5293 Collective 5294 5295 Input Parameters: 5296 + A - the matrix to test 5297 - B - the matrix to test against, this can equal the first parameter 5298 5299 Output Parameters: 5300 . flg - the result 5301 5302 Level: intermediate 5303 5304 Notes: 5305 Only available for `MATAIJ` matrices. 5306 5307 The sequential algorithm has a running time of the order of the number of nonzeros; the parallel 5308 test involves parallel copies of the block-offdiagonal parts of the matrix. 5309 5310 .seealso: `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()` 5311 @*/ 5312 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5313 { 5314 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5315 5316 PetscFunctionBegin; 5317 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5318 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5319 PetscValidBoolPointer(flg, 4); 5320 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f)); 5321 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g)); 5322 *flg = PETSC_FALSE; 5323 if (f && g) { 5324 PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test"); 5325 PetscCall((*f)(A, B, tol, flg)); 5326 } else { 5327 MatType mattype; 5328 5329 PetscCall(MatGetType(f ? B : A, &mattype)); 5330 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype); 5331 } 5332 PetscFunctionReturn(PETSC_SUCCESS); 5333 } 5334 5335 /*@ 5336 MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate. 5337 5338 Collective 5339 5340 Input Parameters: 5341 + mat - the matrix to transpose and complex conjugate 5342 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5343 5344 Output Parameter: 5345 . B - the Hermitian transpose 5346 5347 Level: intermediate 5348 5349 .seealso: `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse` 5350 @*/ 5351 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B) 5352 { 5353 PetscFunctionBegin; 5354 PetscCall(MatTranspose(mat, reuse, B)); 5355 #if defined(PETSC_USE_COMPLEX) 5356 PetscCall(MatConjugate(*B)); 5357 #endif 5358 PetscFunctionReturn(PETSC_SUCCESS); 5359 } 5360 5361 /*@ 5362 MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose, 5363 5364 Collective 5365 5366 Input Parameters: 5367 + A - the matrix to test 5368 - B - the matrix to test against, this can equal the first parameter 5369 5370 Output Parameters: 5371 . flg - the result 5372 5373 Level: intermediate 5374 5375 Notes: 5376 Only available for `MATAIJ` matrices. 5377 5378 The sequential algorithm 5379 has a running time of the order of the number of nonzeros; the parallel 5380 test involves parallel copies of the block-offdiagonal parts of the matrix. 5381 5382 .seealso: `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()` 5383 @*/ 5384 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5385 { 5386 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5387 5388 PetscFunctionBegin; 5389 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5390 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5391 PetscValidBoolPointer(flg, 4); 5392 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f)); 5393 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g)); 5394 if (f && g) { 5395 PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test"); 5396 PetscCall((*f)(A, B, tol, flg)); 5397 } 5398 PetscFunctionReturn(PETSC_SUCCESS); 5399 } 5400 5401 /*@ 5402 MatPermute - Creates a new matrix with rows and columns permuted from the 5403 original. 5404 5405 Collective 5406 5407 Input Parameters: 5408 + mat - the matrix to permute 5409 . row - row permutation, each processor supplies only the permutation for its rows 5410 - col - column permutation, each processor supplies only the permutation for its columns 5411 5412 Output Parameters: 5413 . B - the permuted matrix 5414 5415 Level: advanced 5416 5417 Note: 5418 The index sets map from row/col of permuted matrix to row/col of original matrix. 5419 The index sets should be on the same communicator as mat and have the same local sizes. 5420 5421 Developer Note: 5422 If you want to implement `MatPermute()` for a matrix type, and your approach doesn't 5423 exploit the fact that row and col are permutations, consider implementing the 5424 more general `MatCreateSubMatrix()` instead. 5425 5426 .seealso: `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()` 5427 @*/ 5428 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B) 5429 { 5430 PetscFunctionBegin; 5431 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5432 PetscValidType(mat, 1); 5433 PetscValidHeaderSpecific(row, IS_CLASSID, 2); 5434 PetscValidHeaderSpecific(col, IS_CLASSID, 3); 5435 PetscValidPointer(B, 4); 5436 PetscCheckSameComm(mat, 1, row, 2); 5437 if (row != col) PetscCheckSameComm(row, 2, col, 3); 5438 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5439 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5440 PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name); 5441 MatCheckPreallocated(mat, 1); 5442 5443 if (mat->ops->permute) { 5444 PetscUseTypeMethod(mat, permute, row, col, B); 5445 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5446 } else { 5447 PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B)); 5448 } 5449 PetscFunctionReturn(PETSC_SUCCESS); 5450 } 5451 5452 /*@ 5453 MatEqual - Compares two matrices. 5454 5455 Collective 5456 5457 Input Parameters: 5458 + A - the first matrix 5459 - B - the second matrix 5460 5461 Output Parameter: 5462 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise. 5463 5464 Level: intermediate 5465 5466 .seealso: `Mat` 5467 @*/ 5468 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg) 5469 { 5470 PetscFunctionBegin; 5471 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5472 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5473 PetscValidType(A, 1); 5474 PetscValidType(B, 2); 5475 PetscValidBoolPointer(flg, 3); 5476 PetscCheckSameComm(A, 1, B, 2); 5477 MatCheckPreallocated(A, 1); 5478 MatCheckPreallocated(B, 2); 5479 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5480 PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5481 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, 5482 B->cmap->N); 5483 if (A->ops->equal && A->ops->equal == B->ops->equal) { 5484 PetscUseTypeMethod(A, equal, B, flg); 5485 } else { 5486 PetscCall(MatMultEqual(A, B, 10, flg)); 5487 } 5488 PetscFunctionReturn(PETSC_SUCCESS); 5489 } 5490 5491 /*@ 5492 MatDiagonalScale - Scales a matrix on the left and right by diagonal 5493 matrices that are stored as vectors. Either of the two scaling 5494 matrices can be `NULL`. 5495 5496 Collective 5497 5498 Input Parameters: 5499 + mat - the matrix to be scaled 5500 . l - the left scaling vector (or `NULL`) 5501 - r - the right scaling vector (or `NULL`) 5502 5503 Level: intermediate 5504 5505 Note: 5506 `MatDiagonalScale()` computes A = LAR, where 5507 L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector) 5508 The L scales the rows of the matrix, the R scales the columns of the matrix. 5509 5510 .seealso: `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()` 5511 @*/ 5512 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r) 5513 { 5514 PetscFunctionBegin; 5515 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5516 PetscValidType(mat, 1); 5517 if (l) { 5518 PetscValidHeaderSpecific(l, VEC_CLASSID, 2); 5519 PetscCheckSameComm(mat, 1, l, 2); 5520 } 5521 if (r) { 5522 PetscValidHeaderSpecific(r, VEC_CLASSID, 3); 5523 PetscCheckSameComm(mat, 1, r, 3); 5524 } 5525 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5526 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5527 MatCheckPreallocated(mat, 1); 5528 if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS); 5529 5530 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5531 PetscUseTypeMethod(mat, diagonalscale, l, r); 5532 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5533 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5534 if (l != r) mat->symmetric = PETSC_BOOL3_FALSE; 5535 PetscFunctionReturn(PETSC_SUCCESS); 5536 } 5537 5538 /*@ 5539 MatScale - Scales all elements of a matrix by a given number. 5540 5541 Logically Collective 5542 5543 Input Parameters: 5544 + mat - the matrix to be scaled 5545 - a - the scaling value 5546 5547 Output Parameter: 5548 . mat - the scaled matrix 5549 5550 Level: intermediate 5551 5552 .seealso: `Mat`, `MatDiagonalScale()` 5553 @*/ 5554 PetscErrorCode MatScale(Mat mat, PetscScalar a) 5555 { 5556 PetscFunctionBegin; 5557 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5558 PetscValidType(mat, 1); 5559 PetscCheck(a == (PetscScalar)1.0 || mat->ops->scale, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 5560 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5561 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5562 PetscValidLogicalCollectiveScalar(mat, a, 2); 5563 MatCheckPreallocated(mat, 1); 5564 5565 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5566 if (a != (PetscScalar)1.0) { 5567 PetscUseTypeMethod(mat, scale, a); 5568 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5569 } 5570 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5571 PetscFunctionReturn(PETSC_SUCCESS); 5572 } 5573 5574 /*@ 5575 MatNorm - Calculates various norms of a matrix. 5576 5577 Collective 5578 5579 Input Parameters: 5580 + mat - the matrix 5581 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY` 5582 5583 Output Parameter: 5584 . nrm - the resulting norm 5585 5586 Level: intermediate 5587 5588 .seealso: `Mat` 5589 @*/ 5590 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm) 5591 { 5592 PetscFunctionBegin; 5593 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5594 PetscValidType(mat, 1); 5595 PetscValidRealPointer(nrm, 3); 5596 5597 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5598 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5599 MatCheckPreallocated(mat, 1); 5600 5601 PetscUseTypeMethod(mat, norm, type, nrm); 5602 PetscFunctionReturn(PETSC_SUCCESS); 5603 } 5604 5605 /* 5606 This variable is used to prevent counting of MatAssemblyBegin() that 5607 are called from within a MatAssemblyEnd(). 5608 */ 5609 static PetscInt MatAssemblyEnd_InUse = 0; 5610 /*@ 5611 MatAssemblyBegin - Begins assembling the matrix. This routine should 5612 be called after completing all calls to `MatSetValues()`. 5613 5614 Collective 5615 5616 Input Parameters: 5617 + mat - the matrix 5618 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5619 5620 Level: beginner 5621 5622 Notes: 5623 `MatSetValues()` generally caches the values that belong to other MPI ranks. The matrix is ready to 5624 use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called. 5625 5626 Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES` 5627 in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before 5628 using the matrix. 5629 5630 ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the 5631 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 5632 a global collective operation requiring all processes that share the matrix. 5633 5634 Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed 5635 out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros 5636 before `MAT_FINAL_ASSEMBLY` so the space is not compressed out. 5637 5638 .seealso: `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()` 5639 @*/ 5640 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type) 5641 { 5642 PetscFunctionBegin; 5643 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5644 PetscValidType(mat, 1); 5645 MatCheckPreallocated(mat, 1); 5646 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?"); 5647 if (mat->assembled) { 5648 mat->was_assembled = PETSC_TRUE; 5649 mat->assembled = PETSC_FALSE; 5650 } 5651 5652 if (!MatAssemblyEnd_InUse) { 5653 PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0)); 5654 PetscTryTypeMethod(mat, assemblybegin, type); 5655 PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0)); 5656 } else PetscTryTypeMethod(mat, assemblybegin, type); 5657 PetscFunctionReturn(PETSC_SUCCESS); 5658 } 5659 5660 /*@ 5661 MatAssembled - Indicates if a matrix has been assembled and is ready for 5662 use; for example, in matrix-vector product. 5663 5664 Not Collective 5665 5666 Input Parameter: 5667 . mat - the matrix 5668 5669 Output Parameter: 5670 . assembled - `PETSC_TRUE` or `PETSC_FALSE` 5671 5672 Level: advanced 5673 5674 .seealso: `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()` 5675 @*/ 5676 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled) 5677 { 5678 PetscFunctionBegin; 5679 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5680 PetscValidBoolPointer(assembled, 2); 5681 *assembled = mat->assembled; 5682 PetscFunctionReturn(PETSC_SUCCESS); 5683 } 5684 5685 /*@ 5686 MatAssemblyEnd - Completes assembling the matrix. This routine should 5687 be called after `MatAssemblyBegin()`. 5688 5689 Collective on Mat 5690 5691 Input Parameters: 5692 + mat - the matrix 5693 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5694 5695 Options Database Keys: 5696 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatEndAssembly()` 5697 . -mat_view ::ascii_info_detail - Prints more detailed info 5698 . -mat_view - Prints matrix in ASCII format 5699 . -mat_view ::ascii_matlab - Prints matrix in Matlab format 5700 . -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 5701 . -display <name> - Sets display name (default is host) 5702 . -draw_pause <sec> - Sets number of seconds to pause after display 5703 . -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See [Using MATLAB with PETSc](ch_matlab)) 5704 . -viewer_socket_machine <machine> - Machine to use for socket 5705 . -viewer_socket_port <port> - Port number to use for socket 5706 - -mat_view binary:filename[:append] - Save matrix to file in binary format 5707 5708 Level: beginner 5709 5710 .seealso: `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()` 5711 @*/ 5712 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type) 5713 { 5714 static PetscInt inassm = 0; 5715 PetscBool flg = PETSC_FALSE; 5716 5717 PetscFunctionBegin; 5718 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5719 PetscValidType(mat, 1); 5720 5721 inassm++; 5722 MatAssemblyEnd_InUse++; 5723 if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */ 5724 PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0)); 5725 PetscTryTypeMethod(mat, assemblyend, type); 5726 PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0)); 5727 } else PetscTryTypeMethod(mat, assemblyend, type); 5728 5729 /* Flush assembly is not a true assembly */ 5730 if (type != MAT_FLUSH_ASSEMBLY) { 5731 if (mat->num_ass) { 5732 if (!mat->symmetry_eternal) { 5733 mat->symmetric = PETSC_BOOL3_UNKNOWN; 5734 mat->hermitian = PETSC_BOOL3_UNKNOWN; 5735 } 5736 if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN; 5737 if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN; 5738 } 5739 mat->num_ass++; 5740 mat->assembled = PETSC_TRUE; 5741 mat->ass_nonzerostate = mat->nonzerostate; 5742 } 5743 5744 mat->insertmode = NOT_SET_VALUES; 5745 MatAssemblyEnd_InUse--; 5746 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5747 if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) { 5748 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 5749 5750 if (mat->checksymmetryonassembly) { 5751 PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg)); 5752 if (flg) { 5753 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5754 } else { 5755 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5756 } 5757 } 5758 if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL)); 5759 } 5760 inassm--; 5761 PetscFunctionReturn(PETSC_SUCCESS); 5762 } 5763 5764 /*@ 5765 MatSetOption - Sets a parameter option for a matrix. Some options 5766 may be specific to certain storage formats. Some options 5767 determine how values will be inserted (or added). Sorted, 5768 row-oriented input will generally assemble the fastest. The default 5769 is row-oriented. 5770 5771 Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption` 5772 5773 Input Parameters: 5774 + mat - the matrix 5775 . option - the option, one of those listed below (and possibly others), 5776 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5777 5778 Options Describing Matrix Structure: 5779 + `MAT_SPD` - symmetric positive definite 5780 . `MAT_SYMMETRIC` - symmetric in terms of both structure and value 5781 . `MAT_HERMITIAN` - transpose is the complex conjugation 5782 . `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure 5783 . `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix 5784 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix 5785 - `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix 5786 5787 These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they 5788 do not need to be computed (usually at a high cost) 5789 5790 Options For Use with `MatSetValues()`: 5791 Insert a logically dense subblock, which can be 5792 . `MAT_ROW_ORIENTED` - row-oriented (default) 5793 5794 Note these options reflect the data you pass in with `MatSetValues()`; it has 5795 nothing to do with how the data is stored internally in the matrix 5796 data structure. 5797 5798 When (re)assembling a matrix, we can restrict the input for 5799 efficiency/debugging purposes. These options include 5800 + `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow) 5801 . `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated 5802 . `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries 5803 . `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry 5804 . `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly 5805 . `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if 5806 any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves 5807 performance for very large process counts. 5808 - `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset 5809 of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly 5810 functions, instead sending only neighbor messages. 5811 5812 Level: intermediate 5813 5814 Notes: 5815 Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg! 5816 5817 Some options are relevant only for particular matrix types and 5818 are thus ignored by others. Other options are not supported by 5819 certain matrix types and will generate an error message if set. 5820 5821 If using Fortran to compute a matrix, one may need to 5822 use the column-oriented option (or convert to the row-oriented 5823 format). 5824 5825 `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion 5826 that would generate a new entry in the nonzero structure is instead 5827 ignored. Thus, if memory has not already been allocated for this particular 5828 data, then the insertion is ignored. For dense matrices, in which 5829 the entire array is allocated, no entries are ever ignored. 5830 Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction 5831 5832 `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion 5833 that would generate a new entry in the nonzero structure instead produces 5834 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 5835 5836 `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion 5837 that would generate a new entry that has not been preallocated will 5838 instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats 5839 only.) This is a useful flag when debugging matrix memory preallocation. 5840 If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 5841 5842 `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for 5843 other processors should be dropped, rather than stashed. 5844 This is useful if you know that the "owning" processor is also 5845 always generating the correct matrix entries, so that PETSc need 5846 not transfer duplicate entries generated on another processor. 5847 5848 `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the 5849 searches during matrix assembly. When this flag is set, the hash table 5850 is created during the first matrix assembly. This hash table is 5851 used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()` 5852 to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag 5853 should be used with `MAT_USE_HASH_TABLE` flag. This option is currently 5854 supported by `MATMPIBAIJ` format only. 5855 5856 `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries 5857 are kept in the nonzero structure 5858 5859 `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating 5860 a zero location in the matrix 5861 5862 `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types 5863 5864 `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the 5865 zero row routines and thus improves performance for very large process counts. 5866 5867 `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular 5868 part of the matrix (since they should match the upper triangular part). 5869 5870 `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a 5871 single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common 5872 with finite difference schemes with non-periodic boundary conditions. 5873 5874 Developer Note: 5875 `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other 5876 places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRIC` or `MAT_SPD` would need to be changed back 5877 to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had 5878 not changed. 5879 5880 .seealso: `MatOption`, `Mat`, `MatGetOption()` 5881 @*/ 5882 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg) 5883 { 5884 PetscFunctionBegin; 5885 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5886 if (op > 0) { 5887 PetscValidLogicalCollectiveEnum(mat, op, 2); 5888 PetscValidLogicalCollectiveBool(mat, flg, 3); 5889 } 5890 5891 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); 5892 5893 switch (op) { 5894 case MAT_FORCE_DIAGONAL_ENTRIES: 5895 mat->force_diagonals = flg; 5896 PetscFunctionReturn(PETSC_SUCCESS); 5897 case MAT_NO_OFF_PROC_ENTRIES: 5898 mat->nooffprocentries = flg; 5899 PetscFunctionReturn(PETSC_SUCCESS); 5900 case MAT_SUBSET_OFF_PROC_ENTRIES: 5901 mat->assembly_subset = flg; 5902 if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */ 5903 #if !defined(PETSC_HAVE_MPIUNI) 5904 PetscCall(MatStashScatterDestroy_BTS(&mat->stash)); 5905 #endif 5906 mat->stash.first_assembly_done = PETSC_FALSE; 5907 } 5908 PetscFunctionReturn(PETSC_SUCCESS); 5909 case MAT_NO_OFF_PROC_ZERO_ROWS: 5910 mat->nooffproczerorows = flg; 5911 PetscFunctionReturn(PETSC_SUCCESS); 5912 case MAT_SPD: 5913 if (flg) { 5914 mat->spd = PETSC_BOOL3_TRUE; 5915 mat->symmetric = PETSC_BOOL3_TRUE; 5916 mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5917 } else { 5918 mat->spd = PETSC_BOOL3_FALSE; 5919 } 5920 break; 5921 case MAT_SYMMETRIC: 5922 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5923 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5924 #if !defined(PETSC_USE_COMPLEX) 5925 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5926 #endif 5927 break; 5928 case MAT_HERMITIAN: 5929 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5930 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5931 #if !defined(PETSC_USE_COMPLEX) 5932 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5933 #endif 5934 break; 5935 case MAT_STRUCTURALLY_SYMMETRIC: 5936 mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5937 break; 5938 case MAT_SYMMETRY_ETERNAL: 5939 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"); 5940 mat->symmetry_eternal = flg; 5941 if (flg) mat->structural_symmetry_eternal = PETSC_TRUE; 5942 break; 5943 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 5944 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"); 5945 mat->structural_symmetry_eternal = flg; 5946 break; 5947 case MAT_SPD_ETERNAL: 5948 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"); 5949 mat->spd_eternal = flg; 5950 if (flg) { 5951 mat->structural_symmetry_eternal = PETSC_TRUE; 5952 mat->symmetry_eternal = PETSC_TRUE; 5953 } 5954 break; 5955 case MAT_STRUCTURE_ONLY: 5956 mat->structure_only = flg; 5957 break; 5958 case MAT_SORTED_FULL: 5959 mat->sortedfull = flg; 5960 break; 5961 default: 5962 break; 5963 } 5964 PetscTryTypeMethod(mat, setoption, op, flg); 5965 PetscFunctionReturn(PETSC_SUCCESS); 5966 } 5967 5968 /*@ 5969 MatGetOption - Gets a parameter option that has been set for a matrix. 5970 5971 Logically Collective 5972 5973 Input Parameters: 5974 + mat - the matrix 5975 - option - the option, this only responds to certain options, check the code for which ones 5976 5977 Output Parameter: 5978 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5979 5980 Level: intermediate 5981 5982 Notes: 5983 Can only be called after `MatSetSizes()` and `MatSetType()` have been set. 5984 5985 Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or 5986 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 5987 5988 .seealso: `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, 5989 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 5990 @*/ 5991 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg) 5992 { 5993 PetscFunctionBegin; 5994 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5995 PetscValidType(mat, 1); 5996 5997 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); 5998 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()"); 5999 6000 switch (op) { 6001 case MAT_NO_OFF_PROC_ENTRIES: 6002 *flg = mat->nooffprocentries; 6003 break; 6004 case MAT_NO_OFF_PROC_ZERO_ROWS: 6005 *flg = mat->nooffproczerorows; 6006 break; 6007 case MAT_SYMMETRIC: 6008 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()"); 6009 break; 6010 case MAT_HERMITIAN: 6011 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()"); 6012 break; 6013 case MAT_STRUCTURALLY_SYMMETRIC: 6014 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()"); 6015 break; 6016 case MAT_SPD: 6017 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()"); 6018 break; 6019 case MAT_SYMMETRY_ETERNAL: 6020 *flg = mat->symmetry_eternal; 6021 break; 6022 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6023 *flg = mat->symmetry_eternal; 6024 break; 6025 default: 6026 break; 6027 } 6028 PetscFunctionReturn(PETSC_SUCCESS); 6029 } 6030 6031 /*@ 6032 MatZeroEntries - Zeros all entries of a matrix. For sparse matrices 6033 this routine retains the old nonzero structure. 6034 6035 Logically Collective 6036 6037 Input Parameters: 6038 . mat - the matrix 6039 6040 Level: intermediate 6041 6042 Note: 6043 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. 6044 See the Performance chapter of the users manual for information on preallocating matrices. 6045 6046 .seealso: `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()` 6047 @*/ 6048 PetscErrorCode MatZeroEntries(Mat mat) 6049 { 6050 PetscFunctionBegin; 6051 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6052 PetscValidType(mat, 1); 6053 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6054 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"); 6055 MatCheckPreallocated(mat, 1); 6056 6057 PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0)); 6058 PetscUseTypeMethod(mat, zeroentries); 6059 PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0)); 6060 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6061 PetscFunctionReturn(PETSC_SUCCESS); 6062 } 6063 6064 /*@ 6065 MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal) 6066 of a set of rows and columns of a matrix. 6067 6068 Collective 6069 6070 Input Parameters: 6071 + mat - the matrix 6072 . numRows - the number of rows/columns to zero 6073 . rows - the global row indices 6074 . diag - value put in the diagonal of the eliminated rows 6075 . x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call 6076 - b - optional vector of the right hand side, that will be adjusted by provided solution entries 6077 6078 Level: intermediate 6079 6080 Notes: 6081 This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6082 6083 For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`. 6084 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 6085 6086 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6087 Krylov method to take advantage of the known solution on the zeroed rows. 6088 6089 For the parallel case, all processes that share the matrix (i.e., 6090 those in the communicator used for matrix creation) MUST call this 6091 routine, regardless of whether any rows being zeroed are owned by 6092 them. 6093 6094 Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix. 6095 6096 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6097 list only rows local to itself). 6098 6099 The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine. 6100 6101 .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6102 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6103 @*/ 6104 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6105 { 6106 PetscFunctionBegin; 6107 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6108 PetscValidType(mat, 1); 6109 if (numRows) PetscValidIntPointer(rows, 3); 6110 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6111 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6112 MatCheckPreallocated(mat, 1); 6113 6114 PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b); 6115 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6116 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6117 PetscFunctionReturn(PETSC_SUCCESS); 6118 } 6119 6120 /*@ 6121 MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal) 6122 of a set of rows and columns of a matrix. 6123 6124 Collective 6125 6126 Input Parameters: 6127 + mat - the matrix 6128 . is - the rows to zero 6129 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6130 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6131 - b - optional vector of right hand side, that will be adjusted by provided solution 6132 6133 Level: intermediate 6134 6135 Note: 6136 See `MatZeroRowsColumns()` for details on how this routine operates. 6137 6138 .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6139 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()` 6140 @*/ 6141 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6142 { 6143 PetscInt numRows; 6144 const PetscInt *rows; 6145 6146 PetscFunctionBegin; 6147 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6148 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6149 PetscValidType(mat, 1); 6150 PetscValidType(is, 2); 6151 PetscCall(ISGetLocalSize(is, &numRows)); 6152 PetscCall(ISGetIndices(is, &rows)); 6153 PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b)); 6154 PetscCall(ISRestoreIndices(is, &rows)); 6155 PetscFunctionReturn(PETSC_SUCCESS); 6156 } 6157 6158 /*@ 6159 MatZeroRows - Zeros all entries (except possibly the main diagonal) 6160 of a set of rows of a matrix. 6161 6162 Collective 6163 6164 Input Parameters: 6165 + mat - the matrix 6166 . numRows - the number of rows to zero 6167 . rows - the global row indices 6168 . diag - value put in the diagonal of the zeroed rows 6169 . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call 6170 - b - optional vector of right hand side, that will be adjusted by provided solution entries 6171 6172 Level: intermediate 6173 6174 Notes: 6175 This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6176 6177 For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`. 6178 6179 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6180 Krylov method to take advantage of the known solution on the zeroed rows. 6181 6182 May be followed by using a `PC` of type `PCREDISTRIBUTE` to solve the reduced problem (`PCDISTRIBUTE` completely eliminates the zeroed rows and their corresponding columns) 6183 from the matrix. 6184 6185 Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix 6186 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 6187 formats this does not alter the nonzero structure. 6188 6189 If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure 6190 of the matrix is not changed the values are 6191 merely zeroed. 6192 6193 The user can set a value in the diagonal entry (or for the `MATAIJ` format 6194 formats can optionally remove the main diagonal entry from the 6195 nonzero structure as well, by passing 0.0 as the final argument). 6196 6197 For the parallel case, all processes that share the matrix (i.e., 6198 those in the communicator used for matrix creation) MUST call this 6199 routine, regardless of whether any rows being zeroed are owned by 6200 them. 6201 6202 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6203 list only rows local to itself). 6204 6205 You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it 6206 owns that are to be zeroed. This saves a global synchronization in the implementation. 6207 6208 .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6209 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE` 6210 @*/ 6211 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6212 { 6213 PetscFunctionBegin; 6214 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6215 PetscValidType(mat, 1); 6216 if (numRows) PetscValidIntPointer(rows, 3); 6217 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6218 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6219 MatCheckPreallocated(mat, 1); 6220 6221 PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b); 6222 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6223 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6224 PetscFunctionReturn(PETSC_SUCCESS); 6225 } 6226 6227 /*@ 6228 MatZeroRowsIS - Zeros all entries (except possibly the main diagonal) 6229 of a set of rows of a matrix. 6230 6231 Collective on Mat 6232 6233 Input Parameters: 6234 + mat - the matrix 6235 . is - index set of rows to remove (if `NULL` then no row is removed) 6236 . diag - value put in all diagonals of eliminated rows 6237 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6238 - b - optional vector of right hand side, that will be adjusted by provided solution 6239 6240 Level: intermediate 6241 6242 Note: 6243 See `MatZeroRows()` for details on how this routine operates. 6244 6245 .seealso: `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6246 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6247 @*/ 6248 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6249 { 6250 PetscInt numRows = 0; 6251 const PetscInt *rows = NULL; 6252 6253 PetscFunctionBegin; 6254 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6255 PetscValidType(mat, 1); 6256 if (is) { 6257 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6258 PetscCall(ISGetLocalSize(is, &numRows)); 6259 PetscCall(ISGetIndices(is, &rows)); 6260 } 6261 PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b)); 6262 if (is) PetscCall(ISRestoreIndices(is, &rows)); 6263 PetscFunctionReturn(PETSC_SUCCESS); 6264 } 6265 6266 /*@ 6267 MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal) 6268 of a set of rows of a matrix. These rows must be local to the process. 6269 6270 Collective 6271 6272 Input Parameters: 6273 + mat - the matrix 6274 . numRows - the number of rows to remove 6275 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6276 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6277 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6278 - b - optional vector of right hand side, that will be adjusted by provided solution 6279 6280 Level: intermediate 6281 6282 Notes: 6283 See `MatZeroRows()` for details on how this routine operates. 6284 6285 The grid coordinates are across the entire grid, not just the local portion 6286 6287 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6288 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6289 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6290 `DM_BOUNDARY_PERIODIC` boundary type. 6291 6292 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 6293 a single value per point) you can skip filling those indices. 6294 6295 Fortran Note: 6296 idxm and idxn should be declared as 6297 $ MatStencil idxm(4,m) 6298 and the values inserted using 6299 .vb 6300 idxm(MatStencil_i,1) = i 6301 idxm(MatStencil_j,1) = j 6302 idxm(MatStencil_k,1) = k 6303 idxm(MatStencil_c,1) = c 6304 etc 6305 .ve 6306 6307 .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6308 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6309 @*/ 6310 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6311 { 6312 PetscInt dim = mat->stencil.dim; 6313 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6314 PetscInt *dims = mat->stencil.dims + 1; 6315 PetscInt *starts = mat->stencil.starts; 6316 PetscInt *dxm = (PetscInt *)rows; 6317 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6318 6319 PetscFunctionBegin; 6320 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6321 PetscValidType(mat, 1); 6322 if (numRows) PetscValidPointer(rows, 3); 6323 6324 PetscCall(PetscMalloc1(numRows, &jdxm)); 6325 for (i = 0; i < numRows; ++i) { 6326 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6327 for (j = 0; j < 3 - sdim; ++j) dxm++; 6328 /* Local index in X dir */ 6329 tmp = *dxm++ - starts[0]; 6330 /* Loop over remaining dimensions */ 6331 for (j = 0; j < dim - 1; ++j) { 6332 /* If nonlocal, set index to be negative */ 6333 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6334 /* Update local index */ 6335 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6336 } 6337 /* Skip component slot if necessary */ 6338 if (mat->stencil.noc) dxm++; 6339 /* Local row number */ 6340 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6341 } 6342 PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b)); 6343 PetscCall(PetscFree(jdxm)); 6344 PetscFunctionReturn(PETSC_SUCCESS); 6345 } 6346 6347 /*@ 6348 MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal) 6349 of a set of rows and columns of a matrix. 6350 6351 Collective 6352 6353 Input Parameters: 6354 + mat - the matrix 6355 . numRows - the number of rows/columns to remove 6356 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6357 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6358 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6359 - b - optional vector of right hand side, that will be adjusted by provided solution 6360 6361 Level: intermediate 6362 6363 Notes: 6364 See `MatZeroRowsColumns()` for details on how this routine operates. 6365 6366 The grid coordinates are across the entire grid, not just the local portion 6367 6368 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6369 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6370 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6371 `DM_BOUNDARY_PERIODIC` boundary type. 6372 6373 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 6374 a single value per point) you can skip filling those indices. 6375 6376 Fortran Note: 6377 In Fortran idxm and idxn should be declared as 6378 $ MatStencil idxm(4,m) 6379 and the values inserted using 6380 .vb 6381 idxm(MatStencil_i,1) = i 6382 idxm(MatStencil_j,1) = j 6383 idxm(MatStencil_k,1) = k 6384 idxm(MatStencil_c,1) = c 6385 etc 6386 .ve 6387 6388 .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6389 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()` 6390 @*/ 6391 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6392 { 6393 PetscInt dim = mat->stencil.dim; 6394 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6395 PetscInt *dims = mat->stencil.dims + 1; 6396 PetscInt *starts = mat->stencil.starts; 6397 PetscInt *dxm = (PetscInt *)rows; 6398 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6399 6400 PetscFunctionBegin; 6401 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6402 PetscValidType(mat, 1); 6403 if (numRows) PetscValidPointer(rows, 3); 6404 6405 PetscCall(PetscMalloc1(numRows, &jdxm)); 6406 for (i = 0; i < numRows; ++i) { 6407 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6408 for (j = 0; j < 3 - sdim; ++j) dxm++; 6409 /* Local index in X dir */ 6410 tmp = *dxm++ - starts[0]; 6411 /* Loop over remaining dimensions */ 6412 for (j = 0; j < dim - 1; ++j) { 6413 /* If nonlocal, set index to be negative */ 6414 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6415 /* Update local index */ 6416 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6417 } 6418 /* Skip component slot if necessary */ 6419 if (mat->stencil.noc) dxm++; 6420 /* Local row number */ 6421 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6422 } 6423 PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b)); 6424 PetscCall(PetscFree(jdxm)); 6425 PetscFunctionReturn(PETSC_SUCCESS); 6426 } 6427 6428 /*@C 6429 MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal) 6430 of a set of rows of a matrix; using local numbering of rows. 6431 6432 Collective 6433 6434 Input Parameters: 6435 + mat - the matrix 6436 . numRows - the number of rows to remove 6437 . rows - the local row indices 6438 . diag - value put in all diagonals of eliminated rows 6439 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6440 - b - optional vector of right hand side, that will be adjusted by provided solution 6441 6442 Level: intermediate 6443 6444 Notes: 6445 Before calling `MatZeroRowsLocal()`, the user must first set the 6446 local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`. 6447 6448 See `MatZeroRows()` for details on how this routine operates. 6449 6450 .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`, 6451 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6452 @*/ 6453 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6454 { 6455 PetscFunctionBegin; 6456 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6457 PetscValidType(mat, 1); 6458 if (numRows) PetscValidIntPointer(rows, 3); 6459 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6460 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6461 MatCheckPreallocated(mat, 1); 6462 6463 if (mat->ops->zerorowslocal) { 6464 PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b); 6465 } else { 6466 IS is, newis; 6467 const PetscInt *newRows; 6468 6469 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6470 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6471 PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis)); 6472 PetscCall(ISGetIndices(newis, &newRows)); 6473 PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b); 6474 PetscCall(ISRestoreIndices(newis, &newRows)); 6475 PetscCall(ISDestroy(&newis)); 6476 PetscCall(ISDestroy(&is)); 6477 } 6478 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6479 PetscFunctionReturn(PETSC_SUCCESS); 6480 } 6481 6482 /*@ 6483 MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal) 6484 of a set of rows of a matrix; using local numbering of rows. 6485 6486 Collective 6487 6488 Input Parameters: 6489 + mat - the matrix 6490 . is - index set of rows to remove 6491 . diag - value put in all diagonals of eliminated rows 6492 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6493 - b - optional vector of right hand side, that will be adjusted by provided solution 6494 6495 Level: intermediate 6496 6497 Notes: 6498 Before calling `MatZeroRowsLocalIS()`, the user must first set the 6499 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6500 6501 See `MatZeroRows()` for details on how this routine operates. 6502 6503 .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6504 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6505 @*/ 6506 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6507 { 6508 PetscInt numRows; 6509 const PetscInt *rows; 6510 6511 PetscFunctionBegin; 6512 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6513 PetscValidType(mat, 1); 6514 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6515 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6516 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6517 MatCheckPreallocated(mat, 1); 6518 6519 PetscCall(ISGetLocalSize(is, &numRows)); 6520 PetscCall(ISGetIndices(is, &rows)); 6521 PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b)); 6522 PetscCall(ISRestoreIndices(is, &rows)); 6523 PetscFunctionReturn(PETSC_SUCCESS); 6524 } 6525 6526 /*@ 6527 MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal) 6528 of a set of rows and columns of a matrix; using local numbering of rows. 6529 6530 Collective 6531 6532 Input Parameters: 6533 + mat - the matrix 6534 . numRows - the number of rows to remove 6535 . rows - the global row indices 6536 . diag - value put in all diagonals of eliminated rows 6537 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6538 - b - optional vector of right hand side, that will be adjusted by provided solution 6539 6540 Level: intermediate 6541 6542 Notes: 6543 Before calling `MatZeroRowsColumnsLocal()`, the user must first set the 6544 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6545 6546 See `MatZeroRowsColumns()` for details on how this routine operates. 6547 6548 .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6549 `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6550 @*/ 6551 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6552 { 6553 IS is, newis; 6554 const PetscInt *newRows; 6555 6556 PetscFunctionBegin; 6557 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6558 PetscValidType(mat, 1); 6559 if (numRows) PetscValidIntPointer(rows, 3); 6560 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6561 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6562 MatCheckPreallocated(mat, 1); 6563 6564 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6565 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6566 PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis)); 6567 PetscCall(ISGetIndices(newis, &newRows)); 6568 PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b); 6569 PetscCall(ISRestoreIndices(newis, &newRows)); 6570 PetscCall(ISDestroy(&newis)); 6571 PetscCall(ISDestroy(&is)); 6572 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6573 PetscFunctionReturn(PETSC_SUCCESS); 6574 } 6575 6576 /*@ 6577 MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal) 6578 of a set of rows and columns of a matrix; using local numbering of rows. 6579 6580 Collective on Mat 6581 6582 Input Parameters: 6583 + mat - the matrix 6584 . is - index set of rows to remove 6585 . diag - value put in all diagonals of eliminated rows 6586 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6587 - b - optional vector of right hand side, that will be adjusted by provided solution 6588 6589 Level: intermediate 6590 6591 Notes: 6592 Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the 6593 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6594 6595 See `MatZeroRowsColumns()` for details on how this routine operates. 6596 6597 .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6598 `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6599 @*/ 6600 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6601 { 6602 PetscInt numRows; 6603 const PetscInt *rows; 6604 6605 PetscFunctionBegin; 6606 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6607 PetscValidType(mat, 1); 6608 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6609 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6610 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6611 MatCheckPreallocated(mat, 1); 6612 6613 PetscCall(ISGetLocalSize(is, &numRows)); 6614 PetscCall(ISGetIndices(is, &rows)); 6615 PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b)); 6616 PetscCall(ISRestoreIndices(is, &rows)); 6617 PetscFunctionReturn(PETSC_SUCCESS); 6618 } 6619 6620 /*@C 6621 MatGetSize - Returns the numbers of rows and columns in a matrix. 6622 6623 Not Collective 6624 6625 Input Parameter: 6626 . mat - the matrix 6627 6628 Level: beginner 6629 6630 Output Parameters: 6631 + m - the number of global rows 6632 - n - the number of global columns 6633 6634 Note: 6635 Both output parameters can be `NULL` on input. 6636 6637 .seealso: `Mat`, `MatSetSizes()`, `MatGetLocalSize()` 6638 @*/ 6639 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n) 6640 { 6641 PetscFunctionBegin; 6642 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6643 if (m) *m = mat->rmap->N; 6644 if (n) *n = mat->cmap->N; 6645 PetscFunctionReturn(PETSC_SUCCESS); 6646 } 6647 6648 /*@C 6649 MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns 6650 of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`. 6651 6652 Not Collective 6653 6654 Input Parameter: 6655 . mat - the matrix 6656 6657 Output Parameters: 6658 + m - the number of local rows, use `NULL` to not obtain this value 6659 - n - the number of local columns, use `NULL` to not obtain this value 6660 6661 Level: beginner 6662 6663 .seealso: `Mat`, `MatSetSizes()`, `MatGetSize()` 6664 @*/ 6665 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n) 6666 { 6667 PetscFunctionBegin; 6668 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6669 if (m) PetscValidIntPointer(m, 2); 6670 if (n) PetscValidIntPointer(n, 3); 6671 if (m) *m = mat->rmap->n; 6672 if (n) *n = mat->cmap->n; 6673 PetscFunctionReturn(PETSC_SUCCESS); 6674 } 6675 6676 /*@C 6677 MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by 6678 this processor. (The columns of the "diagonal block" for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts. 6679 6680 Not Collective, unless matrix has not been allocated, then collective 6681 6682 Input Parameter: 6683 . mat - the matrix 6684 6685 Output Parameters: 6686 + m - the global index of the first local column, use `NULL` to not obtain this value 6687 - n - one more than the global index of the last local column, use `NULL` to not obtain this value 6688 6689 Level: developer 6690 6691 .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout` 6692 @*/ 6693 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n) 6694 { 6695 PetscFunctionBegin; 6696 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6697 PetscValidType(mat, 1); 6698 if (m) PetscValidIntPointer(m, 2); 6699 if (n) PetscValidIntPointer(n, 3); 6700 MatCheckPreallocated(mat, 1); 6701 if (m) *m = mat->cmap->rstart; 6702 if (n) *n = mat->cmap->rend; 6703 PetscFunctionReturn(PETSC_SUCCESS); 6704 } 6705 6706 /*@C 6707 MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6708 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 6709 vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts 6710 6711 Not Collective 6712 6713 Input Parameter: 6714 . mat - the matrix 6715 6716 Output Parameters: 6717 + m - the global index of the first local row, use `NULL` to not obtain this value 6718 - n - one more than the global index of the last local row, use `NULL` to not obtain this value 6719 6720 Level: beginner 6721 6722 Note: 6723 This function requires that the matrix be preallocated. If you have not preallocated, consider using 6724 `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N) 6725 and then `MPI_Scan()` to calculate prefix sums of the local sizes. 6726 6727 .seealso: `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, 6728 `PetscLayout` 6729 @*/ 6730 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n) 6731 { 6732 PetscFunctionBegin; 6733 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6734 PetscValidType(mat, 1); 6735 if (m) PetscValidIntPointer(m, 2); 6736 if (n) PetscValidIntPointer(n, 3); 6737 MatCheckPreallocated(mat, 1); 6738 if (m) *m = mat->rmap->rstart; 6739 if (n) *n = mat->rmap->rend; 6740 PetscFunctionReturn(PETSC_SUCCESS); 6741 } 6742 6743 /*@C 6744 MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6745 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 6746 vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts 6747 6748 Not Collective, unless matrix has not been allocated, then collective 6749 6750 Input Parameters: 6751 . mat - the matrix 6752 6753 Output Parameters: 6754 . ranges - start of each processors portion plus one more than the total length at the end 6755 6756 Level: beginner 6757 6758 .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout` 6759 @*/ 6760 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges) 6761 { 6762 PetscFunctionBegin; 6763 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6764 PetscValidType(mat, 1); 6765 MatCheckPreallocated(mat, 1); 6766 PetscCall(PetscLayoutGetRanges(mat->rmap, ranges)); 6767 PetscFunctionReturn(PETSC_SUCCESS); 6768 } 6769 6770 /*@C 6771 MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by 6772 each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts. 6773 6774 Not Collective, unless matrix has not been allocated, then collective on Mat 6775 6776 Input Parameters: 6777 . mat - the matrix 6778 6779 Output Parameters: 6780 . ranges - start of each processors portion plus one more then the total length at the end 6781 6782 Level: beginner 6783 6784 .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()` 6785 @*/ 6786 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges) 6787 { 6788 PetscFunctionBegin; 6789 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6790 PetscValidType(mat, 1); 6791 MatCheckPreallocated(mat, 1); 6792 PetscCall(PetscLayoutGetRanges(mat->cmap, ranges)); 6793 PetscFunctionReturn(PETSC_SUCCESS); 6794 } 6795 6796 /*@C 6797 MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this 6798 corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership 6799 is more complicated. See :any:`<sec_matlayout>` for details on matrix layouts. 6800 6801 Not Collective 6802 6803 Input Parameter: 6804 . A - matrix 6805 6806 Output Parameters: 6807 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value 6808 - cols - columns in which this process owns elements, use `NULL` to not obtain this value 6809 6810 Level: intermediate 6811 6812 .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK`` 6813 @*/ 6814 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols) 6815 { 6816 PetscErrorCode (*f)(Mat, IS *, IS *); 6817 6818 PetscFunctionBegin; 6819 MatCheckPreallocated(A, 1); 6820 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f)); 6821 if (f) { 6822 PetscCall((*f)(A, rows, cols)); 6823 } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */ 6824 if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows)); 6825 if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols)); 6826 } 6827 PetscFunctionReturn(PETSC_SUCCESS); 6828 } 6829 6830 /*@C 6831 MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()` 6832 Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()` 6833 to complete the factorization. 6834 6835 Collective on fact 6836 6837 Input Parameters: 6838 + fact - the factorized matrix obtained with `MatGetFactor()` 6839 . mat - the matrix 6840 . row - row permutation 6841 . column - column permutation 6842 - info - structure containing 6843 .vb 6844 levels - number of levels of fill. 6845 expected fill - as ratio of original fill. 6846 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 6847 missing diagonal entries) 6848 .ve 6849 6850 Output Parameters: 6851 . fact - new matrix that has been symbolically factored 6852 6853 Level: developer 6854 6855 Notes: 6856 See [Matrix Factorization](sec_matfactor) for additional information. 6857 6858 Most users should employ the `KSP` interface for linear solvers 6859 instead of working directly with matrix algebra routines such as this. 6860 See, e.g., `KSPCreate()`. 6861 6862 Uses the definition of level of fill as in Y. Saad, 2003 6863 6864 Developer Note: 6865 The Fortran interface is not autogenerated as the 6866 interface definition cannot be generated correctly [due to `MatFactorInfo`] 6867 6868 References: 6869 . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003 6870 6871 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 6872 `MatGetOrdering()`, `MatFactorInfo` 6873 @*/ 6874 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 6875 { 6876 PetscFunctionBegin; 6877 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 6878 PetscValidType(mat, 2); 6879 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 6880 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 6881 PetscValidPointer(info, 5); 6882 PetscValidPointer(fact, 1); 6883 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels); 6884 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 6885 if (!fact->ops->ilufactorsymbolic) { 6886 MatSolverType stype; 6887 PetscCall(MatFactorGetSolverType(fact, &stype)); 6888 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ILU using solver type %s", ((PetscObject)mat)->type_name, stype); 6889 } 6890 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6891 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6892 MatCheckPreallocated(mat, 2); 6893 6894 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0)); 6895 PetscCall((fact->ops->ilufactorsymbolic)(fact, mat, row, col, info)); 6896 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0)); 6897 PetscFunctionReturn(PETSC_SUCCESS); 6898 } 6899 6900 /*@C 6901 MatICCFactorSymbolic - Performs symbolic incomplete 6902 Cholesky factorization for a symmetric matrix. Use 6903 `MatCholeskyFactorNumeric()` to complete the factorization. 6904 6905 Collective on fact 6906 6907 Input Parameters: 6908 + fact - the factorized matrix obtained with `MatGetFactor()` 6909 . mat - the matrix to be factored 6910 . perm - row and column permutation 6911 - info - structure containing 6912 .vb 6913 levels - number of levels of fill. 6914 expected fill - as ratio of original fill. 6915 .ve 6916 6917 Output Parameter: 6918 . fact - the factored matrix 6919 6920 Level: developer 6921 6922 Notes: 6923 Most users should employ the `KSP` interface for linear solvers 6924 instead of working directly with matrix algebra routines such as this. 6925 See, e.g., `KSPCreate()`. 6926 6927 This uses the definition of level of fill as in Y. Saad, 2003 6928 6929 Developer Note: 6930 The Fortran interface is not autogenerated as the 6931 interface definition cannot be generated correctly [due to `MatFactorInfo`] 6932 6933 References: 6934 . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003 6935 6936 .seealso: `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 6937 @*/ 6938 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 6939 { 6940 PetscFunctionBegin; 6941 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 6942 PetscValidType(mat, 2); 6943 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 6944 PetscValidPointer(info, 4); 6945 PetscValidPointer(fact, 1); 6946 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6947 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels); 6948 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 6949 if (!(fact)->ops->iccfactorsymbolic) { 6950 MatSolverType stype; 6951 PetscCall(MatFactorGetSolverType(fact, &stype)); 6952 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ICC using solver type %s", ((PetscObject)mat)->type_name, stype); 6953 } 6954 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6955 MatCheckPreallocated(mat, 2); 6956 6957 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 6958 PetscCall((fact->ops->iccfactorsymbolic)(fact, mat, perm, info)); 6959 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 6960 PetscFunctionReturn(PETSC_SUCCESS); 6961 } 6962 6963 /*@C 6964 MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat 6965 points to an array of valid matrices, they may be reused to store the new 6966 submatrices. 6967 6968 Collective 6969 6970 Input Parameters: 6971 + mat - the matrix 6972 . n - the number of submatrixes to be extracted (on this processor, may be zero) 6973 . irow, icol - index sets of rows and columns to extract 6974 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 6975 6976 Output Parameter: 6977 . submat - the array of submatrices 6978 6979 Level: advanced 6980 6981 Notes: 6982 `MatCreateSubMatrices()` can extract ONLY sequential submatrices 6983 (from both sequential and parallel matrices). Use `MatCreateSubMatrix()` 6984 to extract a parallel submatrix. 6985 6986 Some matrix types place restrictions on the row and column 6987 indices, such as that they be sorted or that they be equal to each other. 6988 6989 The index sets may not have duplicate entries. 6990 6991 When extracting submatrices from a parallel matrix, each processor can 6992 form a different submatrix by setting the rows and columns of its 6993 individual index sets according to the local submatrix desired. 6994 6995 When finished using the submatrices, the user should destroy 6996 them with `MatDestroySubMatrices()`. 6997 6998 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 6999 original matrix has not changed from that last call to `MatCreateSubMatrices()`. 7000 7001 This routine creates the matrices in submat; you should NOT create them before 7002 calling it. It also allocates the array of matrix pointers submat. 7003 7004 For `MATBAIJ` matrices the index sets must respect the block structure, that is if they 7005 request one row/column in a block, they must request all rows/columns that are in 7006 that block. For example, if the block size is 2 you cannot request just row 0 and 7007 column 0. 7008 7009 Fortran Note: 7010 The Fortran interface is slightly different from that given below; it 7011 requires one to pass in as submat a `Mat` (integer) array of size at least n+1. 7012 7013 .seealso: `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7014 @*/ 7015 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7016 { 7017 PetscInt i; 7018 PetscBool eq; 7019 7020 PetscFunctionBegin; 7021 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7022 PetscValidType(mat, 1); 7023 if (n) { 7024 PetscValidPointer(irow, 3); 7025 for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3); 7026 PetscValidPointer(icol, 4); 7027 for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4); 7028 } 7029 PetscValidPointer(submat, 6); 7030 if (n && scall == MAT_REUSE_MATRIX) { 7031 PetscValidPointer(*submat, 6); 7032 for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6); 7033 } 7034 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7035 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7036 MatCheckPreallocated(mat, 1); 7037 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7038 PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat); 7039 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7040 for (i = 0; i < n; i++) { 7041 (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */ 7042 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7043 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7044 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 7045 if (mat->boundtocpu && mat->bindingpropagates) { 7046 PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE)); 7047 PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE)); 7048 } 7049 #endif 7050 } 7051 PetscFunctionReturn(PETSC_SUCCESS); 7052 } 7053 7054 /*@C 7055 MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms). 7056 7057 Collective 7058 7059 Input Parameters: 7060 + mat - the matrix 7061 . n - the number of submatrixes to be extracted 7062 . irow, icol - index sets of rows and columns to extract 7063 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7064 7065 Output Parameter: 7066 . submat - the array of submatrices 7067 7068 Level: advanced 7069 7070 Note: 7071 This is used by `PCGASM` 7072 7073 .seealso: `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7074 @*/ 7075 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7076 { 7077 PetscInt i; 7078 PetscBool eq; 7079 7080 PetscFunctionBegin; 7081 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7082 PetscValidType(mat, 1); 7083 if (n) { 7084 PetscValidPointer(irow, 3); 7085 PetscValidHeaderSpecific(*irow, IS_CLASSID, 3); 7086 PetscValidPointer(icol, 4); 7087 PetscValidHeaderSpecific(*icol, IS_CLASSID, 4); 7088 } 7089 PetscValidPointer(submat, 6); 7090 if (n && scall == MAT_REUSE_MATRIX) { 7091 PetscValidPointer(*submat, 6); 7092 PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6); 7093 } 7094 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7095 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7096 MatCheckPreallocated(mat, 1); 7097 7098 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7099 PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat); 7100 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7101 for (i = 0; i < n; i++) { 7102 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7103 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7104 } 7105 PetscFunctionReturn(PETSC_SUCCESS); 7106 } 7107 7108 /*@C 7109 MatDestroyMatrices - Destroys an array of matrices. 7110 7111 Collective 7112 7113 Input Parameters: 7114 + n - the number of local matrices 7115 - mat - the matrices (note that this is a pointer to the array of matrices) 7116 7117 Level: advanced 7118 7119 Note: 7120 Frees not only the matrices, but also the array that contains the matrices 7121 7122 Fortran Note: 7123 Will not free the array. 7124 7125 .seealso: `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()` 7126 @*/ 7127 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[]) 7128 { 7129 PetscInt i; 7130 7131 PetscFunctionBegin; 7132 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7133 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7134 PetscValidPointer(mat, 2); 7135 7136 for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i])); 7137 7138 /* memory is allocated even if n = 0 */ 7139 PetscCall(PetscFree(*mat)); 7140 PetscFunctionReturn(PETSC_SUCCESS); 7141 } 7142 7143 /*@C 7144 MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`. 7145 7146 Collective 7147 7148 Input Parameters: 7149 + n - the number of local matrices 7150 - mat - the matrices (note that this is a pointer to the array of matrices, just to match the calling 7151 sequence of MatCreateSubMatrices()) 7152 7153 Level: advanced 7154 7155 Note: 7156 Frees not only the matrices, but also the array that contains the matrices 7157 7158 Fortran Note: 7159 Will not free the array. 7160 7161 .seealso: `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7162 @*/ 7163 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[]) 7164 { 7165 Mat mat0; 7166 7167 PetscFunctionBegin; 7168 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7169 /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */ 7170 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7171 PetscValidPointer(mat, 2); 7172 7173 mat0 = (*mat)[0]; 7174 if (mat0 && mat0->ops->destroysubmatrices) { 7175 PetscCall((mat0->ops->destroysubmatrices)(n, mat)); 7176 } else { 7177 PetscCall(MatDestroyMatrices(n, mat)); 7178 } 7179 PetscFunctionReturn(PETSC_SUCCESS); 7180 } 7181 7182 /*@C 7183 MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process 7184 7185 Collective 7186 7187 Input Parameters: 7188 . mat - the matrix 7189 7190 Output Parameter: 7191 . matstruct - the sequential matrix with the nonzero structure of mat 7192 7193 Level: developer 7194 7195 .seealso: `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7196 @*/ 7197 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct) 7198 { 7199 PetscFunctionBegin; 7200 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7201 PetscValidPointer(matstruct, 2); 7202 7203 PetscValidType(mat, 1); 7204 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7205 MatCheckPreallocated(mat, 1); 7206 7207 PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7208 PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct); 7209 PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7210 PetscFunctionReturn(PETSC_SUCCESS); 7211 } 7212 7213 /*@C 7214 MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`. 7215 7216 Collective 7217 7218 Input Parameters: 7219 . mat - the matrix (note that this is a pointer to the array of matrices, just to match the calling 7220 sequence of `MatGetSequentialNonzeroStructure()`) 7221 7222 Level: advanced 7223 7224 Note: 7225 Frees not only the matrices, but also the array that contains the matrices 7226 7227 .seealso: `Mat`, `MatGetSeqNonzeroStructure()` 7228 @*/ 7229 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat) 7230 { 7231 PetscFunctionBegin; 7232 PetscValidPointer(mat, 1); 7233 PetscCall(MatDestroy(mat)); 7234 PetscFunctionReturn(PETSC_SUCCESS); 7235 } 7236 7237 /*@ 7238 MatIncreaseOverlap - Given a set of submatrices indicated by index sets, 7239 replaces the index sets by larger ones that represent submatrices with 7240 additional overlap. 7241 7242 Collective 7243 7244 Input Parameters: 7245 + mat - the matrix 7246 . n - the number of index sets 7247 . is - the array of index sets (these index sets will changed during the call) 7248 - ov - the additional overlap requested 7249 7250 Options Database Key: 7251 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7252 7253 Level: developer 7254 7255 Note: 7256 The computed overlap preserves the matrix block sizes when the blocks are square. 7257 That is: if a matrix nonzero for a given block would increase the overlap all columns associated with 7258 that block are included in the overlap regardless of whether each specific column would increase the overlap. 7259 7260 .seealso: `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()` 7261 @*/ 7262 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov) 7263 { 7264 PetscInt i, bs, cbs; 7265 7266 PetscFunctionBegin; 7267 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7268 PetscValidType(mat, 1); 7269 PetscValidLogicalCollectiveInt(mat, n, 2); 7270 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7271 if (n) { 7272 PetscValidPointer(is, 3); 7273 for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3); 7274 } 7275 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7276 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7277 MatCheckPreallocated(mat, 1); 7278 7279 if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS); 7280 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7281 PetscUseTypeMethod(mat, increaseoverlap, n, is, ov); 7282 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7283 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 7284 if (bs == cbs) { 7285 for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs)); 7286 } 7287 PetscFunctionReturn(PETSC_SUCCESS); 7288 } 7289 7290 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt); 7291 7292 /*@ 7293 MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across 7294 a sub communicator, replaces the index sets by larger ones that represent submatrices with 7295 additional overlap. 7296 7297 Collective 7298 7299 Input Parameters: 7300 + mat - the matrix 7301 . n - the number of index sets 7302 . is - the array of index sets (these index sets will changed during the call) 7303 - ov - the additional overlap requested 7304 7305 ` Options Database Key: 7306 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7307 7308 Level: developer 7309 7310 .seealso: `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()` 7311 @*/ 7312 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov) 7313 { 7314 PetscInt i; 7315 7316 PetscFunctionBegin; 7317 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7318 PetscValidType(mat, 1); 7319 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7320 if (n) { 7321 PetscValidPointer(is, 3); 7322 PetscValidHeaderSpecific(*is, IS_CLASSID, 3); 7323 } 7324 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7325 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7326 MatCheckPreallocated(mat, 1); 7327 if (!ov) PetscFunctionReturn(PETSC_SUCCESS); 7328 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7329 for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov)); 7330 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7331 PetscFunctionReturn(PETSC_SUCCESS); 7332 } 7333 7334 /*@ 7335 MatGetBlockSize - Returns the matrix block size. 7336 7337 Not Collective 7338 7339 Input Parameter: 7340 . mat - the matrix 7341 7342 Output Parameter: 7343 . bs - block size 7344 7345 Level: intermediate 7346 7347 Notes: 7348 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7349 7350 If the block size has not been set yet this routine returns 1. 7351 7352 .seealso: `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()` 7353 @*/ 7354 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs) 7355 { 7356 PetscFunctionBegin; 7357 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7358 PetscValidIntPointer(bs, 2); 7359 *bs = PetscAbs(mat->rmap->bs); 7360 PetscFunctionReturn(PETSC_SUCCESS); 7361 } 7362 7363 /*@ 7364 MatGetBlockSizes - Returns the matrix block row and column sizes. 7365 7366 Not Collective 7367 7368 Input Parameter: 7369 . mat - the matrix 7370 7371 Output Parameters: 7372 + rbs - row block size 7373 - cbs - column block size 7374 7375 Level: intermediate 7376 7377 Notes: 7378 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7379 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7380 7381 If a block size has not been set yet this routine returns 1. 7382 7383 .seealso: `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()` 7384 @*/ 7385 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs) 7386 { 7387 PetscFunctionBegin; 7388 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7389 if (rbs) PetscValidIntPointer(rbs, 2); 7390 if (cbs) PetscValidIntPointer(cbs, 3); 7391 if (rbs) *rbs = PetscAbs(mat->rmap->bs); 7392 if (cbs) *cbs = PetscAbs(mat->cmap->bs); 7393 PetscFunctionReturn(PETSC_SUCCESS); 7394 } 7395 7396 /*@ 7397 MatSetBlockSize - Sets the matrix block size. 7398 7399 Logically Collective 7400 7401 Input Parameters: 7402 + mat - the matrix 7403 - bs - block size 7404 7405 Level: intermediate 7406 7407 Notes: 7408 Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix. 7409 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7410 7411 For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size 7412 is compatible with the matrix local sizes. 7413 7414 .seealso: `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()` 7415 @*/ 7416 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs) 7417 { 7418 PetscFunctionBegin; 7419 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7420 PetscValidLogicalCollectiveInt(mat, bs, 2); 7421 PetscCall(MatSetBlockSizes(mat, bs, bs)); 7422 PetscFunctionReturn(PETSC_SUCCESS); 7423 } 7424 7425 typedef struct { 7426 PetscInt n; 7427 IS *is; 7428 Mat *mat; 7429 PetscObjectState nonzerostate; 7430 Mat C; 7431 } EnvelopeData; 7432 7433 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata) 7434 { 7435 for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i])); 7436 PetscCall(PetscFree(edata->is)); 7437 PetscCall(PetscFree(edata)); 7438 return PETSC_SUCCESS; 7439 } 7440 7441 /* 7442 MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores 7443 the sizes of these blocks in the matrix. An individual block may lie over several processes. 7444 7445 Collective 7446 7447 Input Parameter: 7448 . mat - the matrix 7449 7450 Notes: 7451 There can be zeros within the blocks 7452 7453 The blocks can overlap between processes, including laying on more than two processes 7454 7455 .seealso: `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()` 7456 */ 7457 static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat) 7458 { 7459 PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend; 7460 PetscInt *diag, *odiag, sc; 7461 VecScatter scatter; 7462 PetscScalar *seqv; 7463 const PetscScalar *parv; 7464 const PetscInt *ia, *ja; 7465 PetscBool set, flag, done; 7466 Mat AA = mat, A; 7467 MPI_Comm comm; 7468 PetscMPIInt rank, size, tag; 7469 MPI_Status status; 7470 PetscContainer container; 7471 EnvelopeData *edata; 7472 Vec seq, par; 7473 IS isglobal; 7474 7475 PetscFunctionBegin; 7476 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7477 PetscCall(MatIsSymmetricKnown(mat, &set, &flag)); 7478 if (!set || !flag) { 7479 /* TOO: only needs nonzero structure of transpose */ 7480 PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA)); 7481 PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN)); 7482 } 7483 PetscCall(MatAIJGetLocalMat(AA, &A)); 7484 PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7485 PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix"); 7486 7487 PetscCall(MatGetLocalSize(mat, &n, NULL)); 7488 PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag)); 7489 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 7490 PetscCallMPI(MPI_Comm_size(comm, &size)); 7491 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7492 7493 PetscCall(PetscMalloc2(n, &sizes, n, &starts)); 7494 7495 if (rank > 0) { 7496 PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7497 PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7498 } 7499 PetscCall(MatGetOwnershipRange(mat, &rstart, NULL)); 7500 for (i = 0; i < n; i++) { 7501 env = PetscMax(env, ja[ia[i + 1] - 1]); 7502 II = rstart + i; 7503 if (env == II) { 7504 starts[lblocks] = tbs; 7505 sizes[lblocks++] = 1 + II - tbs; 7506 tbs = 1 + II; 7507 } 7508 } 7509 if (rank < size - 1) { 7510 PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm)); 7511 PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm)); 7512 } 7513 7514 PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7515 if (!set || !flag) PetscCall(MatDestroy(&AA)); 7516 PetscCall(MatDestroy(&A)); 7517 7518 PetscCall(PetscNew(&edata)); 7519 PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate)); 7520 edata->n = lblocks; 7521 /* create IS needed for extracting blocks from the original matrix */ 7522 PetscCall(PetscMalloc1(lblocks, &edata->is)); 7523 for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i])); 7524 7525 /* Create the resulting inverse matrix structure with preallocation information */ 7526 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C)); 7527 PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 7528 PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat)); 7529 PetscCall(MatSetType(edata->C, MATAIJ)); 7530 7531 /* Communicate the start and end of each row, from each block to the correct rank */ 7532 /* TODO: Use PetscSF instead of VecScatter */ 7533 for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i]; 7534 PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq)); 7535 PetscCall(VecGetArrayWrite(seq, &seqv)); 7536 for (PetscInt i = 0; i < lblocks; i++) { 7537 for (PetscInt j = 0; j < sizes[i]; j++) { 7538 seqv[cnt] = starts[i]; 7539 seqv[cnt + 1] = starts[i] + sizes[i]; 7540 cnt += 2; 7541 } 7542 } 7543 PetscCall(VecRestoreArrayWrite(seq, &seqv)); 7544 PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 7545 sc -= cnt; 7546 PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par)); 7547 PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal)); 7548 PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter)); 7549 PetscCall(ISDestroy(&isglobal)); 7550 PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7551 PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7552 PetscCall(VecScatterDestroy(&scatter)); 7553 PetscCall(VecDestroy(&seq)); 7554 PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend)); 7555 PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag)); 7556 PetscCall(VecGetArrayRead(par, &parv)); 7557 cnt = 0; 7558 PetscCall(MatGetSize(mat, NULL, &n)); 7559 for (PetscInt i = 0; i < mat->rmap->n; i++) { 7560 PetscInt start, end, d = 0, od = 0; 7561 7562 start = (PetscInt)PetscRealPart(parv[cnt]); 7563 end = (PetscInt)PetscRealPart(parv[cnt + 1]); 7564 cnt += 2; 7565 7566 if (start < cstart) { 7567 od += cstart - start + n - cend; 7568 d += cend - cstart; 7569 } else if (start < cend) { 7570 od += n - cend; 7571 d += cend - start; 7572 } else od += n - start; 7573 if (end <= cstart) { 7574 od -= cstart - end + n - cend; 7575 d -= cend - cstart; 7576 } else if (end < cend) { 7577 od -= n - cend; 7578 d -= cend - end; 7579 } else od -= n - end; 7580 7581 odiag[i] = od; 7582 diag[i] = d; 7583 } 7584 PetscCall(VecRestoreArrayRead(par, &parv)); 7585 PetscCall(VecDestroy(&par)); 7586 PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL)); 7587 PetscCall(PetscFree2(diag, odiag)); 7588 PetscCall(PetscFree2(sizes, starts)); 7589 7590 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container)); 7591 PetscCall(PetscContainerSetPointer(container, edata)); 7592 PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy)); 7593 PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container)); 7594 PetscCall(PetscObjectDereference((PetscObject)container)); 7595 PetscFunctionReturn(PETSC_SUCCESS); 7596 } 7597 7598 /*@ 7599 MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A 7600 7601 Collective 7602 7603 Input Parameters: 7604 . A - the matrix 7605 7606 Output Parameters: 7607 . C - matrix with inverted block diagonal of A. This matrix should be created and may have its type set. 7608 7609 Level: advanced 7610 7611 Note: 7612 For efficiency the matrix A should have all the nonzero entries clustered in smallish blocks along the diagonal. 7613 7614 .seealso: `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()` 7615 @*/ 7616 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C) 7617 { 7618 PetscContainer container; 7619 EnvelopeData *edata; 7620 PetscObjectState nonzerostate; 7621 7622 PetscFunctionBegin; 7623 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7624 if (!container) { 7625 PetscCall(MatComputeVariableBlockEnvelope(A)); 7626 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7627 } 7628 PetscCall(PetscContainerGetPointer(container, (void **)&edata)); 7629 PetscCall(MatGetNonzeroState(A, &nonzerostate)); 7630 PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure"); 7631 PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output"); 7632 7633 PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat)); 7634 *C = edata->C; 7635 7636 for (PetscInt i = 0; i < edata->n; i++) { 7637 Mat D; 7638 PetscScalar *dvalues; 7639 7640 PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D)); 7641 PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE)); 7642 PetscCall(MatSeqDenseInvert(D)); 7643 PetscCall(MatDenseGetArray(D, &dvalues)); 7644 PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES)); 7645 PetscCall(MatDestroy(&D)); 7646 } 7647 PetscCall(MatDestroySubMatrices(edata->n, &edata->mat)); 7648 PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY)); 7649 PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY)); 7650 PetscFunctionReturn(PETSC_SUCCESS); 7651 } 7652 7653 /*@ 7654 MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size 7655 7656 Logically Collective 7657 7658 Input Parameters: 7659 + mat - the matrix 7660 . nblocks - the number of blocks on this process, each block can only exist on a single process 7661 - bsizes - the block sizes 7662 7663 Level: intermediate 7664 7665 Notes: 7666 Currently used by `PCVPBJACOBI` for `MATAIJ` matrices 7667 7668 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. 7669 7670 .seealso: `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, 7671 `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI` 7672 @*/ 7673 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes) 7674 { 7675 PetscInt i, ncnt = 0, nlocal; 7676 7677 PetscFunctionBegin; 7678 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7679 PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero"); 7680 PetscCall(MatGetLocalSize(mat, &nlocal, NULL)); 7681 for (i = 0; i < nblocks; i++) ncnt += bsizes[i]; 7682 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); 7683 PetscCall(PetscFree(mat->bsizes)); 7684 mat->nblocks = nblocks; 7685 PetscCall(PetscMalloc1(nblocks, &mat->bsizes)); 7686 PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks)); 7687 PetscFunctionReturn(PETSC_SUCCESS); 7688 } 7689 7690 /*@C 7691 MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size 7692 7693 Logically Collective; No Fortran Support 7694 7695 Input Parameter: 7696 . mat - the matrix 7697 7698 Output Parameters: 7699 + nblocks - the number of blocks on this process 7700 - bsizes - the block sizes 7701 7702 Level: intermediate 7703 7704 .seealso: `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()` 7705 @*/ 7706 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes) 7707 { 7708 PetscFunctionBegin; 7709 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7710 *nblocks = mat->nblocks; 7711 *bsizes = mat->bsizes; 7712 PetscFunctionReturn(PETSC_SUCCESS); 7713 } 7714 7715 /*@ 7716 MatSetBlockSizes - Sets the matrix block row and column sizes. 7717 7718 Logically Collective 7719 7720 Input Parameters: 7721 + mat - the matrix 7722 . rbs - row block size 7723 - cbs - column block size 7724 7725 Level: intermediate 7726 7727 Notes: 7728 Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix. 7729 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7730 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7731 7732 For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes 7733 are compatible with the matrix local sizes. 7734 7735 The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`. 7736 7737 .seealso: `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()` 7738 @*/ 7739 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs) 7740 { 7741 PetscFunctionBegin; 7742 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7743 PetscValidLogicalCollectiveInt(mat, rbs, 2); 7744 PetscValidLogicalCollectiveInt(mat, cbs, 3); 7745 PetscTryTypeMethod(mat, setblocksizes, rbs, cbs); 7746 if (mat->rmap->refcnt) { 7747 ISLocalToGlobalMapping l2g = NULL; 7748 PetscLayout nmap = NULL; 7749 7750 PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap)); 7751 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g)); 7752 PetscCall(PetscLayoutDestroy(&mat->rmap)); 7753 mat->rmap = nmap; 7754 mat->rmap->mapping = l2g; 7755 } 7756 if (mat->cmap->refcnt) { 7757 ISLocalToGlobalMapping l2g = NULL; 7758 PetscLayout nmap = NULL; 7759 7760 PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap)); 7761 if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g)); 7762 PetscCall(PetscLayoutDestroy(&mat->cmap)); 7763 mat->cmap = nmap; 7764 mat->cmap->mapping = l2g; 7765 } 7766 PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs)); 7767 PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs)); 7768 PetscFunctionReturn(PETSC_SUCCESS); 7769 } 7770 7771 /*@ 7772 MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices 7773 7774 Logically Collective 7775 7776 Input Parameters: 7777 + mat - the matrix 7778 . fromRow - matrix from which to copy row block size 7779 - fromCol - matrix from which to copy column block size (can be same as fromRow) 7780 7781 Level: developer 7782 7783 .seealso: `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()` 7784 @*/ 7785 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol) 7786 { 7787 PetscFunctionBegin; 7788 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7789 PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2); 7790 PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3); 7791 if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs)); 7792 if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs)); 7793 PetscFunctionReturn(PETSC_SUCCESS); 7794 } 7795 7796 /*@ 7797 MatResidual - Default routine to calculate the residual r = b - Ax 7798 7799 Collective 7800 7801 Input Parameters: 7802 + mat - the matrix 7803 . b - the right-hand-side 7804 - x - the approximate solution 7805 7806 Output Parameter: 7807 . r - location to store the residual 7808 7809 Level: developer 7810 7811 .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()` 7812 @*/ 7813 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r) 7814 { 7815 PetscFunctionBegin; 7816 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7817 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 7818 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 7819 PetscValidHeaderSpecific(r, VEC_CLASSID, 4); 7820 PetscValidType(mat, 1); 7821 MatCheckPreallocated(mat, 1); 7822 PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0)); 7823 if (!mat->ops->residual) { 7824 PetscCall(MatMult(mat, x, r)); 7825 PetscCall(VecAYPX(r, -1.0, b)); 7826 } else { 7827 PetscUseTypeMethod(mat, residual, b, x, r); 7828 } 7829 PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0)); 7830 PetscFunctionReturn(PETSC_SUCCESS); 7831 } 7832 7833 /*MC 7834 MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix 7835 7836 Synopsis: 7837 MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 7838 7839 Not Collective 7840 7841 Input Parameters: 7842 + A - the matrix 7843 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7844 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7845 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicats if the nonzero structure of the 7846 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7847 always used. 7848 7849 Output Parameters: 7850 + n - number of local rows in the (possibly compressed) matrix 7851 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 7852 . ja - the column indices 7853 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7854 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7855 7856 Level: developer 7857 7858 Note: 7859 Use `MatRestoreRowIJF90()` when you no longer need access to the data 7860 7861 .seealso: [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()` 7862 M*/ 7863 7864 /*MC 7865 MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()` 7866 7867 Synopsis: 7868 MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 7869 7870 Not Collective 7871 7872 Input Parameters: 7873 + A - the matrix 7874 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7875 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7876 inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicats if the nonzero structure of the 7877 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7878 always used. 7879 . n - number of local rows in the (possibly compressed) matrix 7880 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 7881 . ja - the column indices 7882 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7883 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7884 7885 Level: developer 7886 7887 .seealso: [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()` 7888 M*/ 7889 7890 /*@C 7891 MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix 7892 7893 Collective 7894 7895 Input Parameters: 7896 + mat - the matrix 7897 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7898 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7899 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicats if the nonzero structure of the 7900 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7901 always used. 7902 7903 Output Parameters: 7904 + n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed 7905 . 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 7906 . ja - the column indices, use `NULL` if not needed 7907 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7908 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7909 7910 Level: developer 7911 7912 Notes: 7913 You CANNOT change any of the ia[] or ja[] values. 7914 7915 Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values. 7916 7917 Fortran Notes: 7918 In Fortran use 7919 .vb 7920 PetscInt, pointer :: ia(:),ja(:) 7921 call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr) 7922 ! Access the ith and jth entries via ia(i) and ja(j) 7923 .ve 7924 `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()` 7925 7926 .seealso: `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()` 7927 @*/ 7928 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7929 { 7930 PetscFunctionBegin; 7931 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7932 PetscValidType(mat, 1); 7933 if (n) PetscValidIntPointer(n, 5); 7934 if (ia) PetscValidPointer(ia, 6); 7935 if (ja) PetscValidPointer(ja, 7); 7936 if (done) PetscValidBoolPointer(done, 8); 7937 MatCheckPreallocated(mat, 1); 7938 if (!mat->ops->getrowij && done) *done = PETSC_FALSE; 7939 else { 7940 if (done) *done = PETSC_TRUE; 7941 PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0)); 7942 PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done); 7943 PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0)); 7944 } 7945 PetscFunctionReturn(PETSC_SUCCESS); 7946 } 7947 7948 /*@C 7949 MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices. 7950 7951 Collective 7952 7953 Input Parameters: 7954 + mat - the matrix 7955 . shift - 1 or zero indicating we want the indices starting at 0 or 1 7956 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be 7957 symmetrized 7958 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7959 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7960 always used. 7961 . n - number of columns in the (possibly compressed) matrix 7962 . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix 7963 - ja - the row indices 7964 7965 Output Parameters: 7966 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned 7967 7968 Level: developer 7969 7970 .seealso: `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 7971 @*/ 7972 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7973 { 7974 PetscFunctionBegin; 7975 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7976 PetscValidType(mat, 1); 7977 PetscValidIntPointer(n, 5); 7978 if (ia) PetscValidPointer(ia, 6); 7979 if (ja) PetscValidPointer(ja, 7); 7980 PetscValidBoolPointer(done, 8); 7981 MatCheckPreallocated(mat, 1); 7982 if (!mat->ops->getcolumnij) *done = PETSC_FALSE; 7983 else { 7984 *done = PETSC_TRUE; 7985 PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 7986 } 7987 PetscFunctionReturn(PETSC_SUCCESS); 7988 } 7989 7990 /*@C 7991 MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`. 7992 7993 Collective 7994 7995 Input Parameters: 7996 + mat - the matrix 7997 . shift - 1 or zero indicating we want the indices starting at 0 or 1 7998 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7999 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8000 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8001 always used. 8002 . n - size of (possibly compressed) matrix 8003 . ia - the row pointers 8004 - ja - the column indices 8005 8006 Output Parameters: 8007 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8008 8009 Level: developer 8010 8011 Note: 8012 This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental 8013 us of the array after it has been restored. If you pass `NULL`, it will 8014 not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid. 8015 8016 Fortran Note: 8017 `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()` 8018 .seealso: `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()` 8019 @*/ 8020 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8021 { 8022 PetscFunctionBegin; 8023 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8024 PetscValidType(mat, 1); 8025 if (ia) PetscValidPointer(ia, 6); 8026 if (ja) PetscValidPointer(ja, 7); 8027 if (done) PetscValidBoolPointer(done, 8); 8028 MatCheckPreallocated(mat, 1); 8029 8030 if (!mat->ops->restorerowij && done) *done = PETSC_FALSE; 8031 else { 8032 if (done) *done = PETSC_TRUE; 8033 PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8034 if (n) *n = 0; 8035 if (ia) *ia = NULL; 8036 if (ja) *ja = NULL; 8037 } 8038 PetscFunctionReturn(PETSC_SUCCESS); 8039 } 8040 8041 /*@C 8042 MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`. 8043 8044 Collective on Mat 8045 8046 Input Parameters: 8047 + mat - the matrix 8048 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8049 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8050 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8051 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8052 always used. 8053 8054 Output Parameters: 8055 + n - size of (possibly compressed) matrix 8056 . ia - the column pointers 8057 . ja - the row indices 8058 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8059 8060 Level: developer 8061 8062 .seealso: `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()` 8063 @*/ 8064 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8065 { 8066 PetscFunctionBegin; 8067 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8068 PetscValidType(mat, 1); 8069 if (ia) PetscValidPointer(ia, 6); 8070 if (ja) PetscValidPointer(ja, 7); 8071 PetscValidBoolPointer(done, 8); 8072 MatCheckPreallocated(mat, 1); 8073 8074 if (!mat->ops->restorecolumnij) *done = PETSC_FALSE; 8075 else { 8076 *done = PETSC_TRUE; 8077 PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8078 if (n) *n = 0; 8079 if (ia) *ia = NULL; 8080 if (ja) *ja = NULL; 8081 } 8082 PetscFunctionReturn(PETSC_SUCCESS); 8083 } 8084 8085 /*@C 8086 MatColoringPatch -Used inside matrix coloring routines that use `MatGetRowIJ()` and/or `MatGetColumnIJ()`. 8087 8088 Collective 8089 8090 Input Parameters: 8091 + mat - the matrix 8092 . ncolors - max color value 8093 . n - number of entries in colorarray 8094 - colorarray - array indicating color for each column 8095 8096 Output Parameters: 8097 . iscoloring - coloring generated using colorarray information 8098 8099 Level: developer 8100 8101 .seealso: `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()` 8102 @*/ 8103 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring) 8104 { 8105 PetscFunctionBegin; 8106 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8107 PetscValidType(mat, 1); 8108 PetscValidIntPointer(colorarray, 4); 8109 PetscValidPointer(iscoloring, 5); 8110 MatCheckPreallocated(mat, 1); 8111 8112 if (!mat->ops->coloringpatch) { 8113 PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring)); 8114 } else { 8115 PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring); 8116 } 8117 PetscFunctionReturn(PETSC_SUCCESS); 8118 } 8119 8120 /*@ 8121 MatSetUnfactored - Resets a factored matrix to be treated as unfactored. 8122 8123 Logically Collective 8124 8125 Input Parameter: 8126 . mat - the factored matrix to be reset 8127 8128 Level: developer 8129 8130 Notes: 8131 This routine should be used only with factored matrices formed by in-place 8132 factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE` 8133 format). This option can save memory, for example, when solving nonlinear 8134 systems with a matrix-free Newton-Krylov method and a matrix-based, in-place 8135 ILU(0) preconditioner. 8136 8137 Note that one can specify in-place ILU(0) factorization by calling 8138 .vb 8139 PCType(pc,PCILU); 8140 PCFactorSeUseInPlace(pc); 8141 .ve 8142 or by using the options -pc_type ilu -pc_factor_in_place 8143 8144 In-place factorization ILU(0) can also be used as a local 8145 solver for the blocks within the block Jacobi or additive Schwarz 8146 methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc 8147 for details on setting local solver options. 8148 8149 Most users should employ the `KSP` interface for linear solvers 8150 instead of working directly with matrix algebra routines such as this. 8151 See, e.g., `KSPCreate()`. 8152 8153 .seealso: `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()` 8154 @*/ 8155 PetscErrorCode MatSetUnfactored(Mat mat) 8156 { 8157 PetscFunctionBegin; 8158 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8159 PetscValidType(mat, 1); 8160 MatCheckPreallocated(mat, 1); 8161 mat->factortype = MAT_FACTOR_NONE; 8162 if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS); 8163 PetscUseTypeMethod(mat, setunfactored); 8164 PetscFunctionReturn(PETSC_SUCCESS); 8165 } 8166 8167 /*MC 8168 MatDenseGetArrayF90 - Accesses a matrix array from Fortran 8169 8170 Synopsis: 8171 MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8172 8173 Not collective 8174 8175 Input Parameter: 8176 . x - matrix 8177 8178 Output Parameters: 8179 + xx_v - the Fortran pointer to the array 8180 - ierr - error code 8181 8182 Example of Usage: 8183 .vb 8184 PetscScalar, pointer xx_v(:,:) 8185 .... 8186 call MatDenseGetArrayF90(x,xx_v,ierr) 8187 a = xx_v(3) 8188 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8189 .ve 8190 8191 Level: advanced 8192 8193 .seealso: `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()` 8194 M*/ 8195 8196 /*MC 8197 MatDenseRestoreArrayF90 - Restores a matrix array that has been 8198 accessed with `MatDenseGetArrayF90()`. 8199 8200 Synopsis: 8201 MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8202 8203 Not collective 8204 8205 Input Parameters: 8206 + x - matrix 8207 - xx_v - the Fortran90 pointer to the array 8208 8209 Output Parameter: 8210 . ierr - error code 8211 8212 Example of Usage: 8213 .vb 8214 PetscScalar, pointer xx_v(:,:) 8215 .... 8216 call MatDenseGetArrayF90(x,xx_v,ierr) 8217 a = xx_v(3) 8218 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8219 .ve 8220 8221 Level: advanced 8222 8223 .seealso: `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()` 8224 M*/ 8225 8226 /*MC 8227 MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran. 8228 8229 Synopsis: 8230 MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8231 8232 Not collective 8233 8234 Input Parameter: 8235 . x - matrix 8236 8237 Output Parameters: 8238 + xx_v - the Fortran pointer to the array 8239 - ierr - error code 8240 8241 Example of Usage: 8242 .vb 8243 PetscScalar, pointer xx_v(:) 8244 .... 8245 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8246 a = xx_v(3) 8247 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8248 .ve 8249 8250 Level: advanced 8251 8252 .seealso: `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()` 8253 M*/ 8254 8255 /*MC 8256 MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been 8257 accessed with `MatSeqAIJGetArrayF90()`. 8258 8259 Synopsis: 8260 MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8261 8262 Not collective 8263 8264 Input Parameters: 8265 + x - matrix 8266 - xx_v - the Fortran90 pointer to the array 8267 8268 Output Parameter: 8269 . ierr - error code 8270 8271 Example of Usage: 8272 .vb 8273 PetscScalar, pointer xx_v(:) 8274 .... 8275 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8276 a = xx_v(3) 8277 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8278 .ve 8279 8280 Level: advanced 8281 8282 .seealso: `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()` 8283 M*/ 8284 8285 /*@ 8286 MatCreateSubMatrix - Gets a single submatrix on the same number of processors 8287 as the original matrix. 8288 8289 Collective 8290 8291 Input Parameters: 8292 + mat - the original matrix 8293 . isrow - parallel IS containing the rows this processor should obtain 8294 . 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. 8295 - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 8296 8297 Output Parameter: 8298 . newmat - the new submatrix, of the same type as the old 8299 8300 Level: advanced 8301 8302 Notes: 8303 The submatrix will be able to be multiplied with vectors using the same layout as iscol. 8304 8305 Some matrix types place restrictions on the row and column indices, such 8306 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; 8307 for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row. 8308 8309 The index sets may not have duplicate entries. 8310 8311 The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`, 8312 the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls 8313 to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX` 8314 will reuse the matrix generated the first time. You should call `MatDestroy()` on newmat when 8315 you are finished using it. 8316 8317 The communicator of the newly obtained matrix is ALWAYS the same as the communicator of 8318 the input matrix. 8319 8320 If iscol is `NULL` then all columns are obtained (not supported in Fortran). 8321 8322 Example usage: 8323 Consider the following 8x8 matrix with 34 non-zero values, that is 8324 assembled across 3 processors. Let's assume that proc0 owns 3 rows, 8325 proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 8326 as follows: 8327 8328 .vb 8329 1 2 0 | 0 3 0 | 0 4 8330 Proc0 0 5 6 | 7 0 0 | 8 0 8331 9 0 10 | 11 0 0 | 12 0 8332 ------------------------------------- 8333 13 0 14 | 15 16 17 | 0 0 8334 Proc1 0 18 0 | 19 20 21 | 0 0 8335 0 0 0 | 22 23 0 | 24 0 8336 ------------------------------------- 8337 Proc2 25 26 27 | 0 0 28 | 29 0 8338 30 0 0 | 31 32 33 | 0 34 8339 .ve 8340 8341 Suppose isrow = [0 1 | 4 | 6 7] and iscol = [1 2 | 3 4 5 | 6]. The resulting submatrix is 8342 8343 .vb 8344 2 0 | 0 3 0 | 0 8345 Proc0 5 6 | 7 0 0 | 8 8346 ------------------------------- 8347 Proc1 18 0 | 19 20 21 | 0 8348 ------------------------------- 8349 Proc2 26 27 | 0 0 28 | 29 8350 0 0 | 31 32 33 | 0 8351 .ve 8352 8353 .seealso: `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()` 8354 @*/ 8355 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat) 8356 { 8357 PetscMPIInt size; 8358 Mat *local; 8359 IS iscoltmp; 8360 PetscBool flg; 8361 8362 PetscFunctionBegin; 8363 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8364 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 8365 if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 8366 PetscValidPointer(newmat, 5); 8367 if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5); 8368 PetscValidType(mat, 1); 8369 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8370 PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX"); 8371 8372 MatCheckPreallocated(mat, 1); 8373 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8374 8375 if (!iscol || isrow == iscol) { 8376 PetscBool stride; 8377 PetscMPIInt grabentirematrix = 0, grab; 8378 PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride)); 8379 if (stride) { 8380 PetscInt first, step, n, rstart, rend; 8381 PetscCall(ISStrideGetInfo(isrow, &first, &step)); 8382 if (step == 1) { 8383 PetscCall(MatGetOwnershipRange(mat, &rstart, &rend)); 8384 if (rstart == first) { 8385 PetscCall(ISGetLocalSize(isrow, &n)); 8386 if (n == rend - rstart) grabentirematrix = 1; 8387 } 8388 } 8389 } 8390 PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat))); 8391 if (grab) { 8392 PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n")); 8393 if (cll == MAT_INITIAL_MATRIX) { 8394 *newmat = mat; 8395 PetscCall(PetscObjectReference((PetscObject)mat)); 8396 } 8397 PetscFunctionReturn(PETSC_SUCCESS); 8398 } 8399 } 8400 8401 if (!iscol) { 8402 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp)); 8403 } else { 8404 iscoltmp = iscol; 8405 } 8406 8407 /* if original matrix is on just one processor then use submatrix generated */ 8408 if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) { 8409 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat)); 8410 goto setproperties; 8411 } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) { 8412 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local)); 8413 *newmat = *local; 8414 PetscCall(PetscFree(local)); 8415 goto setproperties; 8416 } else if (!mat->ops->createsubmatrix) { 8417 /* Create a new matrix type that implements the operation using the full matrix */ 8418 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8419 switch (cll) { 8420 case MAT_INITIAL_MATRIX: 8421 PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat)); 8422 break; 8423 case MAT_REUSE_MATRIX: 8424 PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp)); 8425 break; 8426 default: 8427 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX"); 8428 } 8429 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8430 goto setproperties; 8431 } 8432 8433 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8434 PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat); 8435 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8436 8437 setproperties: 8438 PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg)); 8439 if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat)); 8440 if (!iscol) PetscCall(ISDestroy(&iscoltmp)); 8441 if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat)); 8442 PetscFunctionReturn(PETSC_SUCCESS); 8443 } 8444 8445 /*@ 8446 MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix 8447 8448 Not Collective 8449 8450 Input Parameters: 8451 + A - the matrix we wish to propagate options from 8452 - B - the matrix we wish to propagate options to 8453 8454 Level: beginner 8455 8456 Note: 8457 Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL` 8458 8459 .seealso: `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, MatIsStructurallySymmetricKnown()` 8460 @*/ 8461 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B) 8462 { 8463 PetscFunctionBegin; 8464 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8465 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 8466 B->symmetry_eternal = A->symmetry_eternal; 8467 B->structural_symmetry_eternal = A->structural_symmetry_eternal; 8468 B->symmetric = A->symmetric; 8469 B->structurally_symmetric = A->structurally_symmetric; 8470 B->spd = A->spd; 8471 B->hermitian = A->hermitian; 8472 PetscFunctionReturn(PETSC_SUCCESS); 8473 } 8474 8475 /*@ 8476 MatStashSetInitialSize - sets the sizes of the matrix stash, that is 8477 used during the assembly process to store values that belong to 8478 other processors. 8479 8480 Not Collective 8481 8482 Input Parameters: 8483 + mat - the matrix 8484 . size - the initial size of the stash. 8485 - bsize - the initial size of the block-stash(if used). 8486 8487 Options Database Keys: 8488 + -matstash_initial_size <size> or <size0,size1,...sizep-1> 8489 - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1> 8490 8491 Level: intermediate 8492 8493 Notes: 8494 The block-stash is used for values set with `MatSetValuesBlocked()` while 8495 the stash is used for values set with `MatSetValues()` 8496 8497 Run with the option -info and look for output of the form 8498 MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs. 8499 to determine the appropriate value, MM, to use for size and 8500 MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs. 8501 to determine the value, BMM to use for bsize 8502 8503 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()` 8504 @*/ 8505 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize) 8506 { 8507 PetscFunctionBegin; 8508 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8509 PetscValidType(mat, 1); 8510 PetscCall(MatStashSetInitialSize_Private(&mat->stash, size)); 8511 PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize)); 8512 PetscFunctionReturn(PETSC_SUCCESS); 8513 } 8514 8515 /*@ 8516 MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of 8517 the matrix 8518 8519 Neighbor-wise Collective 8520 8521 Input Parameters: 8522 + mat - the matrix 8523 . x,y - the vectors 8524 - w - where the result is stored 8525 8526 Level: intermediate 8527 8528 Notes: 8529 `w` may be the same vector as `y`. 8530 8531 This allows one to use either the restriction or interpolation (its transpose) 8532 matrix to do the interpolation 8533 8534 .seealso: `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8535 @*/ 8536 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w) 8537 { 8538 PetscInt M, N, Ny; 8539 8540 PetscFunctionBegin; 8541 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8542 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8543 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8544 PetscValidHeaderSpecific(w, VEC_CLASSID, 4); 8545 PetscCall(MatGetSize(A, &M, &N)); 8546 PetscCall(VecGetSize(y, &Ny)); 8547 if (M == Ny) { 8548 PetscCall(MatMultAdd(A, x, y, w)); 8549 } else { 8550 PetscCall(MatMultTransposeAdd(A, x, y, w)); 8551 } 8552 PetscFunctionReturn(PETSC_SUCCESS); 8553 } 8554 8555 /*@ 8556 MatInterpolate - y = A*x or A'*x depending on the shape of 8557 the matrix 8558 8559 Neighbor-wise Collective 8560 8561 Input Parameters: 8562 + mat - the matrix 8563 - x,y - the vectors 8564 8565 Level: intermediate 8566 8567 Note: 8568 This allows one to use either the restriction or interpolation (its transpose) 8569 matrix to do the interpolation 8570 8571 .seealso: `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8572 @*/ 8573 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y) 8574 { 8575 PetscInt M, N, Ny; 8576 8577 PetscFunctionBegin; 8578 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8579 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8580 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8581 PetscCall(MatGetSize(A, &M, &N)); 8582 PetscCall(VecGetSize(y, &Ny)); 8583 if (M == Ny) { 8584 PetscCall(MatMult(A, x, y)); 8585 } else { 8586 PetscCall(MatMultTranspose(A, x, y)); 8587 } 8588 PetscFunctionReturn(PETSC_SUCCESS); 8589 } 8590 8591 /*@ 8592 MatRestrict - y = A*x or A'*x 8593 8594 Neighbor-wise Collective on Mat 8595 8596 Input Parameters: 8597 + mat - the matrix 8598 - x,y - the vectors 8599 8600 Level: intermediate 8601 8602 Note: 8603 This allows one to use either the restriction or interpolation (its transpose) 8604 matrix to do the restriction 8605 8606 .seealso: `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG` 8607 @*/ 8608 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y) 8609 { 8610 PetscInt M, N, Ny; 8611 8612 PetscFunctionBegin; 8613 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8614 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8615 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8616 PetscCall(MatGetSize(A, &M, &N)); 8617 PetscCall(VecGetSize(y, &Ny)); 8618 if (M == Ny) { 8619 PetscCall(MatMult(A, x, y)); 8620 } else { 8621 PetscCall(MatMultTranspose(A, x, y)); 8622 } 8623 PetscFunctionReturn(PETSC_SUCCESS); 8624 } 8625 8626 /*@ 8627 MatMatInterpolateAdd - Y = W + A*X or W + A'*X 8628 8629 Neighbor-wise Collective on Mat 8630 8631 Input Parameters: 8632 + mat - the matrix 8633 - w, x - the input dense matrices 8634 8635 Output Parameters: 8636 . y - the output dense matrix 8637 8638 Level: intermediate 8639 8640 Note: 8641 This allows one to use either the restriction or interpolation (its transpose) 8642 matrix to do the interpolation. y matrix can be reused if already created with the proper sizes, 8643 otherwise it will be recreated. y must be initialized to `NULL` if not supplied. 8644 8645 .seealso: `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG` 8646 @*/ 8647 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y) 8648 { 8649 PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0; 8650 PetscBool trans = PETSC_TRUE; 8651 MatReuse reuse = MAT_INITIAL_MATRIX; 8652 8653 PetscFunctionBegin; 8654 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8655 PetscValidHeaderSpecific(x, MAT_CLASSID, 2); 8656 PetscValidType(x, 2); 8657 if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3); 8658 if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4); 8659 PetscCall(MatGetSize(A, &M, &N)); 8660 PetscCall(MatGetSize(x, &Mx, &Nx)); 8661 if (N == Mx) trans = PETSC_FALSE; 8662 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); 8663 Mo = trans ? N : M; 8664 if (*y) { 8665 PetscCall(MatGetSize(*y, &My, &Ny)); 8666 if (Mo == My && Nx == Ny) { 8667 reuse = MAT_REUSE_MATRIX; 8668 } else { 8669 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); 8670 PetscCall(MatDestroy(y)); 8671 } 8672 } 8673 8674 if (w && *y == w) { /* this is to minimize changes in PCMG */ 8675 PetscBool flg; 8676 8677 PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w)); 8678 if (w) { 8679 PetscInt My, Ny, Mw, Nw; 8680 8681 PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg)); 8682 PetscCall(MatGetSize(*y, &My, &Ny)); 8683 PetscCall(MatGetSize(w, &Mw, &Nw)); 8684 if (!flg || My != Mw || Ny != Nw) w = NULL; 8685 } 8686 if (!w) { 8687 PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w)); 8688 PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w)); 8689 PetscCall(PetscObjectDereference((PetscObject)w)); 8690 } else { 8691 PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN)); 8692 } 8693 } 8694 if (!trans) { 8695 PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8696 } else { 8697 PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8698 } 8699 if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN)); 8700 PetscFunctionReturn(PETSC_SUCCESS); 8701 } 8702 8703 /*@ 8704 MatMatInterpolate - Y = A*X or A'*X 8705 8706 Neighbor-wise Collective on Mat 8707 8708 Input Parameters: 8709 + mat - the matrix 8710 - x - the input dense matrix 8711 8712 Output Parameters: 8713 . y - the output dense matrix 8714 8715 Level: intermediate 8716 8717 Note: 8718 This allows one to use either the restriction or interpolation (its transpose) 8719 matrix to do the interpolation. y matrix can be reused if already created with the proper sizes, 8720 otherwise it will be recreated. y must be initialized to `NULL` if not supplied. 8721 8722 .seealso: `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG` 8723 @*/ 8724 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y) 8725 { 8726 PetscFunctionBegin; 8727 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8728 PetscFunctionReturn(PETSC_SUCCESS); 8729 } 8730 8731 /*@ 8732 MatMatRestrict - Y = A*X or A'*X 8733 8734 Neighbor-wise Collective on Mat 8735 8736 Input Parameters: 8737 + mat - the matrix 8738 - x - the input dense matrix 8739 8740 Output Parameters: 8741 . y - the output dense matrix 8742 8743 Level: intermediate 8744 8745 Note: 8746 This allows one to use either the restriction or interpolation (its transpose) 8747 matrix to do the restriction. y matrix can be reused if already created with the proper sizes, 8748 otherwise it will be recreated. y must be initialized to `NULL` if not supplied. 8749 8750 .seealso: `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG` 8751 @*/ 8752 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y) 8753 { 8754 PetscFunctionBegin; 8755 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8756 PetscFunctionReturn(PETSC_SUCCESS); 8757 } 8758 8759 /*@ 8760 MatGetNullSpace - retrieves the null space of a matrix. 8761 8762 Logically Collective 8763 8764 Input Parameters: 8765 + mat - the matrix 8766 - nullsp - the null space object 8767 8768 Level: developer 8769 8770 .seealso: `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace` 8771 @*/ 8772 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp) 8773 { 8774 PetscFunctionBegin; 8775 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8776 PetscValidPointer(nullsp, 2); 8777 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp; 8778 PetscFunctionReturn(PETSC_SUCCESS); 8779 } 8780 8781 /*@ 8782 MatSetNullSpace - attaches a null space to a matrix. 8783 8784 Logically Collective 8785 8786 Input Parameters: 8787 + mat - the matrix 8788 - nullsp - the null space object 8789 8790 Level: advanced 8791 8792 Notes: 8793 This null space is used by the `KSP` linear solvers to solve singular systems. 8794 8795 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` 8796 8797 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 8798 to zero but the linear system will still be solved in a least squares sense. 8799 8800 The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that 8801 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). 8802 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 8803 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 8804 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). 8805 This \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix. 8806 8807 If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called 8808 `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this 8809 routine also automatically calls `MatSetTransposeNullSpace()`. 8810 8811 The user should call `MatNullSpaceDestroy()`. 8812 8813 .seealso: `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, 8814 `KSPSetPCSide()` 8815 @*/ 8816 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp) 8817 { 8818 PetscFunctionBegin; 8819 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8820 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8821 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8822 PetscCall(MatNullSpaceDestroy(&mat->nullsp)); 8823 mat->nullsp = nullsp; 8824 if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp)); 8825 PetscFunctionReturn(PETSC_SUCCESS); 8826 } 8827 8828 /*@ 8829 MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix. 8830 8831 Logically Collective 8832 8833 Input Parameters: 8834 + mat - the matrix 8835 - nullsp - the null space object 8836 8837 Level: developer 8838 8839 .seealso: `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()` 8840 @*/ 8841 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp) 8842 { 8843 PetscFunctionBegin; 8844 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8845 PetscValidType(mat, 1); 8846 PetscValidPointer(nullsp, 2); 8847 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp; 8848 PetscFunctionReturn(PETSC_SUCCESS); 8849 } 8850 8851 /*@ 8852 MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix 8853 8854 Logically Collective 8855 8856 Input Parameters: 8857 + mat - the matrix 8858 - nullsp - the null space object 8859 8860 Level: advanced 8861 8862 Notes: 8863 This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning. 8864 8865 See `MatSetNullSpace()` 8866 8867 .seealso: `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()` 8868 @*/ 8869 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp) 8870 { 8871 PetscFunctionBegin; 8872 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8873 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8874 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8875 PetscCall(MatNullSpaceDestroy(&mat->transnullsp)); 8876 mat->transnullsp = nullsp; 8877 PetscFunctionReturn(PETSC_SUCCESS); 8878 } 8879 8880 /*@ 8881 MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions 8882 This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix. 8883 8884 Logically Collective 8885 8886 Input Parameters: 8887 + mat - the matrix 8888 - nullsp - the null space object 8889 8890 Level: advanced 8891 8892 Notes: 8893 Overwrites any previous near null space that may have been attached 8894 8895 You can remove the null space by calling this routine with an nullsp of `NULL` 8896 8897 .seealso: `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()` 8898 @*/ 8899 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp) 8900 { 8901 PetscFunctionBegin; 8902 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8903 PetscValidType(mat, 1); 8904 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8905 MatCheckPreallocated(mat, 1); 8906 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8907 PetscCall(MatNullSpaceDestroy(&mat->nearnullsp)); 8908 mat->nearnullsp = nullsp; 8909 PetscFunctionReturn(PETSC_SUCCESS); 8910 } 8911 8912 /*@ 8913 MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()` 8914 8915 Not Collective 8916 8917 Input Parameter: 8918 . mat - the matrix 8919 8920 Output Parameter: 8921 . nullsp - the null space object, `NULL` if not set 8922 8923 Level: advanced 8924 8925 .seealso: `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()` 8926 @*/ 8927 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp) 8928 { 8929 PetscFunctionBegin; 8930 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8931 PetscValidType(mat, 1); 8932 PetscValidPointer(nullsp, 2); 8933 MatCheckPreallocated(mat, 1); 8934 *nullsp = mat->nearnullsp; 8935 PetscFunctionReturn(PETSC_SUCCESS); 8936 } 8937 8938 /*@C 8939 MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix. 8940 8941 Collective 8942 8943 Input Parameters: 8944 + mat - the matrix 8945 . row - row/column permutation 8946 . fill - expected fill factor >= 1.0 8947 - level - level of fill, for ICC(k) 8948 8949 Notes: 8950 Probably really in-place only when level of fill is zero, otherwise allocates 8951 new space to store factored matrix and deletes previous memory. 8952 8953 Most users should employ the `KSP` interface for linear solvers 8954 instead of working directly with matrix algebra routines such as this. 8955 See, e.g., `KSPCreate()`. 8956 8957 Level: developer 8958 8959 Developer Note: 8960 The Fortran interface is not autogenerated as the 8961 interface definition cannot be generated correctly [due to `MatFactorInfo`] 8962 8963 .seealso: `Mat`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 8964 @*/ 8965 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info) 8966 { 8967 PetscFunctionBegin; 8968 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8969 PetscValidType(mat, 1); 8970 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 8971 PetscValidPointer(info, 3); 8972 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 8973 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 8974 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8975 MatCheckPreallocated(mat, 1); 8976 PetscUseTypeMethod(mat, iccfactor, row, info); 8977 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 8978 PetscFunctionReturn(PETSC_SUCCESS); 8979 } 8980 8981 /*@ 8982 MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the 8983 ghosted ones. 8984 8985 Not Collective 8986 8987 Input Parameters: 8988 + mat - the matrix 8989 - diag - the diagonal values, including ghost ones 8990 8991 Level: developer 8992 8993 Notes: 8994 Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices 8995 8996 This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()` 8997 8998 .seealso: `Mat`, `MatDiagonalScale()` 8999 @*/ 9000 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag) 9001 { 9002 PetscMPIInt size; 9003 9004 PetscFunctionBegin; 9005 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9006 PetscValidHeaderSpecific(diag, VEC_CLASSID, 2); 9007 PetscValidType(mat, 1); 9008 9009 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled"); 9010 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 9011 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 9012 if (size == 1) { 9013 PetscInt n, m; 9014 PetscCall(VecGetSize(diag, &n)); 9015 PetscCall(MatGetSize(mat, NULL, &m)); 9016 PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions"); 9017 PetscCall(MatDiagonalScale(mat, NULL, diag)); 9018 } else { 9019 PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag)); 9020 } 9021 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 9022 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9023 PetscFunctionReturn(PETSC_SUCCESS); 9024 } 9025 9026 /*@ 9027 MatGetInertia - Gets the inertia from a factored matrix 9028 9029 Collective 9030 9031 Input Parameter: 9032 . mat - the matrix 9033 9034 Output Parameters: 9035 + nneg - number of negative eigenvalues 9036 . nzero - number of zero eigenvalues 9037 - npos - number of positive eigenvalues 9038 9039 Level: advanced 9040 9041 Note: 9042 Matrix must have been factored by `MatCholeskyFactor()` 9043 9044 .seealso: `Mat`, `MatGetFactor()`, `MatCholeskyFactor()` 9045 @*/ 9046 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos) 9047 { 9048 PetscFunctionBegin; 9049 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9050 PetscValidType(mat, 1); 9051 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9052 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled"); 9053 PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos); 9054 PetscFunctionReturn(PETSC_SUCCESS); 9055 } 9056 9057 /*@C 9058 MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors 9059 9060 Neighbor-wise Collective 9061 9062 Input Parameters: 9063 + mat - the factored matrix obtained with `MatGetFactor()` 9064 - b - the right-hand-side vectors 9065 9066 Output Parameter: 9067 . x - the result vectors 9068 9069 Level: developer 9070 9071 Note: 9072 The vectors `b` and `x` cannot be the same. I.e., one cannot 9073 call `MatSolves`(A,x,x). 9074 9075 .seealso: `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()` 9076 @*/ 9077 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x) 9078 { 9079 PetscFunctionBegin; 9080 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9081 PetscValidType(mat, 1); 9082 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 9083 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9084 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 9085 9086 MatCheckPreallocated(mat, 1); 9087 PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0)); 9088 PetscUseTypeMethod(mat, solves, b, x); 9089 PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0)); 9090 PetscFunctionReturn(PETSC_SUCCESS); 9091 } 9092 9093 /*@ 9094 MatIsSymmetric - Test whether a matrix is symmetric 9095 9096 Collective 9097 9098 Input Parameters: 9099 + A - the matrix to test 9100 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose) 9101 9102 Output Parameters: 9103 . flg - the result 9104 9105 Level: intermediate 9106 9107 Notes: 9108 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9109 9110 If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()` 9111 9112 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9113 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9114 9115 .seealso: `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`, 9116 `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()` 9117 @*/ 9118 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg) 9119 { 9120 PetscFunctionBegin; 9121 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9122 PetscValidBoolPointer(flg, 3); 9123 9124 if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE; 9125 else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE; 9126 else { 9127 if (!A->ops->issymmetric) { 9128 MatType mattype; 9129 PetscCall(MatGetType(A, &mattype)); 9130 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for symmetric", mattype); 9131 } 9132 PetscUseTypeMethod(A, issymmetric, tol, flg); 9133 if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg)); 9134 } 9135 PetscFunctionReturn(PETSC_SUCCESS); 9136 } 9137 9138 /*@ 9139 MatIsHermitian - Test whether a matrix is Hermitian 9140 9141 Collective on Mat 9142 9143 Input Parameters: 9144 + A - the matrix to test 9145 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian) 9146 9147 Output Parameters: 9148 . flg - the result 9149 9150 Level: intermediate 9151 9152 Notes: 9153 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9154 9155 If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()` 9156 9157 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9158 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`) 9159 9160 .seealso: `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, 9161 `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()` 9162 @*/ 9163 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg) 9164 { 9165 PetscFunctionBegin; 9166 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9167 PetscValidBoolPointer(flg, 3); 9168 9169 if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE; 9170 else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE; 9171 else { 9172 if (!A->ops->ishermitian) { 9173 MatType mattype; 9174 PetscCall(MatGetType(A, &mattype)); 9175 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for hermitian", mattype); 9176 } 9177 PetscUseTypeMethod(A, ishermitian, tol, flg); 9178 if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg)); 9179 } 9180 PetscFunctionReturn(PETSC_SUCCESS); 9181 } 9182 9183 /*@ 9184 MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state 9185 9186 Not Collective 9187 9188 Input Parameter: 9189 . A - the matrix to check 9190 9191 Output Parameters: 9192 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid) 9193 - flg - the result (only valid if set is `PETSC_TRUE`) 9194 9195 Level: advanced 9196 9197 Notes: 9198 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()` 9199 if you want it explicitly checked 9200 9201 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9202 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9203 9204 .seealso: `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9205 @*/ 9206 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9207 { 9208 PetscFunctionBegin; 9209 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9210 PetscValidBoolPointer(set, 2); 9211 PetscValidBoolPointer(flg, 3); 9212 if (A->symmetric != PETSC_BOOL3_UNKNOWN) { 9213 *set = PETSC_TRUE; 9214 *flg = PetscBool3ToBool(A->symmetric); 9215 } else { 9216 *set = PETSC_FALSE; 9217 } 9218 PetscFunctionReturn(PETSC_SUCCESS); 9219 } 9220 9221 /*@ 9222 MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state 9223 9224 Not Collective 9225 9226 Input Parameter: 9227 . A - the matrix to check 9228 9229 Output Parameters: 9230 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid) 9231 - flg - the result (only valid if set is `PETSC_TRUE`) 9232 9233 Level: advanced 9234 9235 Notes: 9236 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). 9237 9238 One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD 9239 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`) 9240 9241 .seealso: `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9242 @*/ 9243 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg) 9244 { 9245 PetscFunctionBegin; 9246 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9247 PetscValidBoolPointer(set, 2); 9248 PetscValidBoolPointer(flg, 3); 9249 if (A->spd != PETSC_BOOL3_UNKNOWN) { 9250 *set = PETSC_TRUE; 9251 *flg = PetscBool3ToBool(A->spd); 9252 } else { 9253 *set = PETSC_FALSE; 9254 } 9255 PetscFunctionReturn(PETSC_SUCCESS); 9256 } 9257 9258 /*@ 9259 MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state 9260 9261 Not Collective 9262 9263 Input Parameter: 9264 . A - the matrix to check 9265 9266 Output Parameters: 9267 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid) 9268 - flg - the result (only valid if set is `PETSC_TRUE`) 9269 9270 Level: advanced 9271 9272 Notes: 9273 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()` 9274 if you want it explicitly checked 9275 9276 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9277 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9278 9279 .seealso: `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()` 9280 @*/ 9281 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg) 9282 { 9283 PetscFunctionBegin; 9284 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9285 PetscValidBoolPointer(set, 2); 9286 PetscValidBoolPointer(flg, 3); 9287 if (A->hermitian != PETSC_BOOL3_UNKNOWN) { 9288 *set = PETSC_TRUE; 9289 *flg = PetscBool3ToBool(A->hermitian); 9290 } else { 9291 *set = PETSC_FALSE; 9292 } 9293 PetscFunctionReturn(PETSC_SUCCESS); 9294 } 9295 9296 /*@ 9297 MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric 9298 9299 Collective on Mat 9300 9301 Input Parameter: 9302 . A - the matrix to test 9303 9304 Output Parameters: 9305 . flg - the result 9306 9307 Level: intermediate 9308 9309 Notes: 9310 If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()` 9311 9312 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 9313 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9314 9315 .seealso: `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()` 9316 @*/ 9317 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg) 9318 { 9319 PetscFunctionBegin; 9320 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9321 PetscValidBoolPointer(flg, 2); 9322 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9323 *flg = PetscBool3ToBool(A->structurally_symmetric); 9324 } else { 9325 PetscUseTypeMethod(A, isstructurallysymmetric, flg); 9326 PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg)); 9327 } 9328 PetscFunctionReturn(PETSC_SUCCESS); 9329 } 9330 9331 /*@ 9332 MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state 9333 9334 Not Collective 9335 9336 Input Parameter: 9337 . A - the matrix to check 9338 9339 Output Parameters: 9340 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid) 9341 - flg - the result (only valid if set is PETSC_TRUE) 9342 9343 Level: advanced 9344 9345 Notes: 9346 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 9347 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9348 9349 Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation) 9350 9351 .seealso: `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9352 @*/ 9353 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9354 { 9355 PetscFunctionBegin; 9356 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9357 PetscValidBoolPointer(set, 2); 9358 PetscValidBoolPointer(flg, 3); 9359 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9360 *set = PETSC_TRUE; 9361 *flg = PetscBool3ToBool(A->structurally_symmetric); 9362 } else { 9363 *set = PETSC_FALSE; 9364 } 9365 PetscFunctionReturn(PETSC_SUCCESS); 9366 } 9367 9368 /*@ 9369 MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need 9370 to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process 9371 9372 Not collective 9373 9374 Input Parameter: 9375 . mat - the matrix 9376 9377 Output Parameters: 9378 + nstash - the size of the stash 9379 . reallocs - the number of additional mallocs incurred. 9380 . bnstash - the size of the block stash 9381 - breallocs - the number of additional mallocs incurred.in the block stash 9382 9383 Level: advanced 9384 9385 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()` 9386 @*/ 9387 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs) 9388 { 9389 PetscFunctionBegin; 9390 PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs)); 9391 PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs)); 9392 PetscFunctionReturn(PETSC_SUCCESS); 9393 } 9394 9395 /*@C 9396 MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same 9397 parallel layout, `PetscLayout` for rows and columns 9398 9399 Collective 9400 9401 Input Parameter: 9402 . mat - the matrix 9403 9404 Output Parameters: 9405 + right - (optional) vector that the matrix can be multiplied against 9406 - left - (optional) vector that the matrix vector product can be stored in 9407 9408 Level: advanced 9409 9410 Notes: 9411 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()`. 9412 9413 These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed 9414 9415 .seealso: `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()` 9416 @*/ 9417 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left) 9418 { 9419 PetscFunctionBegin; 9420 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9421 PetscValidType(mat, 1); 9422 if (mat->ops->getvecs) { 9423 PetscUseTypeMethod(mat, getvecs, right, left); 9424 } else { 9425 PetscInt rbs, cbs; 9426 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 9427 if (right) { 9428 PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup"); 9429 PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), right)); 9430 PetscCall(VecSetSizes(*right, mat->cmap->n, PETSC_DETERMINE)); 9431 PetscCall(VecSetBlockSize(*right, cbs)); 9432 PetscCall(VecSetType(*right, mat->defaultvectype)); 9433 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9434 if (mat->boundtocpu && mat->bindingpropagates) { 9435 PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE)); 9436 PetscCall(VecBindToCPU(*right, PETSC_TRUE)); 9437 } 9438 #endif 9439 PetscCall(PetscLayoutReference(mat->cmap, &(*right)->map)); 9440 } 9441 if (left) { 9442 PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup"); 9443 PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), left)); 9444 PetscCall(VecSetSizes(*left, mat->rmap->n, PETSC_DETERMINE)); 9445 PetscCall(VecSetBlockSize(*left, rbs)); 9446 PetscCall(VecSetType(*left, mat->defaultvectype)); 9447 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9448 if (mat->boundtocpu && mat->bindingpropagates) { 9449 PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE)); 9450 PetscCall(VecBindToCPU(*left, PETSC_TRUE)); 9451 } 9452 #endif 9453 PetscCall(PetscLayoutReference(mat->rmap, &(*left)->map)); 9454 } 9455 } 9456 PetscFunctionReturn(PETSC_SUCCESS); 9457 } 9458 9459 /*@C 9460 MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure 9461 with default values. 9462 9463 Not Collective 9464 9465 Input Parameters: 9466 . info - the `MatFactorInfo` data structure 9467 9468 Level: developer 9469 9470 Notes: 9471 The solvers are generally used through the `KSP` and `PC` objects, for example 9472 `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC` 9473 9474 Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed 9475 9476 Developer Note: 9477 The Fortran interface is not autogenerated as the 9478 interface definition cannot be generated correctly [due to `MatFactorInfo`] 9479 9480 .seealso: `Mat`, `MatGetFactor()`, `MatFactorInfo` 9481 @*/ 9482 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info) 9483 { 9484 PetscFunctionBegin; 9485 PetscCall(PetscMemzero(info, sizeof(MatFactorInfo))); 9486 PetscFunctionReturn(PETSC_SUCCESS); 9487 } 9488 9489 /*@ 9490 MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed 9491 9492 Collective 9493 9494 Input Parameters: 9495 + mat - the factored matrix 9496 - is - the index set defining the Schur indices (0-based) 9497 9498 Level: advanced 9499 9500 Notes: 9501 Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system. 9502 9503 You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call. 9504 9505 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9506 9507 .seealso: `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`, 9508 `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9509 @*/ 9510 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is) 9511 { 9512 PetscErrorCode (*f)(Mat, IS); 9513 9514 PetscFunctionBegin; 9515 PetscValidType(mat, 1); 9516 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9517 PetscValidType(is, 2); 9518 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 9519 PetscCheckSameComm(mat, 1, is, 2); 9520 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 9521 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f)); 9522 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO"); 9523 PetscCall(MatDestroy(&mat->schur)); 9524 PetscCall((*f)(mat, is)); 9525 PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created"); 9526 PetscFunctionReturn(PETSC_SUCCESS); 9527 } 9528 9529 /*@ 9530 MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step 9531 9532 Logically Collective 9533 9534 Input Parameters: 9535 + F - the factored matrix obtained by calling `MatGetFactor()` 9536 . S - location where to return the Schur complement, can be `NULL` 9537 - status - the status of the Schur complement matrix, can be `NULL` 9538 9539 Level: advanced 9540 9541 Notes: 9542 You must call `MatFactorSetSchurIS()` before calling this routine. 9543 9544 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9545 9546 The routine provides a copy of the Schur matrix stored within the solver data structures. 9547 The caller must destroy the object when it is no longer needed. 9548 If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse. 9549 9550 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) 9551 9552 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9553 9554 Developer Note: 9555 The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc 9556 matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix. 9557 9558 .seealso: `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9559 @*/ 9560 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9561 { 9562 PetscFunctionBegin; 9563 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9564 if (S) PetscValidPointer(S, 2); 9565 if (status) PetscValidPointer(status, 3); 9566 if (S) { 9567 PetscErrorCode (*f)(Mat, Mat *); 9568 9569 PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f)); 9570 if (f) { 9571 PetscCall((*f)(F, S)); 9572 } else { 9573 PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S)); 9574 } 9575 } 9576 if (status) *status = F->schur_status; 9577 PetscFunctionReturn(PETSC_SUCCESS); 9578 } 9579 9580 /*@ 9581 MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix 9582 9583 Logically Collective 9584 9585 Input Parameters: 9586 + F - the factored matrix obtained by calling `MatGetFactor()` 9587 . *S - location where to return the Schur complement, can be `NULL` 9588 - status - the status of the Schur complement matrix, can be `NULL` 9589 9590 Level: advanced 9591 9592 Notes: 9593 You must call `MatFactorSetSchurIS()` before calling this routine. 9594 9595 Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS` 9596 9597 The routine returns a the Schur Complement stored within the data structures of the solver. 9598 9599 If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement. 9600 9601 The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed. 9602 9603 Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix 9604 9605 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9606 9607 .seealso: `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9608 @*/ 9609 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9610 { 9611 PetscFunctionBegin; 9612 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9613 if (S) PetscValidPointer(S, 2); 9614 if (status) PetscValidPointer(status, 3); 9615 if (S) *S = F->schur; 9616 if (status) *status = F->schur_status; 9617 PetscFunctionReturn(PETSC_SUCCESS); 9618 } 9619 9620 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F) 9621 { 9622 Mat S = F->schur; 9623 9624 PetscFunctionBegin; 9625 switch (F->schur_status) { 9626 case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through 9627 case MAT_FACTOR_SCHUR_INVERTED: 9628 if (S) { 9629 S->ops->solve = NULL; 9630 S->ops->matsolve = NULL; 9631 S->ops->solvetranspose = NULL; 9632 S->ops->matsolvetranspose = NULL; 9633 S->ops->solveadd = NULL; 9634 S->ops->solvetransposeadd = NULL; 9635 S->factortype = MAT_FACTOR_NONE; 9636 PetscCall(PetscFree(S->solvertype)); 9637 } 9638 case MAT_FACTOR_SCHUR_FACTORED: // fall-through 9639 break; 9640 default: 9641 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9642 } 9643 PetscFunctionReturn(PETSC_SUCCESS); 9644 } 9645 9646 /*@ 9647 MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()` 9648 9649 Logically Collective 9650 9651 Input Parameters: 9652 + F - the factored matrix obtained by calling `MatGetFactor()` 9653 . *S - location where the Schur complement is stored 9654 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`) 9655 9656 Level: advanced 9657 9658 .seealso: `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9659 @*/ 9660 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status) 9661 { 9662 PetscFunctionBegin; 9663 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9664 if (S) { 9665 PetscValidHeaderSpecific(*S, MAT_CLASSID, 2); 9666 *S = NULL; 9667 } 9668 F->schur_status = status; 9669 PetscCall(MatFactorUpdateSchurStatus_Private(F)); 9670 PetscFunctionReturn(PETSC_SUCCESS); 9671 } 9672 9673 /*@ 9674 MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step 9675 9676 Logically Collective 9677 9678 Input Parameters: 9679 + F - the factored matrix obtained by calling `MatGetFactor()` 9680 . rhs - location where the right hand side of the Schur complement system is stored 9681 - sol - location where the solution of the Schur complement system has to be returned 9682 9683 Level: advanced 9684 9685 Notes: 9686 The sizes of the vectors should match the size of the Schur complement 9687 9688 Must be called after `MatFactorSetSchurIS()` 9689 9690 .seealso: `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()` 9691 @*/ 9692 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol) 9693 { 9694 PetscFunctionBegin; 9695 PetscValidType(F, 1); 9696 PetscValidType(rhs, 2); 9697 PetscValidType(sol, 3); 9698 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9699 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9700 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9701 PetscCheckSameComm(F, 1, rhs, 2); 9702 PetscCheckSameComm(F, 1, sol, 3); 9703 PetscCall(MatFactorFactorizeSchurComplement(F)); 9704 switch (F->schur_status) { 9705 case MAT_FACTOR_SCHUR_FACTORED: 9706 PetscCall(MatSolveTranspose(F->schur, rhs, sol)); 9707 break; 9708 case MAT_FACTOR_SCHUR_INVERTED: 9709 PetscCall(MatMultTranspose(F->schur, rhs, sol)); 9710 break; 9711 default: 9712 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9713 } 9714 PetscFunctionReturn(PETSC_SUCCESS); 9715 } 9716 9717 /*@ 9718 MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step 9719 9720 Logically Collective 9721 9722 Input Parameters: 9723 + F - the factored matrix obtained by calling `MatGetFactor()` 9724 . rhs - location where the right hand side of the Schur complement system is stored 9725 - sol - location where the solution of the Schur complement system has to be returned 9726 9727 Level: advanced 9728 9729 Notes: 9730 The sizes of the vectors should match the size of the Schur complement 9731 9732 Must be called after `MatFactorSetSchurIS()` 9733 9734 .seealso: `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()` 9735 @*/ 9736 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol) 9737 { 9738 PetscFunctionBegin; 9739 PetscValidType(F, 1); 9740 PetscValidType(rhs, 2); 9741 PetscValidType(sol, 3); 9742 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9743 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9744 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9745 PetscCheckSameComm(F, 1, rhs, 2); 9746 PetscCheckSameComm(F, 1, sol, 3); 9747 PetscCall(MatFactorFactorizeSchurComplement(F)); 9748 switch (F->schur_status) { 9749 case MAT_FACTOR_SCHUR_FACTORED: 9750 PetscCall(MatSolve(F->schur, rhs, sol)); 9751 break; 9752 case MAT_FACTOR_SCHUR_INVERTED: 9753 PetscCall(MatMult(F->schur, rhs, sol)); 9754 break; 9755 default: 9756 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9757 } 9758 PetscFunctionReturn(PETSC_SUCCESS); 9759 } 9760 9761 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat); 9762 #if PetscDefined(HAVE_CUDA) 9763 PETSC_EXTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Private(Mat); 9764 #endif 9765 9766 /* Schur status updated in the interface */ 9767 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F) 9768 { 9769 Mat S = F->schur; 9770 9771 PetscFunctionBegin; 9772 if (S) { 9773 PetscMPIInt size; 9774 PetscBool isdense, isdensecuda; 9775 9776 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size)); 9777 PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented"); 9778 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense)); 9779 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda)); 9780 PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name); 9781 PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0)); 9782 if (isdense) { 9783 PetscCall(MatSeqDenseInvertFactors_Private(S)); 9784 } else if (isdensecuda) { 9785 #if defined(PETSC_HAVE_CUDA) 9786 PetscCall(MatSeqDenseCUDAInvertFactors_Private(S)); 9787 #endif 9788 } 9789 PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0)); 9790 } 9791 PetscFunctionReturn(PETSC_SUCCESS); 9792 } 9793 9794 /*@ 9795 MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step 9796 9797 Logically Collective on F 9798 9799 Input Parameters: 9800 . F - the factored matrix obtained by calling `MatGetFactor()` 9801 9802 Level: advanced 9803 9804 Notes: 9805 Must be called after `MatFactorSetSchurIS()`. 9806 9807 Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it. 9808 9809 .seealso: `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()` 9810 @*/ 9811 PetscErrorCode MatFactorInvertSchurComplement(Mat F) 9812 { 9813 PetscFunctionBegin; 9814 PetscValidType(F, 1); 9815 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9816 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS); 9817 PetscCall(MatFactorFactorizeSchurComplement(F)); 9818 PetscCall(MatFactorInvertSchurComplement_Private(F)); 9819 F->schur_status = MAT_FACTOR_SCHUR_INVERTED; 9820 PetscFunctionReturn(PETSC_SUCCESS); 9821 } 9822 9823 /*@ 9824 MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step 9825 9826 Logically Collective 9827 9828 Input Parameters: 9829 . F - the factored matrix obtained by calling `MatGetFactor()` 9830 9831 Level: advanced 9832 9833 Note: 9834 Must be called after `MatFactorSetSchurIS()` 9835 9836 .seealso: `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()` 9837 @*/ 9838 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F) 9839 { 9840 MatFactorInfo info; 9841 9842 PetscFunctionBegin; 9843 PetscValidType(F, 1); 9844 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9845 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS); 9846 PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0)); 9847 if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */ 9848 PetscCall(MatCholeskyFactor(F->schur, NULL, &info)); 9849 } else { 9850 PetscCall(MatLUFactor(F->schur, NULL, NULL, &info)); 9851 } 9852 PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0)); 9853 F->schur_status = MAT_FACTOR_SCHUR_FACTORED; 9854 PetscFunctionReturn(PETSC_SUCCESS); 9855 } 9856 9857 /*@ 9858 MatPtAP - Creates the matrix product C = P^T * A * P 9859 9860 Neighbor-wise Collective 9861 9862 Input Parameters: 9863 + A - the matrix 9864 . P - the projection matrix 9865 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9866 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate 9867 if the result is a dense matrix this is irrelevant 9868 9869 Output Parameters: 9870 . C - the product matrix 9871 9872 Level: intermediate 9873 9874 Notes: 9875 C will be created and must be destroyed by the user with `MatDestroy()`. 9876 9877 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9878 9879 Developer Note: 9880 For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`. 9881 9882 .seealso: `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()` 9883 @*/ 9884 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C) 9885 { 9886 PetscFunctionBegin; 9887 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 9888 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9889 9890 if (scall == MAT_INITIAL_MATRIX) { 9891 PetscCall(MatProductCreate(A, P, NULL, C)); 9892 PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP)); 9893 PetscCall(MatProductSetAlgorithm(*C, "default")); 9894 PetscCall(MatProductSetFill(*C, fill)); 9895 9896 (*C)->product->api_user = PETSC_TRUE; 9897 PetscCall(MatProductSetFromOptions(*C)); 9898 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); 9899 PetscCall(MatProductSymbolic(*C)); 9900 } else { /* scall == MAT_REUSE_MATRIX */ 9901 PetscCall(MatProductReplaceMats(A, P, NULL, *C)); 9902 } 9903 9904 PetscCall(MatProductNumeric(*C)); 9905 (*C)->symmetric = A->symmetric; 9906 (*C)->spd = A->spd; 9907 PetscFunctionReturn(PETSC_SUCCESS); 9908 } 9909 9910 /*@ 9911 MatRARt - Creates the matrix product C = R * A * R^T 9912 9913 Neighbor-wise Collective 9914 9915 Input Parameters: 9916 + A - the matrix 9917 . R - the projection matrix 9918 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9919 - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate 9920 if the result is a dense matrix this is irrelevant 9921 9922 Output Parameters: 9923 . C - the product matrix 9924 9925 Level: intermediate 9926 9927 Notes: 9928 C will be created and must be destroyed by the user with `MatDestroy()`. 9929 9930 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9931 9932 This routine is currently only implemented for pairs of `MATAIJ` matrices and classes 9933 which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes, 9934 parallel MatRARt is implemented via explicit transpose of R, which could be very expensive. 9935 We recommend using MatPtAP(). 9936 9937 .seealso: `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()` 9938 @*/ 9939 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C) 9940 { 9941 PetscFunctionBegin; 9942 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 9943 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9944 9945 if (scall == MAT_INITIAL_MATRIX) { 9946 PetscCall(MatProductCreate(A, R, NULL, C)); 9947 PetscCall(MatProductSetType(*C, MATPRODUCT_RARt)); 9948 PetscCall(MatProductSetAlgorithm(*C, "default")); 9949 PetscCall(MatProductSetFill(*C, fill)); 9950 9951 (*C)->product->api_user = PETSC_TRUE; 9952 PetscCall(MatProductSetFromOptions(*C)); 9953 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); 9954 PetscCall(MatProductSymbolic(*C)); 9955 } else { /* scall == MAT_REUSE_MATRIX */ 9956 PetscCall(MatProductReplaceMats(A, R, NULL, *C)); 9957 } 9958 9959 PetscCall(MatProductNumeric(*C)); 9960 if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 9961 PetscFunctionReturn(PETSC_SUCCESS); 9962 } 9963 9964 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C) 9965 { 9966 PetscFunctionBegin; 9967 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9968 9969 if (scall == MAT_INITIAL_MATRIX) { 9970 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype])); 9971 PetscCall(MatProductCreate(A, B, NULL, C)); 9972 PetscCall(MatProductSetType(*C, ptype)); 9973 PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT)); 9974 PetscCall(MatProductSetFill(*C, fill)); 9975 9976 (*C)->product->api_user = PETSC_TRUE; 9977 PetscCall(MatProductSetFromOptions(*C)); 9978 PetscCall(MatProductSymbolic(*C)); 9979 } else { /* scall == MAT_REUSE_MATRIX */ 9980 Mat_Product *product = (*C)->product; 9981 PetscBool isdense; 9982 9983 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, "")); 9984 if (isdense && product && product->type != ptype) { 9985 PetscCall(MatProductClear(*C)); 9986 product = NULL; 9987 } 9988 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype])); 9989 if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */ 9990 PetscCheck(isdense, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first"); 9991 PetscCall(MatProductCreate_Private(A, B, NULL, *C)); 9992 product = (*C)->product; 9993 product->fill = fill; 9994 product->api_user = PETSC_TRUE; 9995 product->clear = PETSC_TRUE; 9996 9997 PetscCall(MatProductSetType(*C, ptype)); 9998 PetscCall(MatProductSetFromOptions(*C)); 9999 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); 10000 PetscCall(MatProductSymbolic(*C)); 10001 } else { /* user may change input matrices A or B when REUSE */ 10002 PetscCall(MatProductReplaceMats(A, B, NULL, *C)); 10003 } 10004 } 10005 PetscCall(MatProductNumeric(*C)); 10006 PetscFunctionReturn(PETSC_SUCCESS); 10007 } 10008 10009 /*@ 10010 MatMatMult - Performs matrix-matrix multiplication C=A*B. 10011 10012 Neighbor-wise Collective 10013 10014 Input Parameters: 10015 + A - the left matrix 10016 . B - the right matrix 10017 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10018 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate 10019 if the result is a dense matrix this is irrelevant 10020 10021 Output Parameters: 10022 . C - the product matrix 10023 10024 Notes: 10025 Unless scall is `MAT_REUSE_MATRIX` C will be created. 10026 10027 `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 10028 call to this function with `MAT_INITIAL_MATRIX`. 10029 10030 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed. 10031 10032 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`, 10033 rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse. 10034 10035 Example of Usage: 10036 .vb 10037 MatProductCreate(A,B,NULL,&C); 10038 MatProductSetType(C,MATPRODUCT_AB); 10039 MatProductSymbolic(C); 10040 MatProductNumeric(C); // compute C=A * B 10041 MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1 10042 MatProductNumeric(C); 10043 MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1 10044 MatProductNumeric(C); 10045 .ve 10046 10047 Level: intermediate 10048 10049 .seealso: `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()` 10050 @*/ 10051 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10052 { 10053 PetscFunctionBegin; 10054 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C)); 10055 PetscFunctionReturn(PETSC_SUCCESS); 10056 } 10057 10058 /*@ 10059 MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T. 10060 10061 Neighbor-wise Collective 10062 10063 Input Parameters: 10064 + A - the left matrix 10065 . B - the right matrix 10066 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10067 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 10068 10069 Output Parameters: 10070 . C - the product matrix 10071 10072 Level: intermediate 10073 10074 Notes: 10075 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10076 10077 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call 10078 10079 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10080 actually needed. 10081 10082 This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class, 10083 and for pairs of `MATMPIDENSE` matrices. 10084 10085 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt` 10086 10087 Options Database Keys: 10088 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the 10089 first redundantly copies the transposed B matrix on each process and requiers O(log P) communication complexity; 10090 the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity. 10091 10092 .seealso: `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductCreate()`, `MatProductAlgorithm`, `MatProductType`, `MATPRODUCT_ABt` 10093 @*/ 10094 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10095 { 10096 PetscFunctionBegin; 10097 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C)); 10098 if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10099 PetscFunctionReturn(PETSC_SUCCESS); 10100 } 10101 10102 /*@ 10103 MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B. 10104 10105 Neighbor-wise Collective 10106 10107 Input Parameters: 10108 + A - the left matrix 10109 . B - the right matrix 10110 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10111 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 10112 10113 Output Parameters: 10114 . C - the product matrix 10115 10116 Level: intermediate 10117 10118 Notes: 10119 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10120 10121 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call. 10122 10123 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB` 10124 10125 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10126 actually needed. 10127 10128 This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes 10129 which inherit from `MATSEQAIJ`. C will be of the same type as the input matrices. 10130 10131 .seealso: `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()` 10132 @*/ 10133 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10134 { 10135 PetscFunctionBegin; 10136 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C)); 10137 PetscFunctionReturn(PETSC_SUCCESS); 10138 } 10139 10140 /*@ 10141 MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C. 10142 10143 Neighbor-wise Collective 10144 10145 Input Parameters: 10146 + A - the left matrix 10147 . B - the middle matrix 10148 . C - the right matrix 10149 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10150 - 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 10151 if the result is a dense matrix this is irrelevant 10152 10153 Output Parameters: 10154 . D - the product matrix 10155 10156 Level: intermediate 10157 10158 Notes: 10159 Unless scall is `MAT_REUSE_MATRIX` D will be created. 10160 10161 `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call 10162 10163 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC` 10164 10165 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10166 actually needed. 10167 10168 If you have many matrices with the same non-zero structure to multiply, you 10169 should use `MAT_REUSE_MATRIX` in all calls but the first 10170 10171 .seealso: `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()` 10172 @*/ 10173 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D) 10174 { 10175 PetscFunctionBegin; 10176 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6); 10177 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10178 10179 if (scall == MAT_INITIAL_MATRIX) { 10180 PetscCall(MatProductCreate(A, B, C, D)); 10181 PetscCall(MatProductSetType(*D, MATPRODUCT_ABC)); 10182 PetscCall(MatProductSetAlgorithm(*D, "default")); 10183 PetscCall(MatProductSetFill(*D, fill)); 10184 10185 (*D)->product->api_user = PETSC_TRUE; 10186 PetscCall(MatProductSetFromOptions(*D)); 10187 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, 10188 ((PetscObject)C)->type_name); 10189 PetscCall(MatProductSymbolic(*D)); 10190 } else { /* user may change input matrices when REUSE */ 10191 PetscCall(MatProductReplaceMats(A, B, C, *D)); 10192 } 10193 PetscCall(MatProductNumeric(*D)); 10194 PetscFunctionReturn(PETSC_SUCCESS); 10195 } 10196 10197 /*@ 10198 MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators. 10199 10200 Collective 10201 10202 Input Parameters: 10203 + mat - the matrix 10204 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices) 10205 . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used) 10206 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10207 10208 Output Parameter: 10209 . matredundant - redundant matrix 10210 10211 Level: advanced 10212 10213 Notes: 10214 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 10215 original matrix has not changed from that last call to MatCreateRedundantMatrix(). 10216 10217 This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before 10218 calling it. 10219 10220 `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be. 10221 10222 .seealso: `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubComm` 10223 @*/ 10224 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant) 10225 { 10226 MPI_Comm comm; 10227 PetscMPIInt size; 10228 PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs; 10229 Mat_Redundant *redund = NULL; 10230 PetscSubcomm psubcomm = NULL; 10231 MPI_Comm subcomm_in = subcomm; 10232 Mat *matseq; 10233 IS isrow, iscol; 10234 PetscBool newsubcomm = PETSC_FALSE; 10235 10236 PetscFunctionBegin; 10237 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10238 if (nsubcomm && reuse == MAT_REUSE_MATRIX) { 10239 PetscValidPointer(*matredundant, 5); 10240 PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5); 10241 } 10242 10243 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10244 if (size == 1 || nsubcomm == 1) { 10245 if (reuse == MAT_INITIAL_MATRIX) { 10246 PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant)); 10247 } else { 10248 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"); 10249 PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN)); 10250 } 10251 PetscFunctionReturn(PETSC_SUCCESS); 10252 } 10253 10254 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10255 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10256 MatCheckPreallocated(mat, 1); 10257 10258 PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0)); 10259 if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */ 10260 /* create psubcomm, then get subcomm */ 10261 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10262 PetscCallMPI(MPI_Comm_size(comm, &size)); 10263 PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size); 10264 10265 PetscCall(PetscSubcommCreate(comm, &psubcomm)); 10266 PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm)); 10267 PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS)); 10268 PetscCall(PetscSubcommSetFromOptions(psubcomm)); 10269 PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL)); 10270 newsubcomm = PETSC_TRUE; 10271 PetscCall(PetscSubcommDestroy(&psubcomm)); 10272 } 10273 10274 /* get isrow, iscol and a local sequential matrix matseq[0] */ 10275 if (reuse == MAT_INITIAL_MATRIX) { 10276 mloc_sub = PETSC_DECIDE; 10277 nloc_sub = PETSC_DECIDE; 10278 if (bs < 1) { 10279 PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M)); 10280 PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N)); 10281 } else { 10282 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M)); 10283 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N)); 10284 } 10285 PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm)); 10286 rstart = rend - mloc_sub; 10287 PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow)); 10288 PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol)); 10289 } else { /* reuse == MAT_REUSE_MATRIX */ 10290 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"); 10291 /* retrieve subcomm */ 10292 PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm)); 10293 redund = (*matredundant)->redundant; 10294 isrow = redund->isrow; 10295 iscol = redund->iscol; 10296 matseq = redund->matseq; 10297 } 10298 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq)); 10299 10300 /* get matredundant over subcomm */ 10301 if (reuse == MAT_INITIAL_MATRIX) { 10302 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant)); 10303 10304 /* create a supporting struct and attach it to C for reuse */ 10305 PetscCall(PetscNew(&redund)); 10306 (*matredundant)->redundant = redund; 10307 redund->isrow = isrow; 10308 redund->iscol = iscol; 10309 redund->matseq = matseq; 10310 if (newsubcomm) { 10311 redund->subcomm = subcomm; 10312 } else { 10313 redund->subcomm = MPI_COMM_NULL; 10314 } 10315 } else { 10316 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant)); 10317 } 10318 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 10319 if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) { 10320 PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE)); 10321 PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE)); 10322 } 10323 #endif 10324 PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0)); 10325 PetscFunctionReturn(PETSC_SUCCESS); 10326 } 10327 10328 /*@C 10329 MatGetMultiProcBlock - Create multiple 'parallel submatrices' from 10330 a given `Mat`. Each submatrix can span multiple procs. 10331 10332 Collective 10333 10334 Input Parameters: 10335 + mat - the matrix 10336 . subcomm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))` 10337 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10338 10339 Output Parameter: 10340 . subMat - parallel sub-matrices each spanning a given `subcomm` 10341 10342 Level: advanced 10343 10344 Notes: 10345 The submatrix partition across processors is dictated by `subComm` a 10346 communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm` 10347 is not restricted to be grouped with consecutive original ranks. 10348 10349 Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices 10350 map directly to the layout of the original matrix [wrt the local 10351 row,col partitioning]. So the original 'DiagonalMat' naturally maps 10352 into the 'DiagonalMat' of the `subMat`, hence it is used directly from 10353 the `subMat`. However the offDiagMat looses some columns - and this is 10354 reconstructed with `MatSetValues()` 10355 10356 This is used by `PCBJACOBI` when a single block spans multiple MPI ranks 10357 10358 .seealso: `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI` 10359 @*/ 10360 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) 10361 { 10362 PetscMPIInt commsize, subCommSize; 10363 10364 PetscFunctionBegin; 10365 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize)); 10366 PetscCallMPI(MPI_Comm_size(subComm, &subCommSize)); 10367 PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize); 10368 10369 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"); 10370 PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10371 PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat); 10372 PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10373 PetscFunctionReturn(PETSC_SUCCESS); 10374 } 10375 10376 /*@ 10377 MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering 10378 10379 Not Collective 10380 10381 Input Parameters: 10382 + mat - matrix to extract local submatrix from 10383 . isrow - local row indices for submatrix 10384 - iscol - local column indices for submatrix 10385 10386 Output Parameter: 10387 . submat - the submatrix 10388 10389 Level: intermediate 10390 10391 Notes: 10392 `submat` should be disposed of with `MatRestoreLocalSubMatrix()`. 10393 10394 Depending on the format of `mat`, the returned submat may not implement `MatMult()`. Its communicator may be 10395 the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of `mat`'s. 10396 10397 `submat` always implements `MatSetValuesLocal()`. If `isrow` and `iscol` have the same block size, then 10398 `MatSetValuesBlockedLocal()` will also be implemented. 10399 10400 `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`. 10401 Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided. 10402 10403 .seealso: `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()` 10404 @*/ 10405 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10406 { 10407 PetscFunctionBegin; 10408 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10409 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10410 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10411 PetscCheckSameComm(isrow, 2, iscol, 3); 10412 PetscValidPointer(submat, 4); 10413 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call"); 10414 10415 if (mat->ops->getlocalsubmatrix) { 10416 PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat); 10417 } else { 10418 PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat)); 10419 } 10420 PetscFunctionReturn(PETSC_SUCCESS); 10421 } 10422 10423 /*@ 10424 MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()` 10425 10426 Not Collective 10427 10428 Input Parameters: 10429 + mat - matrix to extract local submatrix from 10430 . isrow - local row indices for submatrix 10431 . iscol - local column indices for submatrix 10432 - submat - the submatrix 10433 10434 Level: intermediate 10435 10436 .seealso: `Mat`, `MatGetLocalSubMatrix()` 10437 @*/ 10438 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10439 { 10440 PetscFunctionBegin; 10441 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10442 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10443 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10444 PetscCheckSameComm(isrow, 2, iscol, 3); 10445 PetscValidPointer(submat, 4); 10446 if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4); 10447 10448 if (mat->ops->restorelocalsubmatrix) { 10449 PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat); 10450 } else { 10451 PetscCall(MatDestroy(submat)); 10452 } 10453 *submat = NULL; 10454 PetscFunctionReturn(PETSC_SUCCESS); 10455 } 10456 10457 /*@ 10458 MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix 10459 10460 Collective 10461 10462 Input Parameter: 10463 . mat - the matrix 10464 10465 Output Parameter: 10466 . is - if any rows have zero diagonals this contains the list of them 10467 10468 Level: developer 10469 10470 .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10471 @*/ 10472 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is) 10473 { 10474 PetscFunctionBegin; 10475 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10476 PetscValidType(mat, 1); 10477 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10478 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10479 10480 if (!mat->ops->findzerodiagonals) { 10481 Vec diag; 10482 const PetscScalar *a; 10483 PetscInt *rows; 10484 PetscInt rStart, rEnd, r, nrow = 0; 10485 10486 PetscCall(MatCreateVecs(mat, &diag, NULL)); 10487 PetscCall(MatGetDiagonal(mat, diag)); 10488 PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd)); 10489 PetscCall(VecGetArrayRead(diag, &a)); 10490 for (r = 0; r < rEnd - rStart; ++r) 10491 if (a[r] == 0.0) ++nrow; 10492 PetscCall(PetscMalloc1(nrow, &rows)); 10493 nrow = 0; 10494 for (r = 0; r < rEnd - rStart; ++r) 10495 if (a[r] == 0.0) rows[nrow++] = r + rStart; 10496 PetscCall(VecRestoreArrayRead(diag, &a)); 10497 PetscCall(VecDestroy(&diag)); 10498 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is)); 10499 } else { 10500 PetscUseTypeMethod(mat, findzerodiagonals, is); 10501 } 10502 PetscFunctionReturn(PETSC_SUCCESS); 10503 } 10504 10505 /*@ 10506 MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size) 10507 10508 Collective 10509 10510 Input Parameter: 10511 . mat - the matrix 10512 10513 Output Parameter: 10514 . is - contains the list of rows with off block diagonal entries 10515 10516 Level: developer 10517 10518 .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10519 @*/ 10520 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is) 10521 { 10522 PetscFunctionBegin; 10523 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10524 PetscValidType(mat, 1); 10525 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10526 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10527 10528 PetscUseTypeMethod(mat, findoffblockdiagonalentries, is); 10529 PetscFunctionReturn(PETSC_SUCCESS); 10530 } 10531 10532 /*@C 10533 MatInvertBlockDiagonal - Inverts the block diagonal entries. 10534 10535 Collective; No Fortran Support 10536 10537 Input Parameters: 10538 . mat - the matrix 10539 10540 Output Parameters: 10541 . values - the block inverses in column major order (FORTRAN-like) 10542 10543 Level: advanced 10544 10545 Notes: 10546 The size of the blocks is determined by the block size of the matrix. 10547 10548 The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case 10549 10550 The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size 10551 10552 .seealso: `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()` 10553 @*/ 10554 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values) 10555 { 10556 PetscFunctionBegin; 10557 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10558 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10559 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10560 PetscUseTypeMethod(mat, invertblockdiagonal, values); 10561 PetscFunctionReturn(PETSC_SUCCESS); 10562 } 10563 10564 /*@C 10565 MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries. 10566 10567 Collective; No Fortran Support 10568 10569 Input Parameters: 10570 + mat - the matrix 10571 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()` 10572 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()` 10573 10574 Output Parameters: 10575 . values - the block inverses in column major order (FORTRAN-like) 10576 10577 Level: advanced 10578 10579 Notes: 10580 Use `MatInvertBlockDiagonal()` if all blocks have the same size 10581 10582 The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case 10583 10584 .seealso: `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()` 10585 @*/ 10586 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values) 10587 { 10588 PetscFunctionBegin; 10589 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10590 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10591 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10592 PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values); 10593 PetscFunctionReturn(PETSC_SUCCESS); 10594 } 10595 10596 /*@ 10597 MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A 10598 10599 Collective on Mat 10600 10601 Input Parameters: 10602 + A - the matrix 10603 - C - matrix with inverted block diagonal of `A`. This matrix should be created and may have its type set. 10604 10605 Level: advanced 10606 10607 Note: 10608 The blocksize of the matrix is used to determine the blocks on the diagonal of `C` 10609 10610 .seealso: `Mat`, `MatInvertBlockDiagonal()` 10611 @*/ 10612 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C) 10613 { 10614 const PetscScalar *vals; 10615 PetscInt *dnnz; 10616 PetscInt m, rstart, rend, bs, i, j; 10617 10618 PetscFunctionBegin; 10619 PetscCall(MatInvertBlockDiagonal(A, &vals)); 10620 PetscCall(MatGetBlockSize(A, &bs)); 10621 PetscCall(MatGetLocalSize(A, &m, NULL)); 10622 PetscCall(MatSetLayouts(C, A->rmap, A->cmap)); 10623 PetscCall(PetscMalloc1(m / bs, &dnnz)); 10624 for (j = 0; j < m / bs; j++) dnnz[j] = 1; 10625 PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL)); 10626 PetscCall(PetscFree(dnnz)); 10627 PetscCall(MatGetOwnershipRange(C, &rstart, &rend)); 10628 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE)); 10629 for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES)); 10630 PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 10631 PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 10632 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE)); 10633 PetscFunctionReturn(PETSC_SUCCESS); 10634 } 10635 10636 /*@C 10637 MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created 10638 via `MatTransposeColoringCreate()`. 10639 10640 Collective on c 10641 10642 Input Parameter: 10643 . c - coloring context 10644 10645 Level: intermediate 10646 10647 .seealso: `Mat`, `MatTransposeColoringCreate()` 10648 @*/ 10649 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c) 10650 { 10651 MatTransposeColoring matcolor = *c; 10652 10653 PetscFunctionBegin; 10654 if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS); 10655 if (--((PetscObject)matcolor)->refct > 0) { 10656 matcolor = NULL; 10657 PetscFunctionReturn(PETSC_SUCCESS); 10658 } 10659 10660 PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow)); 10661 PetscCall(PetscFree(matcolor->rows)); 10662 PetscCall(PetscFree(matcolor->den2sp)); 10663 PetscCall(PetscFree(matcolor->colorforcol)); 10664 PetscCall(PetscFree(matcolor->columns)); 10665 if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart)); 10666 PetscCall(PetscHeaderDestroy(c)); 10667 PetscFunctionReturn(PETSC_SUCCESS); 10668 } 10669 10670 /*@C 10671 MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which 10672 a `MatTransposeColoring` context has been created, computes a dense B^T by applying 10673 `MatTransposeColoring` to sparse B. 10674 10675 Collective on coloring 10676 10677 Input Parameters: 10678 + B - sparse matrix B 10679 . Btdense - symbolic dense matrix B^T 10680 - coloring - coloring context created with `MatTransposeColoringCreate()` 10681 10682 Output Parameter: 10683 . Btdense - dense matrix B^T 10684 10685 Level: developer 10686 10687 Note: 10688 These are used internally for some implementations of `MatRARt()` 10689 10690 .seealso: `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()` 10691 @*/ 10692 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense) 10693 { 10694 PetscFunctionBegin; 10695 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 10696 PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3); 10697 PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10698 10699 PetscCall((B->ops->transcoloringapplysptoden)(coloring, B, Btdense)); 10700 PetscFunctionReturn(PETSC_SUCCESS); 10701 } 10702 10703 /*@C 10704 MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which 10705 a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense 10706 in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix 10707 Csp from Cden. 10708 10709 Collective 10710 10711 Input Parameters: 10712 + coloring - coloring context created with `MatTransposeColoringCreate()` 10713 - Cden - matrix product of a sparse matrix and a dense matrix Btdense 10714 10715 Output Parameter: 10716 . Csp - sparse matrix 10717 10718 Level: developer 10719 10720 Note: 10721 These are used internally for some implementations of `MatRARt()` 10722 10723 .seealso: `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()` 10724 @*/ 10725 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp) 10726 { 10727 PetscFunctionBegin; 10728 PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10729 PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2); 10730 PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3); 10731 10732 PetscCall((Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp)); 10733 PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY)); 10734 PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY)); 10735 PetscFunctionReturn(PETSC_SUCCESS); 10736 } 10737 10738 /*@C 10739 MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T. 10740 10741 Collective 10742 10743 Input Parameters: 10744 + mat - the matrix product C 10745 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()` 10746 10747 Output Parameter: 10748 . color - the new coloring context 10749 10750 Level: intermediate 10751 10752 .seealso: `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`, 10753 `MatTransColoringApplyDenToSp()` 10754 @*/ 10755 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color) 10756 { 10757 MatTransposeColoring c; 10758 MPI_Comm comm; 10759 10760 PetscFunctionBegin; 10761 PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10762 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10763 PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL)); 10764 10765 c->ctype = iscoloring->ctype; 10766 PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c); 10767 10768 *color = c; 10769 PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10770 PetscFunctionReturn(PETSC_SUCCESS); 10771 } 10772 10773 /*@ 10774 MatGetNonzeroState - Returns a 64 bit integer representing the current state of nonzeros in the matrix. If the 10775 matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the 10776 same, otherwise it will be larger 10777 10778 Not Collective 10779 10780 Input Parameter: 10781 . A - the matrix 10782 10783 Output Parameter: 10784 . state - the current state 10785 10786 Level: intermediate 10787 10788 Notes: 10789 You can only compare states from two different calls to the SAME matrix, you cannot compare calls between 10790 different matrices 10791 10792 Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix 10793 10794 Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers. 10795 10796 .seealso: `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()` 10797 @*/ 10798 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state) 10799 { 10800 PetscFunctionBegin; 10801 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10802 *state = mat->nonzerostate; 10803 PetscFunctionReturn(PETSC_SUCCESS); 10804 } 10805 10806 /*@ 10807 MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential 10808 matrices from each processor 10809 10810 Collective 10811 10812 Input Parameters: 10813 + comm - the communicators the parallel matrix will live on 10814 . seqmat - the input sequential matrices 10815 . n - number of local columns (or `PETSC_DECIDE`) 10816 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10817 10818 Output Parameter: 10819 . mpimat - the parallel matrix generated 10820 10821 Level: developer 10822 10823 Note: 10824 The number of columns of the matrix in EACH processor MUST be the same. 10825 10826 .seealso: `Mat` 10827 @*/ 10828 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat) 10829 { 10830 PetscMPIInt size; 10831 10832 PetscFunctionBegin; 10833 PetscCallMPI(MPI_Comm_size(comm, &size)); 10834 if (size == 1) { 10835 if (reuse == MAT_INITIAL_MATRIX) { 10836 PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat)); 10837 } else { 10838 PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN)); 10839 } 10840 PetscFunctionReturn(PETSC_SUCCESS); 10841 } 10842 10843 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"); 10844 10845 PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0)); 10846 PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat)); 10847 PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0)); 10848 PetscFunctionReturn(PETSC_SUCCESS); 10849 } 10850 10851 /*@ 10852 MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent ranks' ownership ranges. 10853 10854 Collective 10855 10856 Input Parameters: 10857 + A - the matrix to create subdomains from 10858 - N - requested number of subdomains 10859 10860 Output Parameters: 10861 + n - number of subdomains resulting on this rank 10862 - iss - `IS` list with indices of subdomains on this rank 10863 10864 Level: advanced 10865 10866 Note: 10867 The number of subdomains must be smaller than the communicator size 10868 10869 .seealso: `Mat`, `IS` 10870 @*/ 10871 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[]) 10872 { 10873 MPI_Comm comm, subcomm; 10874 PetscMPIInt size, rank, color; 10875 PetscInt rstart, rend, k; 10876 10877 PetscFunctionBegin; 10878 PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 10879 PetscCallMPI(MPI_Comm_size(comm, &size)); 10880 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 10881 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); 10882 *n = 1; 10883 k = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */ 10884 color = rank / k; 10885 PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm)); 10886 PetscCall(PetscMalloc1(1, iss)); 10887 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 10888 PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0])); 10889 PetscCallMPI(MPI_Comm_free(&subcomm)); 10890 PetscFunctionReturn(PETSC_SUCCESS); 10891 } 10892 10893 /*@ 10894 MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection. 10895 10896 If the interpolation and restriction operators are the same, uses `MatPtAP()`. 10897 If they are not the same, uses `MatMatMatMult()`. 10898 10899 Once the coarse grid problem is constructed, correct for interpolation operators 10900 that are not of full rank, which can legitimately happen in the case of non-nested 10901 geometric multigrid. 10902 10903 Input Parameters: 10904 + restrct - restriction operator 10905 . dA - fine grid matrix 10906 . interpolate - interpolation operator 10907 . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10908 - fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate 10909 10910 Output Parameters: 10911 . A - the Galerkin coarse matrix 10912 10913 Options Database Key: 10914 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used 10915 10916 Level: developer 10917 10918 .seealso: `Mat`, `MatPtAP()`, `MatMatMatMult()` 10919 @*/ 10920 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A) 10921 { 10922 IS zerorows; 10923 Vec diag; 10924 10925 PetscFunctionBegin; 10926 PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10927 /* Construct the coarse grid matrix */ 10928 if (interpolate == restrct) { 10929 PetscCall(MatPtAP(dA, interpolate, reuse, fill, A)); 10930 } else { 10931 PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A)); 10932 } 10933 10934 /* If the interpolation matrix is not of full rank, A will have zero rows. 10935 This can legitimately happen in the case of non-nested geometric multigrid. 10936 In that event, we set the rows of the matrix to the rows of the identity, 10937 ignoring the equations (as the RHS will also be zero). */ 10938 10939 PetscCall(MatFindZeroRows(*A, &zerorows)); 10940 10941 if (zerorows != NULL) { /* if there are any zero rows */ 10942 PetscCall(MatCreateVecs(*A, &diag, NULL)); 10943 PetscCall(MatGetDiagonal(*A, diag)); 10944 PetscCall(VecISSet(diag, zerorows, 1.0)); 10945 PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES)); 10946 PetscCall(VecDestroy(&diag)); 10947 PetscCall(ISDestroy(&zerorows)); 10948 } 10949 PetscFunctionReturn(PETSC_SUCCESS); 10950 } 10951 10952 /*@C 10953 MatSetOperation - Allows user to set a matrix operation for any matrix type 10954 10955 Logically Collective 10956 10957 Input Parameters: 10958 + mat - the matrix 10959 . op - the name of the operation 10960 - f - the function that provides the operation 10961 10962 Level: developer 10963 10964 Usage: 10965 .vb 10966 extern PetscErrorCode usermult(Mat, Vec, Vec); 10967 10968 PetscCall(MatCreateXXX(comm, ..., &A)); 10969 PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFunction)usermult)); 10970 .ve 10971 10972 Notes: 10973 See the file `include/petscmat.h` for a complete list of matrix 10974 operations, which all have the form MATOP_<OPERATION>, where 10975 <OPERATION> is the name (in all capital letters) of the 10976 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 10977 10978 All user-provided functions (except for `MATOP_DESTROY`) should have the same calling 10979 sequence as the usual matrix interface routines, since they 10980 are intended to be accessed via the usual matrix interface 10981 routines, e.g., 10982 .vb 10983 MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec) 10984 .ve 10985 10986 In particular each function MUST return `PETSC_SUCCESS` on success and 10987 nonzero on failure. 10988 10989 This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type. 10990 10991 .seealso: `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()` 10992 @*/ 10993 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void)) 10994 { 10995 PetscFunctionBegin; 10996 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10997 if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view; 10998 (((void (**)(void))mat->ops)[op]) = f; 10999 PetscFunctionReturn(PETSC_SUCCESS); 11000 } 11001 11002 /*@C 11003 MatGetOperation - Gets a matrix operation for any matrix type. 11004 11005 Not Collective 11006 11007 Input Parameters: 11008 + mat - the matrix 11009 - op - the name of the operation 11010 11011 Output Parameter: 11012 . f - the function that provides the operation 11013 11014 Level: developer 11015 11016 Usage: 11017 $ PetscErrorCode (*usermult)(Mat,Vec,Vec); 11018 $ MatGetOperation(A,MATOP_MULT,(void(**)(void))&usermult); 11019 11020 Notes: 11021 See the file include/petscmat.h for a complete list of matrix 11022 operations, which all have the form MATOP_<OPERATION>, where 11023 <OPERATION> is the name (in all capital letters) of the 11024 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11025 11026 This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type. 11027 11028 .seealso: `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()` 11029 @*/ 11030 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void)) 11031 { 11032 PetscFunctionBegin; 11033 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11034 *f = (((void (**)(void))mat->ops)[op]); 11035 PetscFunctionReturn(PETSC_SUCCESS); 11036 } 11037 11038 /*@ 11039 MatHasOperation - Determines whether the given matrix supports the particular operation. 11040 11041 Not Collective 11042 11043 Input Parameters: 11044 + mat - the matrix 11045 - op - the operation, for example, `MATOP_GET_DIAGONAL` 11046 11047 Output Parameter: 11048 . has - either `PETSC_TRUE` or `PETSC_FALSE` 11049 11050 Level: advanced 11051 11052 Note: 11053 See `MatSetOperation()` for additional discussion on naming convention and usage of `op`. 11054 11055 .seealso: `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()` 11056 @*/ 11057 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has) 11058 { 11059 PetscFunctionBegin; 11060 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11061 PetscValidBoolPointer(has, 3); 11062 if (mat->ops->hasoperation) { 11063 PetscUseTypeMethod(mat, hasoperation, op, has); 11064 } else { 11065 if (((void **)mat->ops)[op]) *has = PETSC_TRUE; 11066 else { 11067 *has = PETSC_FALSE; 11068 if (op == MATOP_CREATE_SUBMATRIX) { 11069 PetscMPIInt size; 11070 11071 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 11072 if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has)); 11073 } 11074 } 11075 } 11076 PetscFunctionReturn(PETSC_SUCCESS); 11077 } 11078 11079 /*@ 11080 MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent 11081 11082 Collective 11083 11084 Input Parameters: 11085 . mat - the matrix 11086 11087 Output Parameter: 11088 . cong - either `PETSC_TRUE` or `PETSC_FALSE` 11089 11090 Level: beginner 11091 11092 .seealso: `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout` 11093 @*/ 11094 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong) 11095 { 11096 PetscFunctionBegin; 11097 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11098 PetscValidType(mat, 1); 11099 PetscValidBoolPointer(cong, 2); 11100 if (!mat->rmap || !mat->cmap) { 11101 *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE; 11102 PetscFunctionReturn(PETSC_SUCCESS); 11103 } 11104 if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */ 11105 PetscCall(PetscLayoutSetUp(mat->rmap)); 11106 PetscCall(PetscLayoutSetUp(mat->cmap)); 11107 PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong)); 11108 if (*cong) mat->congruentlayouts = 1; 11109 else mat->congruentlayouts = 0; 11110 } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE; 11111 PetscFunctionReturn(PETSC_SUCCESS); 11112 } 11113 11114 PetscErrorCode MatSetInf(Mat A) 11115 { 11116 PetscFunctionBegin; 11117 PetscUseTypeMethod(A, setinf); 11118 PetscFunctionReturn(PETSC_SUCCESS); 11119 } 11120 11121 /*@C 11122 MatCreateGraph - create a scalar matrix (that is a matrix with one vertex for each block vertex in the original matrix), for use in graph algorithms 11123 and possibly removes small values from the graph structure. 11124 11125 Collective 11126 11127 Input Parameters: 11128 + A - the matrix 11129 . sym - `PETSC_TRUE` indicates that the graph should be symmetrized 11130 . scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry 11131 - filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value 11132 11133 Output Parameter: 11134 . graph - the resulting graph 11135 11136 Level: advanced 11137 11138 .seealso: `Mat`, `MatCreate()`, `PCGAMG` 11139 @*/ 11140 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph) 11141 { 11142 PetscFunctionBegin; 11143 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11144 PetscValidType(A, 1); 11145 PetscValidLogicalCollectiveBool(A, scale, 3); 11146 PetscValidPointer(graph, 5); 11147 PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph); 11148 PetscFunctionReturn(PETSC_SUCCESS); 11149 } 11150 11151 /*@ 11152 MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place, 11153 meaning the same memory is used for the matrix, and no new memory is allocated. 11154 11155 Collective on mat 11156 11157 Input Parameter: 11158 . A - the matrix 11159 11160 Output Parameter: 11161 . A - the matrix 11162 11163 Level: intermediate 11164 11165 .seealso: `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatChop()` 11166 @*/ 11167 PetscErrorCode MatEliminateZeros(Mat A) 11168 { 11169 PetscFunctionBegin; 11170 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11171 PetscUseTypeMethod(A, eliminatezeros); 11172 PetscFunctionReturn(PETSC_SUCCESS); 11173 } 11174