1 /* 2 This is where the abstract matrix operations are defined 3 Portions of this code are under: 4 Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved. 5 */ 6 7 #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/ 8 #include <petsc/private/isimpl.h> 9 #include <petsc/private/vecimpl.h> 10 11 /* Logging support */ 12 PetscClassId MAT_CLASSID; 13 PetscClassId MAT_COLORING_CLASSID; 14 PetscClassId MAT_FDCOLORING_CLASSID; 15 PetscClassId MAT_TRANSPOSECOLORING_CLASSID; 16 17 PetscLogEvent MAT_Mult, MAT_Mults, MAT_MultAdd, MAT_MultTranspose; 18 PetscLogEvent MAT_MultTransposeAdd, MAT_Solve, MAT_Solves, MAT_SolveAdd, MAT_SolveTranspose, MAT_MatSolve, MAT_MatTrSolve; 19 PetscLogEvent MAT_SolveTransposeAdd, MAT_SOR, MAT_ForwardSolve, MAT_BackwardSolve, MAT_LUFactor, MAT_LUFactorSymbolic; 20 PetscLogEvent MAT_LUFactorNumeric, MAT_CholeskyFactor, MAT_CholeskyFactorSymbolic, MAT_CholeskyFactorNumeric, MAT_ILUFactor; 21 PetscLogEvent MAT_ILUFactorSymbolic, MAT_ICCFactorSymbolic, MAT_Copy, MAT_Convert, MAT_Scale, MAT_AssemblyBegin; 22 PetscLogEvent MAT_QRFactorNumeric, MAT_QRFactorSymbolic, MAT_QRFactor; 23 PetscLogEvent MAT_AssemblyEnd, MAT_SetValues, MAT_GetValues, MAT_GetRow, MAT_GetRowIJ, MAT_CreateSubMats, MAT_GetOrdering, MAT_RedundantMat, MAT_GetSeqNonzeroStructure; 24 PetscLogEvent MAT_IncreaseOverlap, MAT_Partitioning, MAT_PartitioningND, MAT_Coarsen, MAT_ZeroEntries, MAT_Load, MAT_View, MAT_AXPY, MAT_FDColoringCreate; 25 PetscLogEvent MAT_FDColoringSetUp, MAT_FDColoringApply, MAT_Transpose, MAT_FDColoringFunction, MAT_CreateSubMat; 26 PetscLogEvent MAT_TransposeColoringCreate; 27 PetscLogEvent MAT_MatMult, MAT_MatMultSymbolic, MAT_MatMultNumeric; 28 PetscLogEvent MAT_PtAP, MAT_PtAPSymbolic, MAT_PtAPNumeric, MAT_RARt, MAT_RARtSymbolic, MAT_RARtNumeric; 29 PetscLogEvent MAT_MatTransposeMult, MAT_MatTransposeMultSymbolic, MAT_MatTransposeMultNumeric; 30 PetscLogEvent MAT_TransposeMatMult, MAT_TransposeMatMultSymbolic, MAT_TransposeMatMultNumeric; 31 PetscLogEvent MAT_MatMatMult, MAT_MatMatMultSymbolic, MAT_MatMatMultNumeric; 32 PetscLogEvent MAT_MultHermitianTranspose, MAT_MultHermitianTransposeAdd; 33 PetscLogEvent MAT_Getsymtranspose, MAT_Getsymtransreduced, MAT_GetBrowsOfAcols; 34 PetscLogEvent MAT_GetBrowsOfAocols, MAT_Getlocalmat, MAT_Getlocalmatcondensed, MAT_Seqstompi, MAT_Seqstompinum, MAT_Seqstompisym; 35 PetscLogEvent MAT_Applypapt, MAT_Applypapt_numeric, MAT_Applypapt_symbolic, MAT_GetSequentialNonzeroStructure; 36 PetscLogEvent MAT_GetMultiProcBlock; 37 PetscLogEvent MAT_CUSPARSECopyToGPU, MAT_CUSPARSECopyFromGPU, MAT_CUSPARSEGenerateTranspose, MAT_CUSPARSESolveAnalysis; 38 PetscLogEvent MAT_HIPSPARSECopyToGPU, MAT_HIPSPARSECopyFromGPU, MAT_HIPSPARSEGenerateTranspose, MAT_HIPSPARSESolveAnalysis; 39 PetscLogEvent MAT_PreallCOO, MAT_SetVCOO; 40 PetscLogEvent MAT_SetValuesBatch; 41 PetscLogEvent MAT_ViennaCLCopyToGPU; 42 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU; 43 PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom; 44 PetscLogEvent MAT_FactorFactS, MAT_FactorInvS; 45 PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights; 46 PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR; 47 48 const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL}; 49 50 /*@ 51 MatSetRandom - Sets all components of a matrix to random numbers. 52 53 Logically Collective 54 55 Input Parameters: 56 + x - the matrix 57 - rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or `NULL` and 58 it will create one internally. 59 60 Output Parameter: 61 . x - the matrix 62 63 Example: 64 .vb 65 PetscRandomCreate(PETSC_COMM_WORLD,&rctx); 66 MatSetRandom(x,rctx); 67 PetscRandomDestroy(rctx); 68 .ve 69 70 Level: intermediate 71 72 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. This row value 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 (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 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: 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: 1256 In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used. 1257 Each processor's chunk is loaded independently by its owning rank. 1258 Multiple objects, both matrices and vectors, can be stored within the same file. 1259 They are looked up by their PetscObject name. 1260 1261 As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use 1262 by default the same structure and naming of the AIJ arrays and column count 1263 within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g. 1264 $ save example.mat A b -v7.3 1265 can be directly read by this routine (see Reference 1 for details). 1266 1267 Depending on your MATLAB version, this format might be a default, 1268 otherwise you can set it as default in Preferences. 1269 1270 Unless -nocompression flag is used to save the file in MATLAB, 1271 PETSc must be configured with ZLIB package. 1272 1273 See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c 1274 1275 This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5` 1276 1277 Corresponding `MatView()` is not yet implemented. 1278 1279 The loaded matrix is actually a transpose of the original one in MATLAB, 1280 unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above). 1281 With this format, matrix is automatically transposed by PETSc, 1282 unless the matrix is marked as SPD or symmetric 1283 (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`). 1284 1285 References: 1286 . * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version 1287 1288 .seealso: `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 `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 `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 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: 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 Fortran users should declare info as a double precision 2955 array of dimension `MAT_INFO_SIZE`, and then extract the parameters 2956 of interest. See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h 2957 a complete list of parameter names. 2958 .vb 2959 double precision info(MAT_INFO_SIZE) 2960 double precision mal, nz_a 2961 Mat A 2962 integer ierr 2963 2964 call MatGetInfo(A,MAT_LOCAL,info,ierr) 2965 mal = info(MAT_INFO_MALLOCS) 2966 nz_a = info(MAT_INFO_NZ_ALLOCATED) 2967 .ve 2968 2969 Level: intermediate 2970 2971 Developer Note: 2972 The Fortran interface is not autogenerated as the 2973 interface definition cannot be generated correctly [due to `MatInfo` argument] 2974 2975 .seealso: `Mat`, `MatInfo`, `MatStashGetInfo()` 2976 @*/ 2977 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info) 2978 { 2979 PetscFunctionBegin; 2980 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2981 PetscValidType(mat, 1); 2982 PetscValidPointer(info, 3); 2983 MatCheckPreallocated(mat, 1); 2984 PetscUseTypeMethod(mat, getinfo, flag, info); 2985 PetscFunctionReturn(PETSC_SUCCESS); 2986 } 2987 2988 /* 2989 This is used by external packages where it is not easy to get the info from the actual 2990 matrix factorization. 2991 */ 2992 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info) 2993 { 2994 PetscFunctionBegin; 2995 PetscCall(PetscMemzero(info, sizeof(MatInfo))); 2996 PetscFunctionReturn(PETSC_SUCCESS); 2997 } 2998 2999 /*@C 3000 MatLUFactor - Performs in-place LU factorization of matrix. 3001 3002 Collective 3003 3004 Input Parameters: 3005 + mat - the matrix 3006 . row - row permutation 3007 . col - column permutation 3008 - info - options for factorization, includes 3009 .vb 3010 fill - expected fill as ratio of original fill. 3011 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3012 Run with the option -info to determine an optimal value to use 3013 .ve 3014 Level: developer 3015 3016 Notes: 3017 Most users should employ the `KSP` interface for linear solvers 3018 instead of working directly with matrix algebra routines such as this. 3019 See, e.g., `KSPCreate()`. 3020 3021 This changes the state of the matrix to a factored matrix; it cannot be used 3022 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3023 3024 This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()` 3025 when not using `KSP`. 3026 3027 Developer Note: 3028 The Fortran interface is not autogenerated as the 3029 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3030 3031 .seealso: [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, 3032 `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3033 @*/ 3034 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3035 { 3036 MatFactorInfo tinfo; 3037 3038 PetscFunctionBegin; 3039 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3040 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3041 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3042 if (info) PetscValidPointer(info, 4); 3043 PetscValidType(mat, 1); 3044 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3045 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3046 MatCheckPreallocated(mat, 1); 3047 if (!info) { 3048 PetscCall(MatFactorInfoInitialize(&tinfo)); 3049 info = &tinfo; 3050 } 3051 3052 PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0)); 3053 PetscUseTypeMethod(mat, lufactor, row, col, info); 3054 PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0)); 3055 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3056 PetscFunctionReturn(PETSC_SUCCESS); 3057 } 3058 3059 /*@C 3060 MatILUFactor - Performs in-place ILU factorization of matrix. 3061 3062 Collective 3063 3064 Input Parameters: 3065 + mat - the matrix 3066 . row - row permutation 3067 . col - column permutation 3068 - info - structure containing 3069 .vb 3070 levels - number of levels of fill. 3071 expected fill - as ratio of original fill. 3072 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 3073 missing diagonal entries) 3074 .ve 3075 3076 Level: developer 3077 3078 Notes: 3079 Most users should employ the `KSP` interface for linear solvers 3080 instead of working directly with matrix algebra routines such as this. 3081 See, e.g., `KSPCreate()`. 3082 3083 Probably really in-place only when level of fill is zero, otherwise allocates 3084 new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()` 3085 when not using `KSP`. 3086 3087 Developer Note: 3088 The Fortran interface is not autogenerated as the 3089 interface definition cannot be generated correctly [due to MatFactorInfo] 3090 3091 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 3092 @*/ 3093 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3094 { 3095 PetscFunctionBegin; 3096 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3097 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3098 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3099 PetscValidPointer(info, 4); 3100 PetscValidType(mat, 1); 3101 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 3102 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3103 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3104 MatCheckPreallocated(mat, 1); 3105 3106 PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0)); 3107 PetscUseTypeMethod(mat, ilufactor, row, col, info); 3108 PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0)); 3109 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3110 PetscFunctionReturn(PETSC_SUCCESS); 3111 } 3112 3113 /*@C 3114 MatLUFactorSymbolic - Performs symbolic LU factorization of matrix. 3115 Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`. 3116 3117 Collective on fact 3118 3119 Input Parameters: 3120 + fact - the factor matrix obtained with `MatGetFactor()` 3121 . mat - the matrix 3122 . row, col - row and column permutations 3123 - info - options for factorization, includes 3124 .vb 3125 fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use 3126 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3127 .ve 3128 3129 Level: developer 3130 3131 Notes: 3132 See [Matrix Factorization](sec_matfactor) for additional information about factorizations 3133 3134 Most users should employ the simplified `KSP` interface for linear solvers 3135 instead of working directly with matrix algebra routines such as this. 3136 See, e.g., `KSPCreate()`. 3137 3138 Developer Note: 3139 The Fortran interface is not autogenerated as the 3140 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3141 3142 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3143 @*/ 3144 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 3145 { 3146 MatFactorInfo tinfo; 3147 3148 PetscFunctionBegin; 3149 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3150 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 3151 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 3152 if (info) PetscValidPointer(info, 5); 3153 PetscValidType(mat, 2); 3154 PetscValidPointer(fact, 1); 3155 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3156 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3157 if (!(fact)->ops->lufactorsymbolic) { 3158 MatSolverType stype; 3159 PetscCall(MatFactorGetSolverType(fact, &stype)); 3160 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic LU using solver package %s", ((PetscObject)mat)->type_name, stype); 3161 } 3162 MatCheckPreallocated(mat, 2); 3163 if (!info) { 3164 PetscCall(MatFactorInfoInitialize(&tinfo)); 3165 info = &tinfo; 3166 } 3167 3168 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0)); 3169 PetscCall((fact->ops->lufactorsymbolic)(fact, mat, row, col, info)); 3170 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0)); 3171 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3172 PetscFunctionReturn(PETSC_SUCCESS); 3173 } 3174 3175 /*@C 3176 MatLUFactorNumeric - Performs numeric LU factorization of a matrix. 3177 Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`. 3178 3179 Collective on fact 3180 3181 Input Parameters: 3182 + fact - the factor matrix obtained with `MatGetFactor()` 3183 . mat - the matrix 3184 - info - options for factorization 3185 3186 Level: developer 3187 3188 Notes: 3189 See `MatLUFactor()` for in-place factorization. See 3190 `MatCholeskyFactorNumeric()` for the symmetric, positive definite case. 3191 3192 Most users should employ the `KSP` interface for linear solvers 3193 instead of working directly with matrix algebra routines such as this. 3194 See, e.g., `KSPCreate()`. 3195 3196 Developer Note: 3197 The Fortran interface is not autogenerated as the 3198 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3199 3200 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()` 3201 @*/ 3202 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3203 { 3204 MatFactorInfo tinfo; 3205 3206 PetscFunctionBegin; 3207 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3208 PetscValidType(mat, 2); 3209 PetscValidPointer(fact, 1); 3210 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3211 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3212 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, 3213 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3214 3215 PetscCheck((fact)->ops->lufactornumeric, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s numeric LU", ((PetscObject)mat)->type_name); 3216 MatCheckPreallocated(mat, 2); 3217 if (!info) { 3218 PetscCall(MatFactorInfoInitialize(&tinfo)); 3219 info = &tinfo; 3220 } 3221 3222 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3223 else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0)); 3224 PetscCall((fact->ops->lufactornumeric)(fact, mat, info)); 3225 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3226 else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0)); 3227 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3228 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3229 PetscFunctionReturn(PETSC_SUCCESS); 3230 } 3231 3232 /*@C 3233 MatCholeskyFactor - Performs in-place Cholesky factorization of a 3234 symmetric matrix. 3235 3236 Collective 3237 3238 Input Parameters: 3239 + mat - the matrix 3240 . perm - row and column permutations 3241 - f - expected fill as ratio of original fill 3242 3243 Level: developer 3244 3245 Notes: 3246 See `MatLUFactor()` for the nonsymmetric case. See also `MatGetFactor()`, 3247 `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`. 3248 3249 Most users should employ the `KSP` interface for linear solvers 3250 instead of working directly with matrix algebra routines such as this. 3251 See, e.g., `KSPCreate()`. 3252 3253 Developer Note: 3254 The Fortran interface is not autogenerated as the 3255 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3256 3257 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()` 3258 `MatGetOrdering()` 3259 @*/ 3260 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info) 3261 { 3262 MatFactorInfo tinfo; 3263 3264 PetscFunctionBegin; 3265 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3266 PetscValidType(mat, 1); 3267 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2); 3268 if (info) PetscValidPointer(info, 3); 3269 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3270 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3271 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3272 MatCheckPreallocated(mat, 1); 3273 if (!info) { 3274 PetscCall(MatFactorInfoInitialize(&tinfo)); 3275 info = &tinfo; 3276 } 3277 3278 PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0)); 3279 PetscUseTypeMethod(mat, choleskyfactor, perm, info); 3280 PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0)); 3281 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3282 PetscFunctionReturn(PETSC_SUCCESS); 3283 } 3284 3285 /*@C 3286 MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization 3287 of a symmetric matrix. 3288 3289 Collective on fact 3290 3291 Input Parameters: 3292 + fact - the factor matrix obtained with `MatGetFactor()` 3293 . mat - the matrix 3294 . perm - row and column permutations 3295 - info - options for factorization, includes 3296 .vb 3297 fill - expected fill as ratio of original fill. 3298 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3299 Run with the option -info to determine an optimal value to use 3300 .ve 3301 3302 Level: developer 3303 3304 Notes: 3305 See `MatLUFactorSymbolic()` for the nonsymmetric case. See also 3306 `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`. 3307 3308 Most users should employ the `KSP` interface for linear solvers 3309 instead of working directly with matrix algebra routines such as this. 3310 See, e.g., `KSPCreate()`. 3311 3312 Developer Note: 3313 The Fortran interface is not autogenerated as the 3314 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3315 3316 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()` 3317 `MatGetOrdering()` 3318 @*/ 3319 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 3320 { 3321 MatFactorInfo tinfo; 3322 3323 PetscFunctionBegin; 3324 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3325 PetscValidType(mat, 2); 3326 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 3327 if (info) PetscValidPointer(info, 4); 3328 PetscValidPointer(fact, 1); 3329 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3330 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3331 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3332 if (!(fact)->ops->choleskyfactorsymbolic) { 3333 MatSolverType stype; 3334 PetscCall(MatFactorGetSolverType(fact, &stype)); 3335 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s symbolic factor Cholesky using solver package %s", ((PetscObject)mat)->type_name, stype); 3336 } 3337 MatCheckPreallocated(mat, 2); 3338 if (!info) { 3339 PetscCall(MatFactorInfoInitialize(&tinfo)); 3340 info = &tinfo; 3341 } 3342 3343 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3344 PetscCall((fact->ops->choleskyfactorsymbolic)(fact, mat, perm, info)); 3345 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3346 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3347 PetscFunctionReturn(PETSC_SUCCESS); 3348 } 3349 3350 /*@C 3351 MatCholeskyFactorNumeric - Performs numeric Cholesky factorization 3352 of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and 3353 `MatCholeskyFactorSymbolic()`. 3354 3355 Collective on fact 3356 3357 Input Parameters: 3358 + fact - the factor matrix obtained with `MatGetFactor()` 3359 . mat - the initial matrix 3360 . info - options for factorization 3361 - fact - the symbolic factor of mat 3362 3363 Level: developer 3364 3365 Note: 3366 Most users should employ the `KSP` interface for linear solvers 3367 instead of working directly with matrix algebra routines such as this. 3368 See, e.g., `KSPCreate()`. 3369 3370 Developer Note: 3371 The Fortran interface is not autogenerated as the 3372 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3373 3374 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()` 3375 @*/ 3376 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3377 { 3378 MatFactorInfo tinfo; 3379 3380 PetscFunctionBegin; 3381 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3382 PetscValidType(mat, 2); 3383 PetscValidPointer(fact, 1); 3384 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3385 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3386 PetscCheck((fact)->ops->choleskyfactornumeric, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s numeric factor Cholesky", ((PetscObject)mat)->type_name); 3387 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, 3388 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3389 MatCheckPreallocated(mat, 2); 3390 if (!info) { 3391 PetscCall(MatFactorInfoInitialize(&tinfo)); 3392 info = &tinfo; 3393 } 3394 3395 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3396 else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0)); 3397 PetscCall((fact->ops->choleskyfactornumeric)(fact, mat, info)); 3398 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3399 else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0)); 3400 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3401 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3402 PetscFunctionReturn(PETSC_SUCCESS); 3403 } 3404 3405 /*@ 3406 MatQRFactor - Performs in-place QR factorization of matrix. 3407 3408 Collective 3409 3410 Input Parameters: 3411 + mat - the matrix 3412 . col - column permutation 3413 - info - options for factorization, includes 3414 .vb 3415 fill - expected fill as ratio of original fill. 3416 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3417 Run with the option -info to determine an optimal value to use 3418 .ve 3419 3420 Level: developer 3421 3422 Notes: 3423 Most users should employ the `KSP` interface for linear solvers 3424 instead of working directly with matrix algebra routines such as this. 3425 See, e.g., `KSPCreate()`. 3426 3427 This changes the state of the matrix to a factored matrix; it cannot be used 3428 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3429 3430 Developer Note: 3431 The Fortran interface is not autogenerated as the 3432 interface definition cannot be generated correctly [due to MatFactorInfo] 3433 3434 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`, 3435 `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3436 @*/ 3437 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info) 3438 { 3439 PetscFunctionBegin; 3440 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3441 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2); 3442 if (info) PetscValidPointer(info, 3); 3443 PetscValidType(mat, 1); 3444 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3445 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3446 MatCheckPreallocated(mat, 1); 3447 PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0)); 3448 PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info)); 3449 PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0)); 3450 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3451 PetscFunctionReturn(PETSC_SUCCESS); 3452 } 3453 3454 /*@ 3455 MatQRFactorSymbolic - Performs symbolic QR factorization of matrix. 3456 Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`. 3457 3458 Collective on fact 3459 3460 Input Parameters: 3461 + fact - the factor matrix obtained with `MatGetFactor()` 3462 . mat - the matrix 3463 . col - column permutation 3464 - info - options for factorization, includes 3465 .vb 3466 fill - expected fill as ratio of original fill. 3467 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3468 Run with the option -info to determine an optimal value to use 3469 .ve 3470 3471 Level: developer 3472 3473 Note: 3474 Most users should employ the `KSP` interface for linear solvers 3475 instead of working directly with matrix algebra routines such as this. 3476 See, e.g., `KSPCreate()`. 3477 3478 Developer Note: 3479 The Fortran interface is not autogenerated as the 3480 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3481 3482 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3483 @*/ 3484 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info) 3485 { 3486 MatFactorInfo tinfo; 3487 3488 PetscFunctionBegin; 3489 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3490 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3491 if (info) PetscValidPointer(info, 4); 3492 PetscValidType(mat, 2); 3493 PetscValidPointer(fact, 1); 3494 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3495 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3496 MatCheckPreallocated(mat, 2); 3497 if (!info) { 3498 PetscCall(MatFactorInfoInitialize(&tinfo)); 3499 info = &tinfo; 3500 } 3501 3502 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3503 PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info)); 3504 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3505 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3506 PetscFunctionReturn(PETSC_SUCCESS); 3507 } 3508 3509 /*@ 3510 MatQRFactorNumeric - Performs numeric QR factorization of a matrix. 3511 Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`. 3512 3513 Collective on fact 3514 3515 Input Parameters: 3516 + fact - the factor matrix obtained with `MatGetFactor()` 3517 . mat - the matrix 3518 - info - options for factorization 3519 3520 Level: developer 3521 3522 Notes: 3523 See `MatQRFactor()` for in-place factorization. 3524 3525 Most users should employ the `KSP` interface for linear solvers 3526 instead of working directly with matrix algebra routines such as this. 3527 See, e.g., `KSPCreate()`. 3528 3529 Developer Note: 3530 The Fortran interface is not autogenerated as the 3531 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3532 3533 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()` 3534 @*/ 3535 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3536 { 3537 MatFactorInfo tinfo; 3538 3539 PetscFunctionBegin; 3540 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3541 PetscValidType(mat, 2); 3542 PetscValidPointer(fact, 1); 3543 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3544 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3545 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, 3546 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3547 3548 MatCheckPreallocated(mat, 2); 3549 if (!info) { 3550 PetscCall(MatFactorInfoInitialize(&tinfo)); 3551 info = &tinfo; 3552 } 3553 3554 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3555 else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0)); 3556 PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info)); 3557 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3558 else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0)); 3559 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3560 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3561 PetscFunctionReturn(PETSC_SUCCESS); 3562 } 3563 3564 /*@ 3565 MatSolve - Solves A x = b, given a factored matrix. 3566 3567 Neighbor-wise Collective 3568 3569 Input Parameters: 3570 + mat - the factored matrix 3571 - b - the right-hand-side vector 3572 3573 Output Parameter: 3574 . x - the result vector 3575 3576 Level: developer 3577 3578 Notes: 3579 The vectors `b` and `x` cannot be the same. I.e., one cannot 3580 call `MatSolve`(A,x,x). 3581 3582 Most users should employ the `KSP` interface for linear solvers 3583 instead of working directly with matrix algebra routines such as this. 3584 See, e.g., `KSPCreate()`. 3585 3586 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3587 @*/ 3588 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x) 3589 { 3590 PetscFunctionBegin; 3591 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3592 PetscValidType(mat, 1); 3593 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3594 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3595 PetscCheckSameComm(mat, 1, b, 2); 3596 PetscCheckSameComm(mat, 1, x, 3); 3597 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3598 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); 3599 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); 3600 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); 3601 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3602 MatCheckPreallocated(mat, 1); 3603 3604 PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0)); 3605 if (mat->factorerrortype) { 3606 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3607 PetscCall(VecSetInf(x)); 3608 } else PetscUseTypeMethod(mat, solve, b, x); 3609 PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0)); 3610 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3611 PetscFunctionReturn(PETSC_SUCCESS); 3612 } 3613 3614 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans) 3615 { 3616 Vec b, x; 3617 PetscInt N, i; 3618 PetscErrorCode (*f)(Mat, Vec, Vec); 3619 PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE; 3620 3621 PetscFunctionBegin; 3622 if (A->factorerrortype) { 3623 PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype)); 3624 PetscCall(MatSetInf(X)); 3625 PetscFunctionReturn(PETSC_SUCCESS); 3626 } 3627 f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose; 3628 PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 3629 PetscCall(MatBoundToCPU(A, &Abound)); 3630 if (!Abound) { 3631 PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3632 PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3633 } 3634 #if defined(PETSC_HAVE_CUDA) 3635 if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B)); 3636 if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X)); 3637 #elif (PETSC_HAVE_HIP) 3638 if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B)); 3639 if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X)); 3640 #endif 3641 PetscCall(MatGetSize(B, NULL, &N)); 3642 for (i = 0; i < N; i++) { 3643 PetscCall(MatDenseGetColumnVecRead(B, i, &b)); 3644 PetscCall(MatDenseGetColumnVecWrite(X, i, &x)); 3645 PetscCall((*f)(A, b, x)); 3646 PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x)); 3647 PetscCall(MatDenseRestoreColumnVecRead(B, i, &b)); 3648 } 3649 if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B)); 3650 if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X)); 3651 PetscFunctionReturn(PETSC_SUCCESS); 3652 } 3653 3654 /*@ 3655 MatMatSolve - Solves A X = B, given a factored matrix. 3656 3657 Neighbor-wise Collective 3658 3659 Input Parameters: 3660 + A - the factored matrix 3661 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS) 3662 3663 Output Parameter: 3664 . X - the result matrix (dense matrix) 3665 3666 Level: developer 3667 3668 Note: 3669 If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`; 3670 otherwise, `B` and `X` cannot be the same. 3671 3672 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3673 @*/ 3674 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X) 3675 { 3676 PetscFunctionBegin; 3677 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3678 PetscValidType(A, 1); 3679 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3680 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3681 PetscCheckSameComm(A, 1, B, 2); 3682 PetscCheckSameComm(A, 1, X, 3); 3683 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); 3684 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); 3685 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"); 3686 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3687 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3688 MatCheckPreallocated(A, 1); 3689 3690 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3691 if (!A->ops->matsolve) { 3692 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name)); 3693 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE)); 3694 } else PetscUseTypeMethod(A, matsolve, B, X); 3695 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3696 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3697 PetscFunctionReturn(PETSC_SUCCESS); 3698 } 3699 3700 /*@ 3701 MatMatSolveTranspose - Solves A^T X = B, given a factored matrix. 3702 3703 Neighbor-wise Collective 3704 3705 Input Parameters: 3706 + A - the factored matrix 3707 - B - the right-hand-side matrix (`MATDENSE` matrix) 3708 3709 Output Parameter: 3710 . X - the result matrix (dense matrix) 3711 3712 Level: developer 3713 3714 Note: 3715 The matrices `B` and `X` cannot be the same. I.e., one cannot 3716 call `MatMatSolveTranspose`(A,X,X). 3717 3718 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()` 3719 @*/ 3720 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X) 3721 { 3722 PetscFunctionBegin; 3723 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3724 PetscValidType(A, 1); 3725 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3726 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3727 PetscCheckSameComm(A, 1, B, 2); 3728 PetscCheckSameComm(A, 1, X, 3); 3729 PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3730 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); 3731 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); 3732 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); 3733 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"); 3734 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3735 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3736 MatCheckPreallocated(A, 1); 3737 3738 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3739 if (!A->ops->matsolvetranspose) { 3740 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name)); 3741 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE)); 3742 } else PetscUseTypeMethod(A, matsolvetranspose, B, X); 3743 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3744 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3745 PetscFunctionReturn(PETSC_SUCCESS); 3746 } 3747 3748 /*@ 3749 MatMatTransposeSolve - Solves A X = B^T, given a factored matrix. 3750 3751 Neighbor-wise Collective 3752 3753 Input Parameters: 3754 + A - the factored matrix 3755 - Bt - the transpose of right-hand-side matrix as a `MATDENSE` 3756 3757 Output Parameter: 3758 . X - the result matrix (dense matrix) 3759 3760 Level: developer 3761 3762 Note: 3763 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 3764 format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`. 3765 3766 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3767 @*/ 3768 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X) 3769 { 3770 PetscFunctionBegin; 3771 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3772 PetscValidType(A, 1); 3773 PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2); 3774 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3775 PetscCheckSameComm(A, 1, Bt, 2); 3776 PetscCheckSameComm(A, 1, X, 3); 3777 3778 PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3779 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); 3780 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); 3781 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"); 3782 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3783 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3784 MatCheckPreallocated(A, 1); 3785 3786 PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0)); 3787 PetscUseTypeMethod(A, mattransposesolve, Bt, X); 3788 PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0)); 3789 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3790 PetscFunctionReturn(PETSC_SUCCESS); 3791 } 3792 3793 /*@ 3794 MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or 3795 U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U, 3796 3797 Neighbor-wise Collective 3798 3799 Input Parameters: 3800 + mat - the factored matrix 3801 - b - the right-hand-side vector 3802 3803 Output Parameter: 3804 . x - the result vector 3805 3806 Level: developer 3807 3808 Notes: 3809 `MatSolve()` should be used for most applications, as it performs 3810 a forward solve followed by a backward solve. 3811 3812 The vectors `b` and `x` cannot be the same, i.e., one cannot 3813 call `MatForwardSolve`(A,x,x). 3814 3815 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3816 the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet. 3817 `MatForwardSolve()` solves U^T*D y = b, and 3818 `MatBackwardSolve()` solves U x = y. 3819 Thus they do not provide a symmetric preconditioner. 3820 3821 .seealso: `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatBackwardSolve()` 3822 @*/ 3823 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x) 3824 { 3825 PetscFunctionBegin; 3826 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3827 PetscValidType(mat, 1); 3828 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3829 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3830 PetscCheckSameComm(mat, 1, b, 2); 3831 PetscCheckSameComm(mat, 1, x, 3); 3832 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3833 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); 3834 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); 3835 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); 3836 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3837 MatCheckPreallocated(mat, 1); 3838 3839 PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0)); 3840 PetscUseTypeMethod(mat, forwardsolve, b, x); 3841 PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0)); 3842 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3843 PetscFunctionReturn(PETSC_SUCCESS); 3844 } 3845 3846 /*@ 3847 MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU. 3848 D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U, 3849 3850 Neighbor-wise Collective 3851 3852 Input Parameters: 3853 + mat - the factored matrix 3854 - b - the right-hand-side vector 3855 3856 Output Parameter: 3857 . x - the result vector 3858 3859 Level: developer 3860 3861 Notes: 3862 `MatSolve()` should be used for most applications, as it performs 3863 a forward solve followed by a backward solve. 3864 3865 The vectors `b` and `x` cannot be the same. I.e., one cannot 3866 call `MatBackwardSolve`(A,x,x). 3867 3868 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3869 the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet. 3870 `MatForwardSolve()` solves U^T*D y = b, and 3871 `MatBackwardSolve()` solves U x = y. 3872 Thus they do not provide a symmetric preconditioner. 3873 3874 .seealso: `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatForwardSolve()` 3875 @*/ 3876 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x) 3877 { 3878 PetscFunctionBegin; 3879 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3880 PetscValidType(mat, 1); 3881 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3882 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3883 PetscCheckSameComm(mat, 1, b, 2); 3884 PetscCheckSameComm(mat, 1, x, 3); 3885 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3886 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); 3887 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); 3888 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); 3889 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3890 MatCheckPreallocated(mat, 1); 3891 3892 PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0)); 3893 PetscUseTypeMethod(mat, backwardsolve, b, x); 3894 PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0)); 3895 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3896 PetscFunctionReturn(PETSC_SUCCESS); 3897 } 3898 3899 /*@ 3900 MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix. 3901 3902 Neighbor-wise Collective 3903 3904 Input Parameters: 3905 + mat - the factored matrix 3906 . b - the right-hand-side vector 3907 - y - the vector to be added to 3908 3909 Output Parameter: 3910 . x - the result vector 3911 3912 Level: developer 3913 3914 Note: 3915 The vectors `b` and `x` cannot be the same. I.e., one cannot 3916 call `MatSolveAdd`(A,x,y,x). 3917 3918 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3919 @*/ 3920 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x) 3921 { 3922 PetscScalar one = 1.0; 3923 Vec tmp; 3924 3925 PetscFunctionBegin; 3926 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3927 PetscValidType(mat, 1); 3928 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 3929 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3930 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 3931 PetscCheckSameComm(mat, 1, b, 2); 3932 PetscCheckSameComm(mat, 1, y, 3); 3933 PetscCheckSameComm(mat, 1, x, 4); 3934 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3935 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); 3936 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); 3937 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); 3938 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); 3939 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); 3940 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3941 MatCheckPreallocated(mat, 1); 3942 3943 PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y)); 3944 if (mat->factorerrortype) { 3945 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3946 PetscCall(VecSetInf(x)); 3947 } else if (mat->ops->solveadd) { 3948 PetscUseTypeMethod(mat, solveadd, b, y, x); 3949 } else { 3950 /* do the solve then the add manually */ 3951 if (x != y) { 3952 PetscCall(MatSolve(mat, b, x)); 3953 PetscCall(VecAXPY(x, one, y)); 3954 } else { 3955 PetscCall(VecDuplicate(x, &tmp)); 3956 PetscCall(VecCopy(x, tmp)); 3957 PetscCall(MatSolve(mat, b, x)); 3958 PetscCall(VecAXPY(x, one, tmp)); 3959 PetscCall(VecDestroy(&tmp)); 3960 } 3961 } 3962 PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y)); 3963 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3964 PetscFunctionReturn(PETSC_SUCCESS); 3965 } 3966 3967 /*@ 3968 MatSolveTranspose - Solves A' x = b, given a factored matrix. 3969 3970 Neighbor-wise Collective 3971 3972 Input Parameters: 3973 + mat - the factored matrix 3974 - b - the right-hand-side vector 3975 3976 Output Parameter: 3977 . x - the result vector 3978 3979 Level: developer 3980 3981 Notes: 3982 The vectors `b` and `x` cannot be the same. I.e., one cannot 3983 call `MatSolveTranspose`(A,x,x). 3984 3985 Most users should employ the `KSP` interface for linear solvers 3986 instead of working directly with matrix algebra routines such as this. 3987 See, e.g., `KSPCreate()`. 3988 3989 .seealso: `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()` 3990 @*/ 3991 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x) 3992 { 3993 PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose; 3994 3995 PetscFunctionBegin; 3996 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3997 PetscValidType(mat, 1); 3998 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3999 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 4000 PetscCheckSameComm(mat, 1, b, 2); 4001 PetscCheckSameComm(mat, 1, x, 3); 4002 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4003 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); 4004 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); 4005 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4006 MatCheckPreallocated(mat, 1); 4007 PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0)); 4008 if (mat->factorerrortype) { 4009 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4010 PetscCall(VecSetInf(x)); 4011 } else { 4012 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name); 4013 PetscCall((*f)(mat, b, x)); 4014 } 4015 PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0)); 4016 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4017 PetscFunctionReturn(PETSC_SUCCESS); 4018 } 4019 4020 /*@ 4021 MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a 4022 factored matrix. 4023 4024 Neighbor-wise Collective 4025 4026 Input Parameters: 4027 + mat - the factored matrix 4028 . b - the right-hand-side vector 4029 - y - the vector to be added to 4030 4031 Output Parameter: 4032 . x - the result vector 4033 4034 Level: developer 4035 4036 Note: 4037 The vectors `b` and `x` cannot be the same. I.e., one cannot 4038 call `MatSolveTransposeAdd`(A,x,y,x). 4039 4040 .seealso: `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()` 4041 @*/ 4042 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x) 4043 { 4044 PetscScalar one = 1.0; 4045 Vec tmp; 4046 PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd; 4047 4048 PetscFunctionBegin; 4049 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4050 PetscValidType(mat, 1); 4051 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4052 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4053 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4054 PetscCheckSameComm(mat, 1, b, 2); 4055 PetscCheckSameComm(mat, 1, y, 3); 4056 PetscCheckSameComm(mat, 1, x, 4); 4057 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4058 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); 4059 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); 4060 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); 4061 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); 4062 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4063 MatCheckPreallocated(mat, 1); 4064 4065 PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y)); 4066 if (mat->factorerrortype) { 4067 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4068 PetscCall(VecSetInf(x)); 4069 } else if (f) { 4070 PetscCall((*f)(mat, b, y, x)); 4071 } else { 4072 /* do the solve then the add manually */ 4073 if (x != y) { 4074 PetscCall(MatSolveTranspose(mat, b, x)); 4075 PetscCall(VecAXPY(x, one, y)); 4076 } else { 4077 PetscCall(VecDuplicate(x, &tmp)); 4078 PetscCall(VecCopy(x, tmp)); 4079 PetscCall(MatSolveTranspose(mat, b, x)); 4080 PetscCall(VecAXPY(x, one, tmp)); 4081 PetscCall(VecDestroy(&tmp)); 4082 } 4083 } 4084 PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y)); 4085 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4086 PetscFunctionReturn(PETSC_SUCCESS); 4087 } 4088 4089 /*@ 4090 MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps. 4091 4092 Neighbor-wise Collective 4093 4094 Input Parameters: 4095 + mat - the matrix 4096 . b - the right hand side 4097 . omega - the relaxation factor 4098 . flag - flag indicating the type of SOR (see below) 4099 . shift - diagonal shift 4100 . its - the number of iterations 4101 - lits - the number of local iterations 4102 4103 Output Parameter: 4104 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess) 4105 4106 SOR Flags: 4107 + `SOR_FORWARD_SWEEP` - forward SOR 4108 . `SOR_BACKWARD_SWEEP` - backward SOR 4109 . `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR) 4110 . `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR 4111 . `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR 4112 . `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR 4113 . `SOR_EISENSTAT` - SOR with Eisenstat trick 4114 . `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies 4115 upper/lower triangular part of matrix to 4116 vector (with omega) 4117 - `SOR_ZERO_INITIAL_GUESS` - zero initial guess 4118 4119 Level: developer 4120 4121 Notes: 4122 `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and 4123 `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings 4124 on each processor. 4125 4126 Application programmers will not generally use `MatSOR()` directly, 4127 but instead will employ the `KSP`/`PC` interface. 4128 4129 For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing 4130 4131 Most users should employ the `KSP` interface for linear solvers 4132 instead of working directly with matrix algebra routines such as this. 4133 See, e.g., `KSPCreate()`. 4134 4135 Vectors `x` and `b` CANNOT be the same 4136 4137 The flags are implemented as bitwise inclusive or operations. 4138 For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`) 4139 to specify a zero initial guess for SSOR. 4140 4141 Developer Note: 4142 We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes 4143 4144 .seealso: `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()` 4145 @*/ 4146 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x) 4147 { 4148 PetscFunctionBegin; 4149 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4150 PetscValidType(mat, 1); 4151 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4152 PetscValidHeaderSpecific(x, VEC_CLASSID, 8); 4153 PetscCheckSameComm(mat, 1, b, 2); 4154 PetscCheckSameComm(mat, 1, x, 8); 4155 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4156 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4157 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); 4158 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); 4159 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); 4160 PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its); 4161 PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits); 4162 PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same"); 4163 4164 MatCheckPreallocated(mat, 1); 4165 PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0)); 4166 PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x); 4167 PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0)); 4168 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4169 PetscFunctionReturn(PETSC_SUCCESS); 4170 } 4171 4172 /* 4173 Default matrix copy routine. 4174 */ 4175 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str) 4176 { 4177 PetscInt i, rstart = 0, rend = 0, nz; 4178 const PetscInt *cwork; 4179 const PetscScalar *vwork; 4180 4181 PetscFunctionBegin; 4182 if (B->assembled) PetscCall(MatZeroEntries(B)); 4183 if (str == SAME_NONZERO_PATTERN) { 4184 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 4185 for (i = rstart; i < rend; i++) { 4186 PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork)); 4187 PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES)); 4188 PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork)); 4189 } 4190 } else { 4191 PetscCall(MatAYPX(B, 0.0, A, str)); 4192 } 4193 PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 4194 PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 4195 PetscFunctionReturn(PETSC_SUCCESS); 4196 } 4197 4198 /*@ 4199 MatCopy - Copies a matrix to another matrix. 4200 4201 Collective 4202 4203 Input Parameters: 4204 + A - the matrix 4205 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN` 4206 4207 Output Parameter: 4208 . B - where the copy is put 4209 4210 Level: intermediate 4211 4212 Notes: 4213 If you use `SAME_NONZERO_PATTERN` then the two matrices must have the same nonzero pattern or the routine will crash. 4214 4215 `MatCopy()` copies the matrix entries of a matrix to another existing 4216 matrix (after first zeroing the second matrix). A related routine is 4217 `MatConvert()`, which first creates a new matrix and then copies the data. 4218 4219 .seealso: `Mat`, `MatConvert()`, `MatDuplicate()` 4220 @*/ 4221 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str) 4222 { 4223 PetscInt i; 4224 4225 PetscFunctionBegin; 4226 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 4227 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 4228 PetscValidType(A, 1); 4229 PetscValidType(B, 2); 4230 PetscCheckSameComm(A, 1, B, 2); 4231 MatCheckPreallocated(B, 2); 4232 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4233 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4234 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, 4235 A->cmap->N, B->cmap->N); 4236 MatCheckPreallocated(A, 1); 4237 if (A == B) PetscFunctionReturn(PETSC_SUCCESS); 4238 4239 PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0)); 4240 if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str); 4241 else PetscCall(MatCopy_Basic(A, B, str)); 4242 4243 B->stencil.dim = A->stencil.dim; 4244 B->stencil.noc = A->stencil.noc; 4245 for (i = 0; i <= A->stencil.dim; i++) { 4246 B->stencil.dims[i] = A->stencil.dims[i]; 4247 B->stencil.starts[i] = A->stencil.starts[i]; 4248 } 4249 4250 PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0)); 4251 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4252 PetscFunctionReturn(PETSC_SUCCESS); 4253 } 4254 4255 /*@C 4256 MatConvert - Converts a matrix to another matrix, either of the same 4257 or different type. 4258 4259 Collective 4260 4261 Input Parameters: 4262 + mat - the matrix 4263 . newtype - new matrix type. Use `MATSAME` to create a new matrix of the 4264 same type as the original matrix. 4265 - reuse - denotes if the destination matrix is to be created or reused. 4266 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 4267 `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). 4268 4269 Output Parameter: 4270 . M - pointer to place new matrix 4271 4272 Level: intermediate 4273 4274 Notes: 4275 `MatConvert()` first creates a new matrix and then copies the data from 4276 the first matrix. A related routine is `MatCopy()`, which copies the matrix 4277 entries of one matrix to another already existing matrix context. 4278 4279 Cannot be used to convert a sequential matrix to parallel or parallel to sequential, 4280 the MPI communicator of the generated matrix is always the same as the communicator 4281 of the input matrix. 4282 4283 .seealso: `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 4284 @*/ 4285 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M) 4286 { 4287 PetscBool sametype, issame, flg; 4288 PetscBool3 issymmetric, ishermitian; 4289 char convname[256], mtype[256]; 4290 Mat B; 4291 4292 PetscFunctionBegin; 4293 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4294 PetscValidType(mat, 1); 4295 PetscValidPointer(M, 4); 4296 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4297 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4298 MatCheckPreallocated(mat, 1); 4299 4300 PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg)); 4301 if (flg) newtype = mtype; 4302 4303 PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype)); 4304 PetscCall(PetscStrcmp(newtype, "same", &issame)); 4305 PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix"); 4306 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"); 4307 4308 if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) { 4309 PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4310 PetscFunctionReturn(PETSC_SUCCESS); 4311 } 4312 4313 /* Cache Mat options because some converters use MatHeaderReplace */ 4314 issymmetric = mat->symmetric; 4315 ishermitian = mat->hermitian; 4316 4317 if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) { 4318 PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4319 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4320 } else { 4321 PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL; 4322 const char *prefix[3] = {"seq", "mpi", ""}; 4323 PetscInt i; 4324 /* 4325 Order of precedence: 4326 0) See if newtype is a superclass of the current matrix. 4327 1) See if a specialized converter is known to the current matrix. 4328 2) See if a specialized converter is known to the desired matrix class. 4329 3) See if a good general converter is registered for the desired class 4330 (as of 6/27/03 only MATMPIADJ falls into this category). 4331 4) See if a good general converter is known for the current matrix. 4332 5) Use a really basic converter. 4333 */ 4334 4335 /* 0) See if newtype is a superclass of the current matrix. 4336 i.e mat is mpiaij and newtype is aij */ 4337 for (i = 0; i < 2; i++) { 4338 PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname))); 4339 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4340 PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg)); 4341 PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg)); 4342 if (flg) { 4343 if (reuse == MAT_INPLACE_MATRIX) { 4344 PetscCall(PetscInfo(mat, "Early return\n")); 4345 PetscFunctionReturn(PETSC_SUCCESS); 4346 } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) { 4347 PetscCall(PetscInfo(mat, "Calling MatDuplicate\n")); 4348 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4349 PetscFunctionReturn(PETSC_SUCCESS); 4350 } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) { 4351 PetscCall(PetscInfo(mat, "Calling MatCopy\n")); 4352 PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN)); 4353 PetscFunctionReturn(PETSC_SUCCESS); 4354 } 4355 } 4356 } 4357 /* 1) See if a specialized converter is known to the current matrix and the desired class */ 4358 for (i = 0; i < 3; i++) { 4359 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4360 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4361 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4362 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4363 PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname))); 4364 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4365 PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv)); 4366 PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv)); 4367 if (conv) goto foundconv; 4368 } 4369 4370 /* 2) See if a specialized converter is known to the desired matrix class. */ 4371 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B)); 4372 PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 4373 PetscCall(MatSetType(B, newtype)); 4374 for (i = 0; i < 3; i++) { 4375 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4376 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4377 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4378 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4379 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4380 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4381 PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv)); 4382 PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv)); 4383 if (conv) { 4384 PetscCall(MatDestroy(&B)); 4385 goto foundconv; 4386 } 4387 } 4388 4389 /* 3) See if a good general converter is registered for the desired class */ 4390 conv = B->ops->convertfrom; 4391 PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv)); 4392 PetscCall(MatDestroy(&B)); 4393 if (conv) goto foundconv; 4394 4395 /* 4) See if a good general converter is known for the current matrix */ 4396 if (mat->ops->convert) conv = mat->ops->convert; 4397 PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv)); 4398 if (conv) goto foundconv; 4399 4400 /* 5) Use a really basic converter. */ 4401 PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n")); 4402 conv = MatConvert_Basic; 4403 4404 foundconv: 4405 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4406 PetscCall((*conv)(mat, newtype, reuse, M)); 4407 if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) { 4408 /* the block sizes must be same if the mappings are copied over */ 4409 (*M)->rmap->bs = mat->rmap->bs; 4410 (*M)->cmap->bs = mat->cmap->bs; 4411 PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping)); 4412 PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping)); 4413 (*M)->rmap->mapping = mat->rmap->mapping; 4414 (*M)->cmap->mapping = mat->cmap->mapping; 4415 } 4416 (*M)->stencil.dim = mat->stencil.dim; 4417 (*M)->stencil.noc = mat->stencil.noc; 4418 for (i = 0; i <= mat->stencil.dim; i++) { 4419 (*M)->stencil.dims[i] = mat->stencil.dims[i]; 4420 (*M)->stencil.starts[i] = mat->stencil.starts[i]; 4421 } 4422 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4423 } 4424 PetscCall(PetscObjectStateIncrease((PetscObject)*M)); 4425 4426 /* Copy Mat options */ 4427 if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE)); 4428 else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE)); 4429 if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE)); 4430 else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE)); 4431 PetscFunctionReturn(PETSC_SUCCESS); 4432 } 4433 4434 /*@C 4435 MatFactorGetSolverType - Returns name of the package providing the factorization routines 4436 4437 Not Collective 4438 4439 Input Parameter: 4440 . mat - the matrix, must be a factored matrix 4441 4442 Output Parameter: 4443 . type - the string name of the package (do not free this string) 4444 4445 Level: intermediate 4446 4447 Fortran Note: 4448 Pass in an empty string and the package name will be copied into it. Make sure the string is long enough. 4449 4450 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()` 4451 @*/ 4452 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type) 4453 { 4454 PetscErrorCode (*conv)(Mat, MatSolverType *); 4455 4456 PetscFunctionBegin; 4457 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4458 PetscValidType(mat, 1); 4459 PetscValidPointer(type, 2); 4460 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 4461 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv)); 4462 if (conv) PetscCall((*conv)(mat, type)); 4463 else *type = MATSOLVERPETSC; 4464 PetscFunctionReturn(PETSC_SUCCESS); 4465 } 4466 4467 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType; 4468 struct _MatSolverTypeForSpecifcType { 4469 MatType mtype; 4470 /* no entry for MAT_FACTOR_NONE */ 4471 PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *); 4472 MatSolverTypeForSpecifcType next; 4473 }; 4474 4475 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder; 4476 struct _MatSolverTypeHolder { 4477 char *name; 4478 MatSolverTypeForSpecifcType handlers; 4479 MatSolverTypeHolder next; 4480 }; 4481 4482 static MatSolverTypeHolder MatSolverTypeHolders = NULL; 4483 4484 /*@C 4485 MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type 4486 4487 Input Parameters: 4488 + package - name of the package, for example petsc or superlu 4489 . mtype - the matrix type that works with this package 4490 . ftype - the type of factorization supported by the package 4491 - createfactor - routine that will create the factored matrix ready to be used 4492 4493 Level: developer 4494 4495 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()` 4496 @*/ 4497 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *)) 4498 { 4499 MatSolverTypeHolder next = MatSolverTypeHolders, prev = NULL; 4500 PetscBool flg; 4501 MatSolverTypeForSpecifcType inext, iprev = NULL; 4502 4503 PetscFunctionBegin; 4504 PetscCall(MatInitializePackage()); 4505 if (!next) { 4506 PetscCall(PetscNew(&MatSolverTypeHolders)); 4507 PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name)); 4508 PetscCall(PetscNew(&MatSolverTypeHolders->handlers)); 4509 PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype)); 4510 MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor; 4511 PetscFunctionReturn(PETSC_SUCCESS); 4512 } 4513 while (next) { 4514 PetscCall(PetscStrcasecmp(package, next->name, &flg)); 4515 if (flg) { 4516 PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers"); 4517 inext = next->handlers; 4518 while (inext) { 4519 PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg)); 4520 if (flg) { 4521 inext->createfactor[(int)ftype - 1] = createfactor; 4522 PetscFunctionReturn(PETSC_SUCCESS); 4523 } 4524 iprev = inext; 4525 inext = inext->next; 4526 } 4527 PetscCall(PetscNew(&iprev->next)); 4528 PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype)); 4529 iprev->next->createfactor[(int)ftype - 1] = createfactor; 4530 PetscFunctionReturn(PETSC_SUCCESS); 4531 } 4532 prev = next; 4533 next = next->next; 4534 } 4535 PetscCall(PetscNew(&prev->next)); 4536 PetscCall(PetscStrallocpy(package, &prev->next->name)); 4537 PetscCall(PetscNew(&prev->next->handlers)); 4538 PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype)); 4539 prev->next->handlers->createfactor[(int)ftype - 1] = createfactor; 4540 PetscFunctionReturn(PETSC_SUCCESS); 4541 } 4542 4543 /*@C 4544 MatSolverTypeGet - Gets the function that creates the factor matrix if it exist 4545 4546 Input Parameters: 4547 + type - name of the package, for example petsc or superlu 4548 . ftype - the type of factorization supported by the type 4549 - mtype - the matrix type that works with this type 4550 4551 Output Parameters: 4552 + foundtype - `PETSC_TRUE` if the type was registered 4553 . foundmtype - `PETSC_TRUE` if the type supports the requested mtype 4554 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found 4555 4556 Level: developer 4557 4558 .seealso: `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()` 4559 @*/ 4560 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *)) 4561 { 4562 MatSolverTypeHolder next = MatSolverTypeHolders; 4563 PetscBool flg; 4564 MatSolverTypeForSpecifcType inext; 4565 4566 PetscFunctionBegin; 4567 if (foundtype) *foundtype = PETSC_FALSE; 4568 if (foundmtype) *foundmtype = PETSC_FALSE; 4569 if (createfactor) *createfactor = NULL; 4570 4571 if (type) { 4572 while (next) { 4573 PetscCall(PetscStrcasecmp(type, next->name, &flg)); 4574 if (flg) { 4575 if (foundtype) *foundtype = PETSC_TRUE; 4576 inext = next->handlers; 4577 while (inext) { 4578 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4579 if (flg) { 4580 if (foundmtype) *foundmtype = PETSC_TRUE; 4581 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4582 PetscFunctionReturn(PETSC_SUCCESS); 4583 } 4584 inext = inext->next; 4585 } 4586 } 4587 next = next->next; 4588 } 4589 } else { 4590 while (next) { 4591 inext = next->handlers; 4592 while (inext) { 4593 PetscCall(PetscStrcmp(mtype, inext->mtype, &flg)); 4594 if (flg && inext->createfactor[(int)ftype - 1]) { 4595 if (foundtype) *foundtype = PETSC_TRUE; 4596 if (foundmtype) *foundmtype = PETSC_TRUE; 4597 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4598 PetscFunctionReturn(PETSC_SUCCESS); 4599 } 4600 inext = inext->next; 4601 } 4602 next = next->next; 4603 } 4604 /* try with base classes inext->mtype */ 4605 next = MatSolverTypeHolders; 4606 while (next) { 4607 inext = next->handlers; 4608 while (inext) { 4609 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4610 if (flg && inext->createfactor[(int)ftype - 1]) { 4611 if (foundtype) *foundtype = PETSC_TRUE; 4612 if (foundmtype) *foundmtype = PETSC_TRUE; 4613 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4614 PetscFunctionReturn(PETSC_SUCCESS); 4615 } 4616 inext = inext->next; 4617 } 4618 next = next->next; 4619 } 4620 } 4621 PetscFunctionReturn(PETSC_SUCCESS); 4622 } 4623 4624 PetscErrorCode MatSolverTypeDestroy(void) 4625 { 4626 MatSolverTypeHolder next = MatSolverTypeHolders, prev; 4627 MatSolverTypeForSpecifcType inext, iprev; 4628 4629 PetscFunctionBegin; 4630 while (next) { 4631 PetscCall(PetscFree(next->name)); 4632 inext = next->handlers; 4633 while (inext) { 4634 PetscCall(PetscFree(inext->mtype)); 4635 iprev = inext; 4636 inext = inext->next; 4637 PetscCall(PetscFree(iprev)); 4638 } 4639 prev = next; 4640 next = next->next; 4641 PetscCall(PetscFree(prev)); 4642 } 4643 MatSolverTypeHolders = NULL; 4644 PetscFunctionReturn(PETSC_SUCCESS); 4645 } 4646 4647 /*@C 4648 MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4649 4650 Logically Collective 4651 4652 Input Parameters: 4653 . mat - the matrix 4654 4655 Output Parameters: 4656 . flg - `PETSC_TRUE` if uses the ordering 4657 4658 Level: developer 4659 4660 Note: 4661 Most internal PETSc factorizations use the ordering passed to the factorization routine but external 4662 packages do not, thus we want to skip generating the ordering when it is not needed or used. 4663 4664 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4665 @*/ 4666 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg) 4667 { 4668 PetscFunctionBegin; 4669 *flg = mat->canuseordering; 4670 PetscFunctionReturn(PETSC_SUCCESS); 4671 } 4672 4673 /*@C 4674 MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object 4675 4676 Logically Collective 4677 4678 Input Parameters: 4679 . mat - the matrix obtained with `MatGetFactor()` 4680 4681 Output Parameters: 4682 . otype - the preferred type 4683 4684 Level: developer 4685 4686 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4687 @*/ 4688 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype) 4689 { 4690 PetscFunctionBegin; 4691 *otype = mat->preferredordering[ftype]; 4692 PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering"); 4693 PetscFunctionReturn(PETSC_SUCCESS); 4694 } 4695 4696 /*@C 4697 MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic() 4698 4699 Collective 4700 4701 Input Parameters: 4702 + mat - the matrix 4703 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4704 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4705 4706 Output Parameters: 4707 . f - the factor matrix used with MatXXFactorSymbolic() calls 4708 4709 Options Database Key: 4710 . -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory. 4711 One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices. 4712 4713 Level: intermediate 4714 4715 Notes: 4716 Users usually access the factorization solvers via `KSP` 4717 4718 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4719 such as pastix, superlu, mumps etc. 4720 4721 PETSc must have been ./configure to use the external solver, using the option --download-package 4722 4723 Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption 4724 where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set 4725 call `MatSetOptionsPrefixFactor()` on the originating matrix or `MatSetOptionsPrefix()` on the resulting factor matrix. 4726 4727 Developer Note: 4728 This should actually be called `MatCreateFactor()` since it creates a new factor object 4729 4730 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, 4731 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4732 @*/ 4733 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f) 4734 { 4735 PetscBool foundtype, foundmtype; 4736 PetscErrorCode (*conv)(Mat, MatFactorType, Mat *); 4737 4738 PetscFunctionBegin; 4739 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4740 PetscValidType(mat, 1); 4741 4742 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4743 MatCheckPreallocated(mat, 1); 4744 4745 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv)); 4746 if (!foundtype) { 4747 if (type) { 4748 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], 4749 ((PetscObject)mat)->type_name, type); 4750 } else { 4751 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); 4752 } 4753 } 4754 PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name); 4755 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); 4756 4757 PetscCall((*conv)(mat, ftype, f)); 4758 if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix)); 4759 PetscFunctionReturn(PETSC_SUCCESS); 4760 } 4761 4762 /*@C 4763 MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type 4764 4765 Not Collective 4766 4767 Input Parameters: 4768 + mat - the matrix 4769 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4770 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4771 4772 Output Parameter: 4773 . flg - PETSC_TRUE if the factorization is available 4774 4775 Level: intermediate 4776 4777 Notes: 4778 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4779 such as pastix, superlu, mumps etc. 4780 4781 PETSc must have been ./configure to use the external solver, using the option --download-package 4782 4783 Developer Note: 4784 This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object 4785 4786 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactor()`, `MatSolverTypeRegister()`, 4787 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4788 @*/ 4789 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg) 4790 { 4791 PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *); 4792 4793 PetscFunctionBegin; 4794 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4795 PetscValidType(mat, 1); 4796 PetscValidBoolPointer(flg, 4); 4797 4798 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4799 MatCheckPreallocated(mat, 1); 4800 4801 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv)); 4802 *flg = gconv ? PETSC_TRUE : PETSC_FALSE; 4803 PetscFunctionReturn(PETSC_SUCCESS); 4804 } 4805 4806 /*@ 4807 MatDuplicate - Duplicates a matrix including the non-zero structure. 4808 4809 Collective 4810 4811 Input Parameters: 4812 + mat - the matrix 4813 - op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`. 4814 See the manual page for `MatDuplicateOption()` for an explanation of these options. 4815 4816 Output Parameter: 4817 . M - pointer to place new matrix 4818 4819 Level: intermediate 4820 4821 Notes: 4822 You cannot change the nonzero pattern for the parent or child matrix if you use `MAT_SHARE_NONZERO_PATTERN`. 4823 4824 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. 4825 4826 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 4827 is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated. 4828 User should not use `MatDuplicate()` to create new matrix M if M is intended to be reused as the product of matrix operation. 4829 4830 .seealso: `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption` 4831 @*/ 4832 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M) 4833 { 4834 Mat B; 4835 VecType vtype; 4836 PetscInt i; 4837 PetscObject dm; 4838 void (*viewf)(void); 4839 4840 PetscFunctionBegin; 4841 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4842 PetscValidType(mat, 1); 4843 PetscValidPointer(M, 3); 4844 PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix"); 4845 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4846 MatCheckPreallocated(mat, 1); 4847 4848 *M = NULL; 4849 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4850 PetscUseTypeMethod(mat, duplicate, op, M); 4851 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4852 B = *M; 4853 4854 PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf)); 4855 if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf)); 4856 PetscCall(MatGetVecType(mat, &vtype)); 4857 PetscCall(MatSetVecType(B, vtype)); 4858 4859 B->stencil.dim = mat->stencil.dim; 4860 B->stencil.noc = mat->stencil.noc; 4861 for (i = 0; i <= mat->stencil.dim; i++) { 4862 B->stencil.dims[i] = mat->stencil.dims[i]; 4863 B->stencil.starts[i] = mat->stencil.starts[i]; 4864 } 4865 4866 B->nooffproczerorows = mat->nooffproczerorows; 4867 B->nooffprocentries = mat->nooffprocentries; 4868 4869 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm)); 4870 if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm)); 4871 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4872 PetscFunctionReturn(PETSC_SUCCESS); 4873 } 4874 4875 /*@ 4876 MatGetDiagonal - Gets the diagonal of a matrix as a `Vec` 4877 4878 Logically Collective 4879 4880 Input Parameters: 4881 + mat - the matrix 4882 - v - the vector for storing the diagonal 4883 4884 Output Parameter: 4885 . v - the diagonal of the matrix 4886 4887 Level: intermediate 4888 4889 Note: 4890 Currently only correct in parallel for square matrices. 4891 4892 .seealso: `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()` 4893 @*/ 4894 PetscErrorCode MatGetDiagonal(Mat mat, Vec v) 4895 { 4896 PetscFunctionBegin; 4897 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4898 PetscValidType(mat, 1); 4899 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4900 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4901 MatCheckPreallocated(mat, 1); 4902 4903 PetscUseTypeMethod(mat, getdiagonal, v); 4904 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4905 PetscFunctionReturn(PETSC_SUCCESS); 4906 } 4907 4908 /*@C 4909 MatGetRowMin - Gets the minimum value (of the real part) of each 4910 row of the matrix 4911 4912 Logically Collective 4913 4914 Input Parameter: 4915 . mat - the matrix 4916 4917 Output Parameters: 4918 + v - the vector for storing the maximums 4919 - idx - the indices of the column found for each row (optional) 4920 4921 Level: intermediate 4922 4923 Note: 4924 The result of this call are the same as if one converted the matrix to dense format 4925 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 4926 4927 This code is only implemented for a couple of matrix formats. 4928 4929 .seealso: `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, 4930 `MatGetRowMax()` 4931 @*/ 4932 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[]) 4933 { 4934 PetscFunctionBegin; 4935 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4936 PetscValidType(mat, 1); 4937 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4938 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4939 4940 if (!mat->cmap->N) { 4941 PetscCall(VecSet(v, PETSC_MAX_REAL)); 4942 if (idx) { 4943 PetscInt i, m = mat->rmap->n; 4944 for (i = 0; i < m; i++) idx[i] = -1; 4945 } 4946 } else { 4947 MatCheckPreallocated(mat, 1); 4948 } 4949 PetscUseTypeMethod(mat, getrowmin, v, idx); 4950 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4951 PetscFunctionReturn(PETSC_SUCCESS); 4952 } 4953 4954 /*@C 4955 MatGetRowMinAbs - Gets the minimum value (in absolute value) of each 4956 row of the matrix 4957 4958 Logically Collective 4959 4960 Input Parameter: 4961 . mat - the matrix 4962 4963 Output Parameters: 4964 + v - the vector for storing the minimums 4965 - idx - the indices of the column found for each row (or `NULL` if not needed) 4966 4967 Level: intermediate 4968 4969 Notes: 4970 if a row is completely empty or has only 0.0 values then the idx[] value for that 4971 row is 0 (the first column). 4972 4973 This code is only implemented for a couple of matrix formats. 4974 4975 .seealso: `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()` 4976 @*/ 4977 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[]) 4978 { 4979 PetscFunctionBegin; 4980 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4981 PetscValidType(mat, 1); 4982 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 4983 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4984 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4985 4986 if (!mat->cmap->N) { 4987 PetscCall(VecSet(v, 0.0)); 4988 if (idx) { 4989 PetscInt i, m = mat->rmap->n; 4990 for (i = 0; i < m; i++) idx[i] = -1; 4991 } 4992 } else { 4993 MatCheckPreallocated(mat, 1); 4994 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 4995 PetscUseTypeMethod(mat, getrowminabs, v, idx); 4996 } 4997 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 4998 PetscFunctionReturn(PETSC_SUCCESS); 4999 } 5000 5001 /*@C 5002 MatGetRowMax - Gets the maximum value (of the real part) of each 5003 row of the matrix 5004 5005 Logically Collective 5006 5007 Input Parameter: 5008 . mat - the matrix 5009 5010 Output Parameters: 5011 + v - the vector for storing the maximums 5012 - idx - the indices of the column found for each row (optional) 5013 5014 Level: intermediate 5015 5016 Notes: 5017 The result of this call are the same as if one converted the matrix to dense format 5018 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5019 5020 This code is only implemented for a couple of matrix formats. 5021 5022 .seealso: `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5023 @*/ 5024 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[]) 5025 { 5026 PetscFunctionBegin; 5027 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5028 PetscValidType(mat, 1); 5029 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5030 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5031 5032 if (!mat->cmap->N) { 5033 PetscCall(VecSet(v, PETSC_MIN_REAL)); 5034 if (idx) { 5035 PetscInt i, m = mat->rmap->n; 5036 for (i = 0; i < m; i++) idx[i] = -1; 5037 } 5038 } else { 5039 MatCheckPreallocated(mat, 1); 5040 PetscUseTypeMethod(mat, getrowmax, v, idx); 5041 } 5042 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5043 PetscFunctionReturn(PETSC_SUCCESS); 5044 } 5045 5046 /*@C 5047 MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each 5048 row of the matrix 5049 5050 Logically Collective 5051 5052 Input Parameter: 5053 . mat - the matrix 5054 5055 Output Parameters: 5056 + v - the vector for storing the maximums 5057 - idx - the indices of the column found for each row (or `NULL` if not needed) 5058 5059 Level: intermediate 5060 5061 Notes: 5062 if a row is completely empty or has only 0.0 values then the idx[] value for that 5063 row is 0 (the first column). 5064 5065 This code is only implemented for a couple of matrix formats. 5066 5067 .seealso: `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5068 @*/ 5069 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[]) 5070 { 5071 PetscFunctionBegin; 5072 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5073 PetscValidType(mat, 1); 5074 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5075 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5076 5077 if (!mat->cmap->N) { 5078 PetscCall(VecSet(v, 0.0)); 5079 if (idx) { 5080 PetscInt i, m = mat->rmap->n; 5081 for (i = 0; i < m; i++) idx[i] = -1; 5082 } 5083 } else { 5084 MatCheckPreallocated(mat, 1); 5085 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5086 PetscUseTypeMethod(mat, getrowmaxabs, v, idx); 5087 } 5088 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5089 PetscFunctionReturn(PETSC_SUCCESS); 5090 } 5091 5092 /*@ 5093 MatGetRowSum - Gets the sum of each row of the matrix 5094 5095 Logically or Neighborhood Collective 5096 5097 Input Parameters: 5098 . mat - the matrix 5099 5100 Output Parameter: 5101 . v - the vector for storing the sum of rows 5102 5103 Level: intermediate 5104 5105 Notes: 5106 This code is slow since it is not currently specialized for different formats 5107 5108 .seealso: `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()` 5109 @*/ 5110 PetscErrorCode MatGetRowSum(Mat mat, Vec v) 5111 { 5112 Vec ones; 5113 5114 PetscFunctionBegin; 5115 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5116 PetscValidType(mat, 1); 5117 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5118 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5119 MatCheckPreallocated(mat, 1); 5120 PetscCall(MatCreateVecs(mat, &ones, NULL)); 5121 PetscCall(VecSet(ones, 1.)); 5122 PetscCall(MatMult(mat, ones, v)); 5123 PetscCall(VecDestroy(&ones)); 5124 PetscFunctionReturn(PETSC_SUCCESS); 5125 } 5126 5127 /*@ 5128 MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) 5129 when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B) 5130 5131 Collective 5132 5133 Input Parameter: 5134 . mat - the matrix to provide the transpose 5135 5136 Output Parameter: 5137 . 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 5138 5139 Level: advanced 5140 5141 Note: 5142 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 5143 routine allows bypassing that call. 5144 5145 .seealso: `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5146 @*/ 5147 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B) 5148 { 5149 PetscContainer rB = NULL; 5150 MatParentState *rb = NULL; 5151 5152 PetscFunctionBegin; 5153 PetscCall(PetscNew(&rb)); 5154 rb->id = ((PetscObject)mat)->id; 5155 rb->state = 0; 5156 PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate)); 5157 PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB)); 5158 PetscCall(PetscContainerSetPointer(rB, rb)); 5159 PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault)); 5160 PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB)); 5161 PetscCall(PetscObjectDereference((PetscObject)rB)); 5162 PetscFunctionReturn(PETSC_SUCCESS); 5163 } 5164 5165 /*@ 5166 MatTranspose - Computes an in-place or out-of-place transpose of a matrix. 5167 5168 Collective 5169 5170 Input Parameters: 5171 + mat - the matrix to transpose 5172 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5173 5174 Output Parameter: 5175 . B - the transpose 5176 5177 Level: intermediate 5178 5179 Notes: 5180 If you use `MAT_INPLACE_MATRIX` then you must pass in &mat for B 5181 5182 `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 5183 transpose, call `MatTransposeSetPrecursor`(mat,B) before calling this routine. 5184 5185 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. 5186 5187 Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed. 5188 5189 If mat is unchanged from the last call this function returns immediately without recomputing the result 5190 5191 If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()` 5192 5193 .seealso: `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`, 5194 `MatTransposeSymbolic()`, `MatCreateTranspose()` 5195 @*/ 5196 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B) 5197 { 5198 PetscContainer rB = NULL; 5199 MatParentState *rb = NULL; 5200 5201 PetscFunctionBegin; 5202 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5203 PetscValidType(mat, 1); 5204 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5205 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5206 PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first"); 5207 PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX"); 5208 MatCheckPreallocated(mat, 1); 5209 if (reuse == MAT_REUSE_MATRIX) { 5210 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5211 PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor()."); 5212 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5213 PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5214 if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS); 5215 } 5216 5217 PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0)); 5218 if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) { 5219 PetscUseTypeMethod(mat, transpose, reuse, B); 5220 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5221 } 5222 PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0)); 5223 5224 if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B)); 5225 if (reuse != MAT_INPLACE_MATRIX) { 5226 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5227 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5228 rb->state = ((PetscObject)mat)->state; 5229 rb->nonzerostate = mat->nonzerostate; 5230 } 5231 PetscFunctionReturn(PETSC_SUCCESS); 5232 } 5233 5234 /*@ 5235 MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix. 5236 5237 Collective 5238 5239 Input Parameters: 5240 . A - the matrix to transpose 5241 5242 Output Parameter: 5243 . 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 5244 numerical portion. 5245 5246 Level: intermediate 5247 5248 Note: 5249 This is not supported for many matrix types, use `MatTranspose()` in those cases 5250 5251 .seealso: `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5252 @*/ 5253 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B) 5254 { 5255 PetscFunctionBegin; 5256 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5257 PetscValidType(A, 1); 5258 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5259 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5260 PetscCheck(A->ops->transposesymbolic, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 5261 PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0)); 5262 PetscCall((*A->ops->transposesymbolic)(A, B)); 5263 PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0)); 5264 5265 PetscCall(MatTransposeSetPrecursor(A, *B)); 5266 PetscFunctionReturn(PETSC_SUCCESS); 5267 } 5268 5269 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B) 5270 { 5271 PetscContainer rB; 5272 MatParentState *rb; 5273 5274 PetscFunctionBegin; 5275 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5276 PetscValidType(A, 1); 5277 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5278 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5279 PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB)); 5280 PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()"); 5281 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5282 PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5283 PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure"); 5284 PetscFunctionReturn(PETSC_SUCCESS); 5285 } 5286 5287 /*@ 5288 MatIsTranspose - Test whether a matrix is another one's transpose, 5289 or its own, in which case it tests symmetry. 5290 5291 Collective 5292 5293 Input Parameters: 5294 + A - the matrix to test 5295 - B - the matrix to test against, this can equal the first parameter 5296 5297 Output Parameters: 5298 . flg - the result 5299 5300 Level: intermediate 5301 5302 Notes: 5303 Only available for `MATAIJ` matrices. 5304 5305 The sequential algorithm has a running time of the order of the number of nonzeros; the parallel 5306 test involves parallel copies of the block-offdiagonal parts of the matrix. 5307 5308 .seealso: `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()` 5309 @*/ 5310 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5311 { 5312 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5313 5314 PetscFunctionBegin; 5315 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5316 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5317 PetscValidBoolPointer(flg, 4); 5318 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f)); 5319 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g)); 5320 *flg = PETSC_FALSE; 5321 if (f && g) { 5322 PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test"); 5323 PetscCall((*f)(A, B, tol, flg)); 5324 } else { 5325 MatType mattype; 5326 5327 PetscCall(MatGetType(f ? B : A, &mattype)); 5328 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype); 5329 } 5330 PetscFunctionReturn(PETSC_SUCCESS); 5331 } 5332 5333 /*@ 5334 MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate. 5335 5336 Collective 5337 5338 Input Parameters: 5339 + mat - the matrix to transpose and complex conjugate 5340 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5341 5342 Output Parameter: 5343 . B - the Hermitian transpose 5344 5345 Level: intermediate 5346 5347 .seealso: `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse` 5348 @*/ 5349 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B) 5350 { 5351 PetscFunctionBegin; 5352 PetscCall(MatTranspose(mat, reuse, B)); 5353 #if defined(PETSC_USE_COMPLEX) 5354 PetscCall(MatConjugate(*B)); 5355 #endif 5356 PetscFunctionReturn(PETSC_SUCCESS); 5357 } 5358 5359 /*@ 5360 MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose, 5361 5362 Collective 5363 5364 Input Parameters: 5365 + A - the matrix to test 5366 - B - the matrix to test against, this can equal the first parameter 5367 5368 Output Parameters: 5369 . flg - the result 5370 5371 Level: intermediate 5372 5373 Notes: 5374 Only available for `MATAIJ` matrices. 5375 5376 The sequential algorithm 5377 has a running time of the order of the number of nonzeros; the parallel 5378 test involves parallel copies of the block-offdiagonal parts of the matrix. 5379 5380 .seealso: `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()` 5381 @*/ 5382 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5383 { 5384 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5385 5386 PetscFunctionBegin; 5387 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5388 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5389 PetscValidBoolPointer(flg, 4); 5390 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f)); 5391 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g)); 5392 if (f && g) { 5393 PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test"); 5394 PetscCall((*f)(A, B, tol, flg)); 5395 } 5396 PetscFunctionReturn(PETSC_SUCCESS); 5397 } 5398 5399 /*@ 5400 MatPermute - Creates a new matrix with rows and columns permuted from the 5401 original. 5402 5403 Collective 5404 5405 Input Parameters: 5406 + mat - the matrix to permute 5407 . row - row permutation, each processor supplies only the permutation for its rows 5408 - col - column permutation, each processor supplies only the permutation for its columns 5409 5410 Output Parameters: 5411 . B - the permuted matrix 5412 5413 Level: advanced 5414 5415 Note: 5416 The index sets map from row/col of permuted matrix to row/col of original matrix. 5417 The index sets should be on the same communicator as mat and have the same local sizes. 5418 5419 Developer Note: 5420 If you want to implement `MatPermute()` for a matrix type, and your approach doesn't 5421 exploit the fact that row and col are permutations, consider implementing the 5422 more general `MatCreateSubMatrix()` instead. 5423 5424 .seealso: `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()` 5425 @*/ 5426 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B) 5427 { 5428 PetscFunctionBegin; 5429 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5430 PetscValidType(mat, 1); 5431 PetscValidHeaderSpecific(row, IS_CLASSID, 2); 5432 PetscValidHeaderSpecific(col, IS_CLASSID, 3); 5433 PetscValidPointer(B, 4); 5434 PetscCheckSameComm(mat, 1, row, 2); 5435 if (row != col) PetscCheckSameComm(row, 2, col, 3); 5436 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5437 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5438 PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name); 5439 MatCheckPreallocated(mat, 1); 5440 5441 if (mat->ops->permute) { 5442 PetscUseTypeMethod(mat, permute, row, col, B); 5443 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5444 } else { 5445 PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B)); 5446 } 5447 PetscFunctionReturn(PETSC_SUCCESS); 5448 } 5449 5450 /*@ 5451 MatEqual - Compares two matrices. 5452 5453 Collective 5454 5455 Input Parameters: 5456 + A - the first matrix 5457 - B - the second matrix 5458 5459 Output Parameter: 5460 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise. 5461 5462 Level: intermediate 5463 5464 .seealso: `Mat` 5465 @*/ 5466 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg) 5467 { 5468 PetscFunctionBegin; 5469 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5470 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5471 PetscValidType(A, 1); 5472 PetscValidType(B, 2); 5473 PetscValidBoolPointer(flg, 3); 5474 PetscCheckSameComm(A, 1, B, 2); 5475 MatCheckPreallocated(A, 1); 5476 MatCheckPreallocated(B, 2); 5477 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5478 PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5479 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, 5480 B->cmap->N); 5481 if (A->ops->equal && A->ops->equal == B->ops->equal) { 5482 PetscUseTypeMethod(A, equal, B, flg); 5483 } else { 5484 PetscCall(MatMultEqual(A, B, 10, flg)); 5485 } 5486 PetscFunctionReturn(PETSC_SUCCESS); 5487 } 5488 5489 /*@ 5490 MatDiagonalScale - Scales a matrix on the left and right by diagonal 5491 matrices that are stored as vectors. Either of the two scaling 5492 matrices can be `NULL`. 5493 5494 Collective 5495 5496 Input Parameters: 5497 + mat - the matrix to be scaled 5498 . l - the left scaling vector (or `NULL`) 5499 - r - the right scaling vector (or `NULL`) 5500 5501 Level: intermediate 5502 5503 Note: 5504 `MatDiagonalScale()` computes A = LAR, where 5505 L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector) 5506 The L scales the rows of the matrix, the R scales the columns of the matrix. 5507 5508 .seealso: `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()` 5509 @*/ 5510 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r) 5511 { 5512 PetscFunctionBegin; 5513 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5514 PetscValidType(mat, 1); 5515 if (l) { 5516 PetscValidHeaderSpecific(l, VEC_CLASSID, 2); 5517 PetscCheckSameComm(mat, 1, l, 2); 5518 } 5519 if (r) { 5520 PetscValidHeaderSpecific(r, VEC_CLASSID, 3); 5521 PetscCheckSameComm(mat, 1, r, 3); 5522 } 5523 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5524 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5525 MatCheckPreallocated(mat, 1); 5526 if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS); 5527 5528 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5529 PetscUseTypeMethod(mat, diagonalscale, l, r); 5530 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5531 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5532 if (l != r) mat->symmetric = PETSC_BOOL3_FALSE; 5533 PetscFunctionReturn(PETSC_SUCCESS); 5534 } 5535 5536 /*@ 5537 MatScale - Scales all elements of a matrix by a given number. 5538 5539 Logically Collective 5540 5541 Input Parameters: 5542 + mat - the matrix to be scaled 5543 - a - the scaling value 5544 5545 Output Parameter: 5546 . mat - the scaled matrix 5547 5548 Level: intermediate 5549 5550 .seealso: `Mat`, `MatDiagonalScale()` 5551 @*/ 5552 PetscErrorCode MatScale(Mat mat, PetscScalar a) 5553 { 5554 PetscFunctionBegin; 5555 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5556 PetscValidType(mat, 1); 5557 PetscCheck(a == (PetscScalar)1.0 || mat->ops->scale, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 5558 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5559 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5560 PetscValidLogicalCollectiveScalar(mat, a, 2); 5561 MatCheckPreallocated(mat, 1); 5562 5563 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5564 if (a != (PetscScalar)1.0) { 5565 PetscUseTypeMethod(mat, scale, a); 5566 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5567 } 5568 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5569 PetscFunctionReturn(PETSC_SUCCESS); 5570 } 5571 5572 /*@ 5573 MatNorm - Calculates various norms of a matrix. 5574 5575 Collective 5576 5577 Input Parameters: 5578 + mat - the matrix 5579 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY` 5580 5581 Output Parameter: 5582 . nrm - the resulting norm 5583 5584 Level: intermediate 5585 5586 .seealso: `Mat` 5587 @*/ 5588 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm) 5589 { 5590 PetscFunctionBegin; 5591 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5592 PetscValidType(mat, 1); 5593 PetscValidRealPointer(nrm, 3); 5594 5595 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5596 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5597 MatCheckPreallocated(mat, 1); 5598 5599 PetscUseTypeMethod(mat, norm, type, nrm); 5600 PetscFunctionReturn(PETSC_SUCCESS); 5601 } 5602 5603 /* 5604 This variable is used to prevent counting of MatAssemblyBegin() that 5605 are called from within a MatAssemblyEnd(). 5606 */ 5607 static PetscInt MatAssemblyEnd_InUse = 0; 5608 /*@ 5609 MatAssemblyBegin - Begins assembling the matrix. This routine should 5610 be called after completing all calls to `MatSetValues()`. 5611 5612 Collective 5613 5614 Input Parameters: 5615 + mat - the matrix 5616 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5617 5618 Level: beginner 5619 5620 Notes: 5621 `MatSetValues()` generally caches the values that belong to other MPI ranks. The matrix is ready to 5622 use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called. 5623 5624 Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES` 5625 in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before 5626 using the matrix. 5627 5628 ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the 5629 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 5630 a global collective operation requiring all processes that share the matrix. 5631 5632 Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed 5633 out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros 5634 before `MAT_FINAL_ASSEMBLY` so the space is not compressed out. 5635 5636 .seealso: `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()` 5637 @*/ 5638 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type) 5639 { 5640 PetscFunctionBegin; 5641 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5642 PetscValidType(mat, 1); 5643 MatCheckPreallocated(mat, 1); 5644 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?"); 5645 if (mat->assembled) { 5646 mat->was_assembled = PETSC_TRUE; 5647 mat->assembled = PETSC_FALSE; 5648 } 5649 5650 if (!MatAssemblyEnd_InUse) { 5651 PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0)); 5652 PetscTryTypeMethod(mat, assemblybegin, type); 5653 PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0)); 5654 } else PetscTryTypeMethod(mat, assemblybegin, type); 5655 PetscFunctionReturn(PETSC_SUCCESS); 5656 } 5657 5658 /*@ 5659 MatAssembled - Indicates if a matrix has been assembled and is ready for 5660 use; for example, in matrix-vector product. 5661 5662 Not Collective 5663 5664 Input Parameter: 5665 . mat - the matrix 5666 5667 Output Parameter: 5668 . assembled - `PETSC_TRUE` or `PETSC_FALSE` 5669 5670 Level: advanced 5671 5672 .seealso: `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()` 5673 @*/ 5674 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled) 5675 { 5676 PetscFunctionBegin; 5677 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5678 PetscValidBoolPointer(assembled, 2); 5679 *assembled = mat->assembled; 5680 PetscFunctionReturn(PETSC_SUCCESS); 5681 } 5682 5683 /*@ 5684 MatAssemblyEnd - Completes assembling the matrix. This routine should 5685 be called after `MatAssemblyBegin()`. 5686 5687 Collective on Mat 5688 5689 Input Parameters: 5690 + mat - the matrix 5691 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5692 5693 Options Database Keys: 5694 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatEndAssembly()` 5695 . -mat_view ::ascii_info_detail - Prints more detailed info 5696 . -mat_view - Prints matrix in ASCII format 5697 . -mat_view ::ascii_matlab - Prints matrix in Matlab format 5698 . -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 5699 . -display <name> - Sets display name (default is host) 5700 . -draw_pause <sec> - Sets number of seconds to pause after display 5701 . -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See [Using MATLAB with PETSc](ch_matlab)) 5702 . -viewer_socket_machine <machine> - Machine to use for socket 5703 . -viewer_socket_port <port> - Port number to use for socket 5704 - -mat_view binary:filename[:append] - Save matrix to file in binary format 5705 5706 Level: beginner 5707 5708 .seealso: `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()` 5709 @*/ 5710 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type) 5711 { 5712 static PetscInt inassm = 0; 5713 PetscBool flg = PETSC_FALSE; 5714 5715 PetscFunctionBegin; 5716 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5717 PetscValidType(mat, 1); 5718 5719 inassm++; 5720 MatAssemblyEnd_InUse++; 5721 if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */ 5722 PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0)); 5723 PetscTryTypeMethod(mat, assemblyend, type); 5724 PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0)); 5725 } else PetscTryTypeMethod(mat, assemblyend, type); 5726 5727 /* Flush assembly is not a true assembly */ 5728 if (type != MAT_FLUSH_ASSEMBLY) { 5729 if (mat->num_ass) { 5730 if (!mat->symmetry_eternal) { 5731 mat->symmetric = PETSC_BOOL3_UNKNOWN; 5732 mat->hermitian = PETSC_BOOL3_UNKNOWN; 5733 } 5734 if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN; 5735 if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN; 5736 } 5737 mat->num_ass++; 5738 mat->assembled = PETSC_TRUE; 5739 mat->ass_nonzerostate = mat->nonzerostate; 5740 } 5741 5742 mat->insertmode = NOT_SET_VALUES; 5743 MatAssemblyEnd_InUse--; 5744 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5745 if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) { 5746 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 5747 5748 if (mat->checksymmetryonassembly) { 5749 PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg)); 5750 if (flg) { 5751 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5752 } else { 5753 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5754 } 5755 } 5756 if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL)); 5757 } 5758 inassm--; 5759 PetscFunctionReturn(PETSC_SUCCESS); 5760 } 5761 5762 /*@ 5763 MatSetOption - Sets a parameter option for a matrix. Some options 5764 may be specific to certain storage formats. Some options 5765 determine how values will be inserted (or added). Sorted, 5766 row-oriented input will generally assemble the fastest. The default 5767 is row-oriented. 5768 5769 Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption` 5770 5771 Input Parameters: 5772 + mat - the matrix 5773 . option - the option, one of those listed below (and possibly others), 5774 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5775 5776 Options Describing Matrix Structure: 5777 + `MAT_SPD` - symmetric positive definite 5778 . `MAT_SYMMETRIC` - symmetric in terms of both structure and value 5779 . `MAT_HERMITIAN` - transpose is the complex conjugation 5780 . `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure 5781 . `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix 5782 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix 5783 - `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix 5784 5785 These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they 5786 do not need to be computed (usually at a high cost) 5787 5788 Options For Use with `MatSetValues()`: 5789 Insert a logically dense subblock, which can be 5790 . `MAT_ROW_ORIENTED` - row-oriented (default) 5791 5792 These options reflect the data you pass in with `MatSetValues()`; it has 5793 nothing to do with how the data is stored internally in the matrix 5794 data structure. 5795 5796 When (re)assembling a matrix, we can restrict the input for 5797 efficiency/debugging purposes. These options include 5798 + `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow) 5799 . `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated 5800 . `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries 5801 . `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry 5802 . `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly 5803 . `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if 5804 any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves 5805 performance for very large process counts. 5806 - `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset 5807 of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly 5808 functions, instead sending only neighbor messages. 5809 5810 Level: intermediate 5811 5812 Notes: 5813 Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg! 5814 5815 Some options are relevant only for particular matrix types and 5816 are thus ignored by others. Other options are not supported by 5817 certain matrix types and will generate an error message if set. 5818 5819 If using Fortran to compute a matrix, one may need to 5820 use the column-oriented option (or convert to the row-oriented 5821 format). 5822 5823 `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion 5824 that would generate a new entry in the nonzero structure is instead 5825 ignored. Thus, if memory has not already been allocated for this particular 5826 data, then the insertion is ignored. For dense matrices, in which 5827 the entire array is allocated, no entries are ever ignored. 5828 Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction 5829 5830 `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion 5831 that would generate a new entry in the nonzero structure instead produces 5832 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 5833 5834 `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion 5835 that would generate a new entry that has not been preallocated will 5836 instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats 5837 only.) This is a useful flag when debugging matrix memory preallocation. 5838 If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 5839 5840 `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for 5841 other processors should be dropped, rather than stashed. 5842 This is useful if you know that the "owning" processor is also 5843 always generating the correct matrix entries, so that PETSc need 5844 not transfer duplicate entries generated on another processor. 5845 5846 `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the 5847 searches during matrix assembly. When this flag is set, the hash table 5848 is created during the first matrix assembly. This hash table is 5849 used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()` 5850 to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag 5851 should be used with `MAT_USE_HASH_TABLE` flag. This option is currently 5852 supported by `MATMPIBAIJ` format only. 5853 5854 `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries 5855 are kept in the nonzero structure 5856 5857 `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating 5858 a zero location in the matrix 5859 5860 `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types 5861 5862 `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the 5863 zero row routines and thus improves performance for very large process counts. 5864 5865 `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular 5866 part of the matrix (since they should match the upper triangular part). 5867 5868 `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a 5869 single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common 5870 with finite difference schemes with non-periodic boundary conditions. 5871 5872 Developer Note: 5873 `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other 5874 places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRIC` or `MAT_SPD` would need to be changed back 5875 to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had 5876 not changed. 5877 5878 .seealso: `MatOption`, `Mat`, `MatGetOption()` 5879 @*/ 5880 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg) 5881 { 5882 PetscFunctionBegin; 5883 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5884 if (op > 0) { 5885 PetscValidLogicalCollectiveEnum(mat, op, 2); 5886 PetscValidLogicalCollectiveBool(mat, flg, 3); 5887 } 5888 5889 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); 5890 5891 switch (op) { 5892 case MAT_FORCE_DIAGONAL_ENTRIES: 5893 mat->force_diagonals = flg; 5894 PetscFunctionReturn(PETSC_SUCCESS); 5895 case MAT_NO_OFF_PROC_ENTRIES: 5896 mat->nooffprocentries = flg; 5897 PetscFunctionReturn(PETSC_SUCCESS); 5898 case MAT_SUBSET_OFF_PROC_ENTRIES: 5899 mat->assembly_subset = flg; 5900 if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */ 5901 #if !defined(PETSC_HAVE_MPIUNI) 5902 PetscCall(MatStashScatterDestroy_BTS(&mat->stash)); 5903 #endif 5904 mat->stash.first_assembly_done = PETSC_FALSE; 5905 } 5906 PetscFunctionReturn(PETSC_SUCCESS); 5907 case MAT_NO_OFF_PROC_ZERO_ROWS: 5908 mat->nooffproczerorows = flg; 5909 PetscFunctionReturn(PETSC_SUCCESS); 5910 case MAT_SPD: 5911 if (flg) { 5912 mat->spd = PETSC_BOOL3_TRUE; 5913 mat->symmetric = PETSC_BOOL3_TRUE; 5914 mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5915 } else { 5916 mat->spd = PETSC_BOOL3_FALSE; 5917 } 5918 break; 5919 case MAT_SYMMETRIC: 5920 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5921 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5922 #if !defined(PETSC_USE_COMPLEX) 5923 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5924 #endif 5925 break; 5926 case MAT_HERMITIAN: 5927 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5928 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 5929 #if !defined(PETSC_USE_COMPLEX) 5930 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5931 #endif 5932 break; 5933 case MAT_STRUCTURALLY_SYMMETRIC: 5934 mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 5935 break; 5936 case MAT_SYMMETRY_ETERNAL: 5937 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"); 5938 mat->symmetry_eternal = flg; 5939 if (flg) mat->structural_symmetry_eternal = PETSC_TRUE; 5940 break; 5941 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 5942 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"); 5943 mat->structural_symmetry_eternal = flg; 5944 break; 5945 case MAT_SPD_ETERNAL: 5946 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"); 5947 mat->spd_eternal = flg; 5948 if (flg) { 5949 mat->structural_symmetry_eternal = PETSC_TRUE; 5950 mat->symmetry_eternal = PETSC_TRUE; 5951 } 5952 break; 5953 case MAT_STRUCTURE_ONLY: 5954 mat->structure_only = flg; 5955 break; 5956 case MAT_SORTED_FULL: 5957 mat->sortedfull = flg; 5958 break; 5959 default: 5960 break; 5961 } 5962 PetscTryTypeMethod(mat, setoption, op, flg); 5963 PetscFunctionReturn(PETSC_SUCCESS); 5964 } 5965 5966 /*@ 5967 MatGetOption - Gets a parameter option that has been set for a matrix. 5968 5969 Logically Collective 5970 5971 Input Parameters: 5972 + mat - the matrix 5973 - option - the option, this only responds to certain options, check the code for which ones 5974 5975 Output Parameter: 5976 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5977 5978 Level: intermediate 5979 5980 Notes: 5981 Can only be called after `MatSetSizes()` and `MatSetType()` have been set. 5982 5983 Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or 5984 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 5985 5986 .seealso: `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, 5987 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 5988 @*/ 5989 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg) 5990 { 5991 PetscFunctionBegin; 5992 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5993 PetscValidType(mat, 1); 5994 5995 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); 5996 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()"); 5997 5998 switch (op) { 5999 case MAT_NO_OFF_PROC_ENTRIES: 6000 *flg = mat->nooffprocentries; 6001 break; 6002 case MAT_NO_OFF_PROC_ZERO_ROWS: 6003 *flg = mat->nooffproczerorows; 6004 break; 6005 case MAT_SYMMETRIC: 6006 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()"); 6007 break; 6008 case MAT_HERMITIAN: 6009 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()"); 6010 break; 6011 case MAT_STRUCTURALLY_SYMMETRIC: 6012 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()"); 6013 break; 6014 case MAT_SPD: 6015 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()"); 6016 break; 6017 case MAT_SYMMETRY_ETERNAL: 6018 *flg = mat->symmetry_eternal; 6019 break; 6020 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6021 *flg = mat->symmetry_eternal; 6022 break; 6023 default: 6024 break; 6025 } 6026 PetscFunctionReturn(PETSC_SUCCESS); 6027 } 6028 6029 /*@ 6030 MatZeroEntries - Zeros all entries of a matrix. For sparse matrices 6031 this routine retains the old nonzero structure. 6032 6033 Logically Collective 6034 6035 Input Parameters: 6036 . mat - the matrix 6037 6038 Level: intermediate 6039 6040 Note: 6041 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. 6042 See the Performance chapter of the users manual for information on preallocating matrices. 6043 6044 .seealso: `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()` 6045 @*/ 6046 PetscErrorCode MatZeroEntries(Mat mat) 6047 { 6048 PetscFunctionBegin; 6049 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6050 PetscValidType(mat, 1); 6051 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6052 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"); 6053 MatCheckPreallocated(mat, 1); 6054 6055 PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0)); 6056 PetscUseTypeMethod(mat, zeroentries); 6057 PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0)); 6058 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6059 PetscFunctionReturn(PETSC_SUCCESS); 6060 } 6061 6062 /*@ 6063 MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal) 6064 of a set of rows and columns of a matrix. 6065 6066 Collective 6067 6068 Input Parameters: 6069 + mat - the matrix 6070 . numRows - the number of rows/columns to zero 6071 . rows - the global row indices 6072 . diag - value put in the diagonal of the eliminated rows 6073 . x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call 6074 - b - optional vector of the right hand side, that will be adjusted by provided solution entries 6075 6076 Level: intermediate 6077 6078 Notes: 6079 This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6080 6081 For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`. 6082 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 6083 6084 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6085 Krylov method to take advantage of the known solution on the zeroed rows. 6086 6087 For the parallel case, all processes that share the matrix (i.e., 6088 those in the communicator used for matrix creation) MUST call this 6089 routine, regardless of whether any rows being zeroed are owned by 6090 them. 6091 6092 Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix. 6093 6094 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6095 list only rows local to itself). 6096 6097 The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine. 6098 6099 .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6100 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6101 @*/ 6102 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6103 { 6104 PetscFunctionBegin; 6105 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6106 PetscValidType(mat, 1); 6107 if (numRows) PetscValidIntPointer(rows, 3); 6108 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6109 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6110 MatCheckPreallocated(mat, 1); 6111 6112 PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b); 6113 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6114 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6115 PetscFunctionReturn(PETSC_SUCCESS); 6116 } 6117 6118 /*@ 6119 MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal) 6120 of a set of rows and columns of a matrix. 6121 6122 Collective 6123 6124 Input Parameters: 6125 + mat - the matrix 6126 . is - the rows to zero 6127 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6128 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6129 - b - optional vector of right hand side, that will be adjusted by provided solution 6130 6131 Level: intermediate 6132 6133 Note: 6134 See `MatZeroRowsColumns()` for details on how this routine operates. 6135 6136 .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6137 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()` 6138 @*/ 6139 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6140 { 6141 PetscInt numRows; 6142 const PetscInt *rows; 6143 6144 PetscFunctionBegin; 6145 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6146 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6147 PetscValidType(mat, 1); 6148 PetscValidType(is, 2); 6149 PetscCall(ISGetLocalSize(is, &numRows)); 6150 PetscCall(ISGetIndices(is, &rows)); 6151 PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b)); 6152 PetscCall(ISRestoreIndices(is, &rows)); 6153 PetscFunctionReturn(PETSC_SUCCESS); 6154 } 6155 6156 /*@ 6157 MatZeroRows - Zeros all entries (except possibly the main diagonal) 6158 of a set of rows of a matrix. 6159 6160 Collective 6161 6162 Input Parameters: 6163 + mat - the matrix 6164 . numRows - the number of rows to zero 6165 . rows - the global row indices 6166 . diag - value put in the diagonal of the zeroed rows 6167 . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call 6168 - b - optional vector of right hand side, that will be adjusted by provided solution entries 6169 6170 Level: intermediate 6171 6172 Notes: 6173 This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6174 6175 For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`. 6176 6177 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6178 Krylov method to take advantage of the known solution on the zeroed rows. 6179 6180 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) 6181 from the matrix. 6182 6183 Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix 6184 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 6185 formats this does not alter the nonzero structure. 6186 6187 If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure 6188 of the matrix is not changed the values are 6189 merely zeroed. 6190 6191 The user can set a value in the diagonal entry (or for the `MATAIJ` format 6192 formats can optionally remove the main diagonal entry from the 6193 nonzero structure as well, by passing 0.0 as the final argument). 6194 6195 For the parallel case, all processes that share the matrix (i.e., 6196 those in the communicator used for matrix creation) MUST call this 6197 routine, regardless of whether any rows being zeroed are owned by 6198 them. 6199 6200 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6201 list only rows local to itself). 6202 6203 You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it 6204 owns that are to be zeroed. This saves a global synchronization in the implementation. 6205 6206 .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6207 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE` 6208 @*/ 6209 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6210 { 6211 PetscFunctionBegin; 6212 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6213 PetscValidType(mat, 1); 6214 if (numRows) PetscValidIntPointer(rows, 3); 6215 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6216 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6217 MatCheckPreallocated(mat, 1); 6218 6219 PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b); 6220 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6221 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6222 PetscFunctionReturn(PETSC_SUCCESS); 6223 } 6224 6225 /*@ 6226 MatZeroRowsIS - Zeros all entries (except possibly the main diagonal) 6227 of a set of rows of a matrix. 6228 6229 Collective on Mat 6230 6231 Input Parameters: 6232 + mat - the matrix 6233 . is - index set of rows to remove (if `NULL` then no row is removed) 6234 . diag - value put in all diagonals of eliminated rows 6235 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6236 - b - optional vector of right hand side, that will be adjusted by provided solution 6237 6238 Level: intermediate 6239 6240 Note: 6241 See `MatZeroRows()` for details on how this routine operates. 6242 6243 .seealso: `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6244 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6245 @*/ 6246 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6247 { 6248 PetscInt numRows = 0; 6249 const PetscInt *rows = NULL; 6250 6251 PetscFunctionBegin; 6252 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6253 PetscValidType(mat, 1); 6254 if (is) { 6255 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6256 PetscCall(ISGetLocalSize(is, &numRows)); 6257 PetscCall(ISGetIndices(is, &rows)); 6258 } 6259 PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b)); 6260 if (is) PetscCall(ISRestoreIndices(is, &rows)); 6261 PetscFunctionReturn(PETSC_SUCCESS); 6262 } 6263 6264 /*@ 6265 MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal) 6266 of a set of rows of a matrix. These rows must be local to the process. 6267 6268 Collective 6269 6270 Input Parameters: 6271 + mat - the matrix 6272 . numRows - the number of rows to remove 6273 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6274 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6275 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6276 - b - optional vector of right hand side, that will be adjusted by provided solution 6277 6278 Level: intermediate 6279 6280 Notes: 6281 See `MatZeroRows()` for details on how this routine operates. 6282 6283 The grid coordinates are across the entire grid, not just the local portion 6284 6285 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6286 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6287 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6288 `DM_BOUNDARY_PERIODIC` boundary type. 6289 6290 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 6291 a single value per point) you can skip filling those indices. 6292 6293 Fortran Note: 6294 `idxm` and `idxn` should be declared as 6295 $ MatStencil idxm(4,m) 6296 and the values inserted using 6297 .vb 6298 idxm(MatStencil_i,1) = i 6299 idxm(MatStencil_j,1) = j 6300 idxm(MatStencil_k,1) = k 6301 idxm(MatStencil_c,1) = c 6302 etc 6303 .ve 6304 6305 .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6306 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6307 @*/ 6308 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6309 { 6310 PetscInt dim = mat->stencil.dim; 6311 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6312 PetscInt *dims = mat->stencil.dims + 1; 6313 PetscInt *starts = mat->stencil.starts; 6314 PetscInt *dxm = (PetscInt *)rows; 6315 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6316 6317 PetscFunctionBegin; 6318 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6319 PetscValidType(mat, 1); 6320 if (numRows) PetscValidPointer(rows, 3); 6321 6322 PetscCall(PetscMalloc1(numRows, &jdxm)); 6323 for (i = 0; i < numRows; ++i) { 6324 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6325 for (j = 0; j < 3 - sdim; ++j) dxm++; 6326 /* Local index in X dir */ 6327 tmp = *dxm++ - starts[0]; 6328 /* Loop over remaining dimensions */ 6329 for (j = 0; j < dim - 1; ++j) { 6330 /* If nonlocal, set index to be negative */ 6331 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6332 /* Update local index */ 6333 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6334 } 6335 /* Skip component slot if necessary */ 6336 if (mat->stencil.noc) dxm++; 6337 /* Local row number */ 6338 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6339 } 6340 PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b)); 6341 PetscCall(PetscFree(jdxm)); 6342 PetscFunctionReturn(PETSC_SUCCESS); 6343 } 6344 6345 /*@ 6346 MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal) 6347 of a set of rows and columns of a matrix. 6348 6349 Collective 6350 6351 Input Parameters: 6352 + mat - the matrix 6353 . numRows - the number of rows/columns to remove 6354 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6355 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6356 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6357 - b - optional vector of right hand side, that will be adjusted by provided solution 6358 6359 Level: intermediate 6360 6361 Notes: 6362 See `MatZeroRowsColumns()` for details on how this routine operates. 6363 6364 The grid coordinates are across the entire grid, not just the local portion 6365 6366 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6367 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6368 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6369 `DM_BOUNDARY_PERIODIC` boundary type. 6370 6371 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 6372 a single value per point) you can skip filling those indices. 6373 6374 Fortran Note: 6375 `idxm` and `idxn` should be declared as 6376 $ MatStencil idxm(4,m) 6377 and the values inserted using 6378 .vb 6379 idxm(MatStencil_i,1) = i 6380 idxm(MatStencil_j,1) = j 6381 idxm(MatStencil_k,1) = k 6382 idxm(MatStencil_c,1) = c 6383 etc 6384 .ve 6385 6386 .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6387 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()` 6388 @*/ 6389 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6390 { 6391 PetscInt dim = mat->stencil.dim; 6392 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6393 PetscInt *dims = mat->stencil.dims + 1; 6394 PetscInt *starts = mat->stencil.starts; 6395 PetscInt *dxm = (PetscInt *)rows; 6396 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6397 6398 PetscFunctionBegin; 6399 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6400 PetscValidType(mat, 1); 6401 if (numRows) PetscValidPointer(rows, 3); 6402 6403 PetscCall(PetscMalloc1(numRows, &jdxm)); 6404 for (i = 0; i < numRows; ++i) { 6405 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6406 for (j = 0; j < 3 - sdim; ++j) dxm++; 6407 /* Local index in X dir */ 6408 tmp = *dxm++ - starts[0]; 6409 /* Loop over remaining dimensions */ 6410 for (j = 0; j < dim - 1; ++j) { 6411 /* If nonlocal, set index to be negative */ 6412 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT; 6413 /* Update local index */ 6414 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6415 } 6416 /* Skip component slot if necessary */ 6417 if (mat->stencil.noc) dxm++; 6418 /* Local row number */ 6419 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6420 } 6421 PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b)); 6422 PetscCall(PetscFree(jdxm)); 6423 PetscFunctionReturn(PETSC_SUCCESS); 6424 } 6425 6426 /*@C 6427 MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal) 6428 of a set of rows of a matrix; using local numbering of rows. 6429 6430 Collective 6431 6432 Input Parameters: 6433 + mat - the matrix 6434 . numRows - the number of rows to remove 6435 . rows - the local row indices 6436 . diag - value put in all diagonals of eliminated rows 6437 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6438 - b - optional vector of right hand side, that will be adjusted by provided solution 6439 6440 Level: intermediate 6441 6442 Notes: 6443 Before calling `MatZeroRowsLocal()`, the user must first set the 6444 local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`. 6445 6446 See `MatZeroRows()` for details on how this routine operates. 6447 6448 .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`, 6449 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6450 @*/ 6451 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6452 { 6453 PetscFunctionBegin; 6454 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6455 PetscValidType(mat, 1); 6456 if (numRows) PetscValidIntPointer(rows, 3); 6457 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6458 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6459 MatCheckPreallocated(mat, 1); 6460 6461 if (mat->ops->zerorowslocal) { 6462 PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b); 6463 } else { 6464 IS is, newis; 6465 const PetscInt *newRows; 6466 6467 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6468 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6469 PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis)); 6470 PetscCall(ISGetIndices(newis, &newRows)); 6471 PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b); 6472 PetscCall(ISRestoreIndices(newis, &newRows)); 6473 PetscCall(ISDestroy(&newis)); 6474 PetscCall(ISDestroy(&is)); 6475 } 6476 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6477 PetscFunctionReturn(PETSC_SUCCESS); 6478 } 6479 6480 /*@ 6481 MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal) 6482 of a set of rows of a matrix; using local numbering of rows. 6483 6484 Collective 6485 6486 Input Parameters: 6487 + mat - the matrix 6488 . is - index set of rows to remove 6489 . diag - value put in all diagonals of eliminated rows 6490 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6491 - b - optional vector of right hand side, that will be adjusted by provided solution 6492 6493 Level: intermediate 6494 6495 Notes: 6496 Before calling `MatZeroRowsLocalIS()`, the user must first set the 6497 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6498 6499 See `MatZeroRows()` for details on how this routine operates. 6500 6501 .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6502 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6503 @*/ 6504 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6505 { 6506 PetscInt numRows; 6507 const PetscInt *rows; 6508 6509 PetscFunctionBegin; 6510 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6511 PetscValidType(mat, 1); 6512 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6513 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6514 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6515 MatCheckPreallocated(mat, 1); 6516 6517 PetscCall(ISGetLocalSize(is, &numRows)); 6518 PetscCall(ISGetIndices(is, &rows)); 6519 PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b)); 6520 PetscCall(ISRestoreIndices(is, &rows)); 6521 PetscFunctionReturn(PETSC_SUCCESS); 6522 } 6523 6524 /*@ 6525 MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal) 6526 of a set of rows and columns of a matrix; using local numbering of rows. 6527 6528 Collective 6529 6530 Input Parameters: 6531 + mat - the matrix 6532 . numRows - the number of rows to remove 6533 . rows - the global row indices 6534 . diag - value put in all diagonals of eliminated rows 6535 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6536 - b - optional vector of right hand side, that will be adjusted by provided solution 6537 6538 Level: intermediate 6539 6540 Notes: 6541 Before calling `MatZeroRowsColumnsLocal()`, the user must first set the 6542 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6543 6544 See `MatZeroRowsColumns()` for details on how this routine operates. 6545 6546 .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6547 `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6548 @*/ 6549 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6550 { 6551 IS is, newis; 6552 const PetscInt *newRows; 6553 6554 PetscFunctionBegin; 6555 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6556 PetscValidType(mat, 1); 6557 if (numRows) PetscValidIntPointer(rows, 3); 6558 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6559 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6560 MatCheckPreallocated(mat, 1); 6561 6562 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6563 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6564 PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis)); 6565 PetscCall(ISGetIndices(newis, &newRows)); 6566 PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b); 6567 PetscCall(ISRestoreIndices(newis, &newRows)); 6568 PetscCall(ISDestroy(&newis)); 6569 PetscCall(ISDestroy(&is)); 6570 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6571 PetscFunctionReturn(PETSC_SUCCESS); 6572 } 6573 6574 /*@ 6575 MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal) 6576 of a set of rows and columns of a matrix; using local numbering of rows. 6577 6578 Collective on Mat 6579 6580 Input Parameters: 6581 + mat - the matrix 6582 . is - index set of rows to remove 6583 . diag - value put in all diagonals of eliminated rows 6584 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6585 - b - optional vector of right hand side, that will be adjusted by provided solution 6586 6587 Level: intermediate 6588 6589 Notes: 6590 Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the 6591 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6592 6593 See `MatZeroRowsColumns()` for details on how this routine operates. 6594 6595 .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6596 `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6597 @*/ 6598 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6599 { 6600 PetscInt numRows; 6601 const PetscInt *rows; 6602 6603 PetscFunctionBegin; 6604 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6605 PetscValidType(mat, 1); 6606 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6607 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6608 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6609 MatCheckPreallocated(mat, 1); 6610 6611 PetscCall(ISGetLocalSize(is, &numRows)); 6612 PetscCall(ISGetIndices(is, &rows)); 6613 PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b)); 6614 PetscCall(ISRestoreIndices(is, &rows)); 6615 PetscFunctionReturn(PETSC_SUCCESS); 6616 } 6617 6618 /*@C 6619 MatGetSize - Returns the numbers of rows and columns in a matrix. 6620 6621 Not Collective 6622 6623 Input Parameter: 6624 . mat - the matrix 6625 6626 Level: beginner 6627 6628 Output Parameters: 6629 + m - the number of global rows 6630 - n - the number of global columns 6631 6632 Note: 6633 Both output parameters can be `NULL` on input. 6634 6635 .seealso: `Mat`, `MatSetSizes()`, `MatGetLocalSize()` 6636 @*/ 6637 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n) 6638 { 6639 PetscFunctionBegin; 6640 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6641 if (m) *m = mat->rmap->N; 6642 if (n) *n = mat->cmap->N; 6643 PetscFunctionReturn(PETSC_SUCCESS); 6644 } 6645 6646 /*@C 6647 MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns 6648 of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`. 6649 6650 Not Collective 6651 6652 Input Parameter: 6653 . mat - the matrix 6654 6655 Output Parameters: 6656 + m - the number of local rows, use `NULL` to not obtain this value 6657 - n - the number of local columns, use `NULL` to not obtain this value 6658 6659 Level: beginner 6660 6661 .seealso: `Mat`, `MatSetSizes()`, `MatGetSize()` 6662 @*/ 6663 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n) 6664 { 6665 PetscFunctionBegin; 6666 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6667 if (m) PetscValidIntPointer(m, 2); 6668 if (n) PetscValidIntPointer(n, 3); 6669 if (m) *m = mat->rmap->n; 6670 if (n) *n = mat->cmap->n; 6671 PetscFunctionReturn(PETSC_SUCCESS); 6672 } 6673 6674 /*@C 6675 MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by 6676 this processor. (The columns of the "diagonal block" for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts. 6677 6678 Not Collective, unless matrix has not been allocated, then collective 6679 6680 Input Parameter: 6681 . mat - the matrix 6682 6683 Output Parameters: 6684 + m - the global index of the first local column, use `NULL` to not obtain this value 6685 - n - one more than the global index of the last local column, use `NULL` to not obtain this value 6686 6687 Level: developer 6688 6689 .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout` 6690 @*/ 6691 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n) 6692 { 6693 PetscFunctionBegin; 6694 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6695 PetscValidType(mat, 1); 6696 if (m) PetscValidIntPointer(m, 2); 6697 if (n) PetscValidIntPointer(n, 3); 6698 MatCheckPreallocated(mat, 1); 6699 if (m) *m = mat->cmap->rstart; 6700 if (n) *n = mat->cmap->rend; 6701 PetscFunctionReturn(PETSC_SUCCESS); 6702 } 6703 6704 /*@C 6705 MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6706 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 6707 vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts 6708 6709 Not Collective 6710 6711 Input Parameter: 6712 . mat - the matrix 6713 6714 Output Parameters: 6715 + m - the global index of the first local row, use `NULL` to not obtain this value 6716 - n - one more than the global index of the last local row, use `NULL` to not obtain this value 6717 6718 Level: beginner 6719 6720 Note: 6721 This function requires that the matrix be preallocated. If you have not preallocated, consider using 6722 `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N) 6723 and then `MPI_Scan()` to calculate prefix sums of the local sizes. 6724 6725 .seealso: `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, 6726 `PetscLayout` 6727 @*/ 6728 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n) 6729 { 6730 PetscFunctionBegin; 6731 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6732 PetscValidType(mat, 1); 6733 if (m) PetscValidIntPointer(m, 2); 6734 if (n) PetscValidIntPointer(n, 3); 6735 MatCheckPreallocated(mat, 1); 6736 if (m) *m = mat->rmap->rstart; 6737 if (n) *n = mat->rmap->rend; 6738 PetscFunctionReturn(PETSC_SUCCESS); 6739 } 6740 6741 /*@C 6742 MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6743 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 6744 vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts 6745 6746 Not Collective, unless matrix has not been allocated, then collective 6747 6748 Input Parameters: 6749 . mat - the matrix 6750 6751 Output Parameters: 6752 . ranges - start of each processors portion plus one more than the total length at the end 6753 6754 Level: beginner 6755 6756 .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout` 6757 @*/ 6758 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges) 6759 { 6760 PetscFunctionBegin; 6761 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6762 PetscValidType(mat, 1); 6763 MatCheckPreallocated(mat, 1); 6764 PetscCall(PetscLayoutGetRanges(mat->rmap, ranges)); 6765 PetscFunctionReturn(PETSC_SUCCESS); 6766 } 6767 6768 /*@C 6769 MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by 6770 each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts. 6771 6772 Not Collective, unless matrix has not been allocated, then collective on Mat 6773 6774 Input Parameters: 6775 . mat - the matrix 6776 6777 Output Parameters: 6778 . ranges - start of each processors portion plus one more then the total length at the end 6779 6780 Level: beginner 6781 6782 .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()` 6783 @*/ 6784 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges) 6785 { 6786 PetscFunctionBegin; 6787 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6788 PetscValidType(mat, 1); 6789 MatCheckPreallocated(mat, 1); 6790 PetscCall(PetscLayoutGetRanges(mat->cmap, ranges)); 6791 PetscFunctionReturn(PETSC_SUCCESS); 6792 } 6793 6794 /*@C 6795 MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this 6796 corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership 6797 is more complicated. See :any:`<sec_matlayout>` for details on matrix layouts. 6798 6799 Not Collective 6800 6801 Input Parameter: 6802 . A - matrix 6803 6804 Output Parameters: 6805 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value 6806 - cols - columns in which this process owns elements, use `NULL` to not obtain this value 6807 6808 Level: intermediate 6809 6810 .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK`` 6811 @*/ 6812 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols) 6813 { 6814 PetscErrorCode (*f)(Mat, IS *, IS *); 6815 6816 PetscFunctionBegin; 6817 MatCheckPreallocated(A, 1); 6818 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f)); 6819 if (f) { 6820 PetscCall((*f)(A, rows, cols)); 6821 } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */ 6822 if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows)); 6823 if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols)); 6824 } 6825 PetscFunctionReturn(PETSC_SUCCESS); 6826 } 6827 6828 /*@C 6829 MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()` 6830 Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()` 6831 to complete the factorization. 6832 6833 Collective on fact 6834 6835 Input Parameters: 6836 + fact - the factorized matrix obtained with `MatGetFactor()` 6837 . mat - the matrix 6838 . row - row permutation 6839 . column - column permutation 6840 - info - structure containing 6841 .vb 6842 levels - number of levels of fill. 6843 expected fill - as ratio of original fill. 6844 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 6845 missing diagonal entries) 6846 .ve 6847 6848 Output Parameters: 6849 . fact - new matrix that has been symbolically factored 6850 6851 Level: developer 6852 6853 Notes: 6854 See [Matrix Factorization](sec_matfactor) for additional information. 6855 6856 Most users should employ the `KSP` interface for linear solvers 6857 instead of working directly with matrix algebra routines such as this. 6858 See, e.g., `KSPCreate()`. 6859 6860 Uses the definition of level of fill as in Y. Saad, 2003 6861 6862 Developer Note: 6863 The Fortran interface is not autogenerated as the 6864 interface definition cannot be generated correctly [due to `MatFactorInfo`] 6865 6866 References: 6867 . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003 6868 6869 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 6870 `MatGetOrdering()`, `MatFactorInfo` 6871 @*/ 6872 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 6873 { 6874 PetscFunctionBegin; 6875 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 6876 PetscValidType(mat, 2); 6877 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 6878 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 6879 PetscValidPointer(info, 5); 6880 PetscValidPointer(fact, 1); 6881 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels); 6882 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 6883 if (!fact->ops->ilufactorsymbolic) { 6884 MatSolverType stype; 6885 PetscCall(MatFactorGetSolverType(fact, &stype)); 6886 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ILU using solver type %s", ((PetscObject)mat)->type_name, stype); 6887 } 6888 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6889 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6890 MatCheckPreallocated(mat, 2); 6891 6892 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0)); 6893 PetscCall((fact->ops->ilufactorsymbolic)(fact, mat, row, col, info)); 6894 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0)); 6895 PetscFunctionReturn(PETSC_SUCCESS); 6896 } 6897 6898 /*@C 6899 MatICCFactorSymbolic - Performs symbolic incomplete 6900 Cholesky factorization for a symmetric matrix. Use 6901 `MatCholeskyFactorNumeric()` to complete the factorization. 6902 6903 Collective on fact 6904 6905 Input Parameters: 6906 + fact - the factorized matrix obtained with `MatGetFactor()` 6907 . mat - the matrix to be factored 6908 . perm - row and column permutation 6909 - info - structure containing 6910 .vb 6911 levels - number of levels of fill. 6912 expected fill - as ratio of original fill. 6913 .ve 6914 6915 Output Parameter: 6916 . fact - the factored matrix 6917 6918 Level: developer 6919 6920 Notes: 6921 Most users should employ the `KSP` interface for linear solvers 6922 instead of working directly with matrix algebra routines such as this. 6923 See, e.g., `KSPCreate()`. 6924 6925 This uses the definition of level of fill as in Y. Saad, 2003 6926 6927 Developer Note: 6928 The Fortran interface is not autogenerated as the 6929 interface definition cannot be generated correctly [due to `MatFactorInfo`] 6930 6931 References: 6932 . * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003 6933 6934 .seealso: `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 6935 @*/ 6936 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 6937 { 6938 PetscFunctionBegin; 6939 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 6940 PetscValidType(mat, 2); 6941 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 6942 PetscValidPointer(info, 4); 6943 PetscValidPointer(fact, 1); 6944 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6945 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels); 6946 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 6947 if (!(fact)->ops->iccfactorsymbolic) { 6948 MatSolverType stype; 6949 PetscCall(MatFactorGetSolverType(fact, &stype)); 6950 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ICC using solver type %s", ((PetscObject)mat)->type_name, stype); 6951 } 6952 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6953 MatCheckPreallocated(mat, 2); 6954 6955 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 6956 PetscCall((fact->ops->iccfactorsymbolic)(fact, mat, perm, info)); 6957 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 6958 PetscFunctionReturn(PETSC_SUCCESS); 6959 } 6960 6961 /*@C 6962 MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat 6963 points to an array of valid matrices, they may be reused to store the new 6964 submatrices. 6965 6966 Collective 6967 6968 Input Parameters: 6969 + mat - the matrix 6970 . n - the number of submatrixes to be extracted (on this processor, may be zero) 6971 . irow, icol - index sets of rows and columns to extract 6972 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 6973 6974 Output Parameter: 6975 . submat - the array of submatrices 6976 6977 Level: advanced 6978 6979 Notes: 6980 `MatCreateSubMatrices()` can extract ONLY sequential submatrices 6981 (from both sequential and parallel matrices). Use `MatCreateSubMatrix()` 6982 to extract a parallel submatrix. 6983 6984 Some matrix types place restrictions on the row and column 6985 indices, such as that they be sorted or that they be equal to each other. 6986 6987 The index sets may not have duplicate entries. 6988 6989 When extracting submatrices from a parallel matrix, each processor can 6990 form a different submatrix by setting the rows and columns of its 6991 individual index sets according to the local submatrix desired. 6992 6993 When finished using the submatrices, the user should destroy 6994 them with `MatDestroySubMatrices()`. 6995 6996 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 6997 original matrix has not changed from that last call to `MatCreateSubMatrices()`. 6998 6999 This routine creates the matrices in submat; you should NOT create them before 7000 calling it. It also allocates the array of matrix pointers submat. 7001 7002 For `MATBAIJ` matrices the index sets must respect the block structure, that is if they 7003 request one row/column in a block, they must request all rows/columns that are in 7004 that block. For example, if the block size is 2 you cannot request just row 0 and 7005 column 0. 7006 7007 Fortran Note: 7008 The Fortran interface is slightly different from that given below; it 7009 requires one to pass in as `submat` a `Mat` (integer) array of size at least n+1. 7010 7011 .seealso: `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7012 @*/ 7013 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7014 { 7015 PetscInt i; 7016 PetscBool eq; 7017 7018 PetscFunctionBegin; 7019 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7020 PetscValidType(mat, 1); 7021 if (n) { 7022 PetscValidPointer(irow, 3); 7023 for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3); 7024 PetscValidPointer(icol, 4); 7025 for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4); 7026 } 7027 PetscValidPointer(submat, 6); 7028 if (n && scall == MAT_REUSE_MATRIX) { 7029 PetscValidPointer(*submat, 6); 7030 for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6); 7031 } 7032 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7033 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7034 MatCheckPreallocated(mat, 1); 7035 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7036 PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat); 7037 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7038 for (i = 0; i < n; i++) { 7039 (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */ 7040 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7041 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7042 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 7043 if (mat->boundtocpu && mat->bindingpropagates) { 7044 PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE)); 7045 PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE)); 7046 } 7047 #endif 7048 } 7049 PetscFunctionReturn(PETSC_SUCCESS); 7050 } 7051 7052 /*@C 7053 MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms). 7054 7055 Collective 7056 7057 Input Parameters: 7058 + mat - the matrix 7059 . n - the number of submatrixes to be extracted 7060 . irow, icol - index sets of rows and columns to extract 7061 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7062 7063 Output Parameter: 7064 . submat - the array of submatrices 7065 7066 Level: advanced 7067 7068 Note: 7069 This is used by `PCGASM` 7070 7071 .seealso: `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7072 @*/ 7073 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7074 { 7075 PetscInt i; 7076 PetscBool eq; 7077 7078 PetscFunctionBegin; 7079 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7080 PetscValidType(mat, 1); 7081 if (n) { 7082 PetscValidPointer(irow, 3); 7083 PetscValidHeaderSpecific(*irow, IS_CLASSID, 3); 7084 PetscValidPointer(icol, 4); 7085 PetscValidHeaderSpecific(*icol, IS_CLASSID, 4); 7086 } 7087 PetscValidPointer(submat, 6); 7088 if (n && scall == MAT_REUSE_MATRIX) { 7089 PetscValidPointer(*submat, 6); 7090 PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6); 7091 } 7092 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7093 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7094 MatCheckPreallocated(mat, 1); 7095 7096 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7097 PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat); 7098 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7099 for (i = 0; i < n; i++) { 7100 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7101 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7102 } 7103 PetscFunctionReturn(PETSC_SUCCESS); 7104 } 7105 7106 /*@C 7107 MatDestroyMatrices - Destroys an array of matrices. 7108 7109 Collective 7110 7111 Input Parameters: 7112 + n - the number of local matrices 7113 - mat - the matrices (this is a pointer to the array of matrices) 7114 7115 Level: advanced 7116 7117 Note: 7118 Frees not only the matrices, but also the array that contains the matrices 7119 7120 Fortran Note: 7121 This does not free the array. 7122 7123 .seealso: `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()` 7124 @*/ 7125 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[]) 7126 { 7127 PetscInt i; 7128 7129 PetscFunctionBegin; 7130 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7131 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7132 PetscValidPointer(mat, 2); 7133 7134 for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i])); 7135 7136 /* memory is allocated even if n = 0 */ 7137 PetscCall(PetscFree(*mat)); 7138 PetscFunctionReturn(PETSC_SUCCESS); 7139 } 7140 7141 /*@C 7142 MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`. 7143 7144 Collective 7145 7146 Input Parameters: 7147 + n - the number of local matrices 7148 - mat - the matrices (this is a pointer to the array of matrices, just to match the calling 7149 sequence of `MatCreateSubMatrices()`) 7150 7151 Level: advanced 7152 7153 Note: 7154 Frees not only the matrices, but also the array that contains the matrices 7155 7156 Fortran Note: 7157 This does not free the array. 7158 7159 .seealso: `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7160 @*/ 7161 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[]) 7162 { 7163 Mat mat0; 7164 7165 PetscFunctionBegin; 7166 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7167 /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */ 7168 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7169 PetscValidPointer(mat, 2); 7170 7171 mat0 = (*mat)[0]; 7172 if (mat0 && mat0->ops->destroysubmatrices) { 7173 PetscCall((mat0->ops->destroysubmatrices)(n, mat)); 7174 } else { 7175 PetscCall(MatDestroyMatrices(n, mat)); 7176 } 7177 PetscFunctionReturn(PETSC_SUCCESS); 7178 } 7179 7180 /*@C 7181 MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process 7182 7183 Collective 7184 7185 Input Parameters: 7186 . mat - the matrix 7187 7188 Output Parameter: 7189 . matstruct - the sequential matrix with the nonzero structure of mat 7190 7191 Level: developer 7192 7193 .seealso: `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7194 @*/ 7195 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct) 7196 { 7197 PetscFunctionBegin; 7198 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7199 PetscValidPointer(matstruct, 2); 7200 7201 PetscValidType(mat, 1); 7202 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7203 MatCheckPreallocated(mat, 1); 7204 7205 PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7206 PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct); 7207 PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7208 PetscFunctionReturn(PETSC_SUCCESS); 7209 } 7210 7211 /*@C 7212 MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`. 7213 7214 Collective 7215 7216 Input Parameters: 7217 . mat - the matrix (this is a pointer to the array of matrices, just to match the calling 7218 sequence of `MatGetSequentialNonzeroStructure()`) 7219 7220 Level: advanced 7221 7222 Note: 7223 Frees not only the matrices, but also the array that contains the matrices 7224 7225 .seealso: `Mat`, `MatGetSeqNonzeroStructure()` 7226 @*/ 7227 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat) 7228 { 7229 PetscFunctionBegin; 7230 PetscValidPointer(mat, 1); 7231 PetscCall(MatDestroy(mat)); 7232 PetscFunctionReturn(PETSC_SUCCESS); 7233 } 7234 7235 /*@ 7236 MatIncreaseOverlap - Given a set of submatrices indicated by index sets, 7237 replaces the index sets by larger ones that represent submatrices with 7238 additional overlap. 7239 7240 Collective 7241 7242 Input Parameters: 7243 + mat - the matrix 7244 . n - the number of index sets 7245 . is - the array of index sets (these index sets will changed during the call) 7246 - ov - the additional overlap requested 7247 7248 Options Database Key: 7249 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7250 7251 Level: developer 7252 7253 Note: 7254 The computed overlap preserves the matrix block sizes when the blocks are square. 7255 That is: if a matrix nonzero for a given block would increase the overlap all columns associated with 7256 that block are included in the overlap regardless of whether each specific column would increase the overlap. 7257 7258 .seealso: `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()` 7259 @*/ 7260 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov) 7261 { 7262 PetscInt i, bs, cbs; 7263 7264 PetscFunctionBegin; 7265 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7266 PetscValidType(mat, 1); 7267 PetscValidLogicalCollectiveInt(mat, n, 2); 7268 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7269 if (n) { 7270 PetscValidPointer(is, 3); 7271 for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3); 7272 } 7273 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7274 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7275 MatCheckPreallocated(mat, 1); 7276 7277 if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS); 7278 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7279 PetscUseTypeMethod(mat, increaseoverlap, n, is, ov); 7280 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7281 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 7282 if (bs == cbs) { 7283 for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs)); 7284 } 7285 PetscFunctionReturn(PETSC_SUCCESS); 7286 } 7287 7288 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt); 7289 7290 /*@ 7291 MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across 7292 a sub communicator, replaces the index sets by larger ones that represent submatrices with 7293 additional overlap. 7294 7295 Collective 7296 7297 Input Parameters: 7298 + mat - the matrix 7299 . n - the number of index sets 7300 . is - the array of index sets (these index sets will changed during the call) 7301 - ov - the additional overlap requested 7302 7303 ` Options Database Key: 7304 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7305 7306 Level: developer 7307 7308 .seealso: `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()` 7309 @*/ 7310 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov) 7311 { 7312 PetscInt i; 7313 7314 PetscFunctionBegin; 7315 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7316 PetscValidType(mat, 1); 7317 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7318 if (n) { 7319 PetscValidPointer(is, 3); 7320 PetscValidHeaderSpecific(*is, IS_CLASSID, 3); 7321 } 7322 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7323 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7324 MatCheckPreallocated(mat, 1); 7325 if (!ov) PetscFunctionReturn(PETSC_SUCCESS); 7326 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7327 for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov)); 7328 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7329 PetscFunctionReturn(PETSC_SUCCESS); 7330 } 7331 7332 /*@ 7333 MatGetBlockSize - Returns the matrix block size. 7334 7335 Not Collective 7336 7337 Input Parameter: 7338 . mat - the matrix 7339 7340 Output Parameter: 7341 . bs - block size 7342 7343 Level: intermediate 7344 7345 Notes: 7346 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7347 7348 If the block size has not been set yet this routine returns 1. 7349 7350 .seealso: `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()` 7351 @*/ 7352 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs) 7353 { 7354 PetscFunctionBegin; 7355 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7356 PetscValidIntPointer(bs, 2); 7357 *bs = PetscAbs(mat->rmap->bs); 7358 PetscFunctionReturn(PETSC_SUCCESS); 7359 } 7360 7361 /*@ 7362 MatGetBlockSizes - Returns the matrix block row and column sizes. 7363 7364 Not Collective 7365 7366 Input Parameter: 7367 . mat - the matrix 7368 7369 Output Parameters: 7370 + rbs - row block size 7371 - cbs - column block size 7372 7373 Level: intermediate 7374 7375 Notes: 7376 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7377 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7378 7379 If a block size has not been set yet this routine returns 1. 7380 7381 .seealso: `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()` 7382 @*/ 7383 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs) 7384 { 7385 PetscFunctionBegin; 7386 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7387 if (rbs) PetscValidIntPointer(rbs, 2); 7388 if (cbs) PetscValidIntPointer(cbs, 3); 7389 if (rbs) *rbs = PetscAbs(mat->rmap->bs); 7390 if (cbs) *cbs = PetscAbs(mat->cmap->bs); 7391 PetscFunctionReturn(PETSC_SUCCESS); 7392 } 7393 7394 /*@ 7395 MatSetBlockSize - Sets the matrix block size. 7396 7397 Logically Collective 7398 7399 Input Parameters: 7400 + mat - the matrix 7401 - bs - block size 7402 7403 Level: intermediate 7404 7405 Notes: 7406 Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix. 7407 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7408 7409 For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size 7410 is compatible with the matrix local sizes. 7411 7412 .seealso: `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()` 7413 @*/ 7414 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs) 7415 { 7416 PetscFunctionBegin; 7417 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7418 PetscValidLogicalCollectiveInt(mat, bs, 2); 7419 PetscCall(MatSetBlockSizes(mat, bs, bs)); 7420 PetscFunctionReturn(PETSC_SUCCESS); 7421 } 7422 7423 typedef struct { 7424 PetscInt n; 7425 IS *is; 7426 Mat *mat; 7427 PetscObjectState nonzerostate; 7428 Mat C; 7429 } EnvelopeData; 7430 7431 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata) 7432 { 7433 for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i])); 7434 PetscCall(PetscFree(edata->is)); 7435 PetscCall(PetscFree(edata)); 7436 return PETSC_SUCCESS; 7437 } 7438 7439 /* 7440 MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores 7441 the sizes of these blocks in the matrix. An individual block may lie over several processes. 7442 7443 Collective 7444 7445 Input Parameter: 7446 . mat - the matrix 7447 7448 Notes: 7449 There can be zeros within the blocks 7450 7451 The blocks can overlap between processes, including laying on more than two processes 7452 7453 .seealso: `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()` 7454 */ 7455 static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat) 7456 { 7457 PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend; 7458 PetscInt *diag, *odiag, sc; 7459 VecScatter scatter; 7460 PetscScalar *seqv; 7461 const PetscScalar *parv; 7462 const PetscInt *ia, *ja; 7463 PetscBool set, flag, done; 7464 Mat AA = mat, A; 7465 MPI_Comm comm; 7466 PetscMPIInt rank, size, tag; 7467 MPI_Status status; 7468 PetscContainer container; 7469 EnvelopeData *edata; 7470 Vec seq, par; 7471 IS isglobal; 7472 7473 PetscFunctionBegin; 7474 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7475 PetscCall(MatIsSymmetricKnown(mat, &set, &flag)); 7476 if (!set || !flag) { 7477 /* TOO: only needs nonzero structure of transpose */ 7478 PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA)); 7479 PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN)); 7480 } 7481 PetscCall(MatAIJGetLocalMat(AA, &A)); 7482 PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7483 PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix"); 7484 7485 PetscCall(MatGetLocalSize(mat, &n, NULL)); 7486 PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag)); 7487 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 7488 PetscCallMPI(MPI_Comm_size(comm, &size)); 7489 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7490 7491 PetscCall(PetscMalloc2(n, &sizes, n, &starts)); 7492 7493 if (rank > 0) { 7494 PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7495 PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7496 } 7497 PetscCall(MatGetOwnershipRange(mat, &rstart, NULL)); 7498 for (i = 0; i < n; i++) { 7499 env = PetscMax(env, ja[ia[i + 1] - 1]); 7500 II = rstart + i; 7501 if (env == II) { 7502 starts[lblocks] = tbs; 7503 sizes[lblocks++] = 1 + II - tbs; 7504 tbs = 1 + II; 7505 } 7506 } 7507 if (rank < size - 1) { 7508 PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm)); 7509 PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm)); 7510 } 7511 7512 PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7513 if (!set || !flag) PetscCall(MatDestroy(&AA)); 7514 PetscCall(MatDestroy(&A)); 7515 7516 PetscCall(PetscNew(&edata)); 7517 PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate)); 7518 edata->n = lblocks; 7519 /* create IS needed for extracting blocks from the original matrix */ 7520 PetscCall(PetscMalloc1(lblocks, &edata->is)); 7521 for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i])); 7522 7523 /* Create the resulting inverse matrix structure with preallocation information */ 7524 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C)); 7525 PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 7526 PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat)); 7527 PetscCall(MatSetType(edata->C, MATAIJ)); 7528 7529 /* Communicate the start and end of each row, from each block to the correct rank */ 7530 /* TODO: Use PetscSF instead of VecScatter */ 7531 for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i]; 7532 PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq)); 7533 PetscCall(VecGetArrayWrite(seq, &seqv)); 7534 for (PetscInt i = 0; i < lblocks; i++) { 7535 for (PetscInt j = 0; j < sizes[i]; j++) { 7536 seqv[cnt] = starts[i]; 7537 seqv[cnt + 1] = starts[i] + sizes[i]; 7538 cnt += 2; 7539 } 7540 } 7541 PetscCall(VecRestoreArrayWrite(seq, &seqv)); 7542 PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 7543 sc -= cnt; 7544 PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par)); 7545 PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal)); 7546 PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter)); 7547 PetscCall(ISDestroy(&isglobal)); 7548 PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7549 PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7550 PetscCall(VecScatterDestroy(&scatter)); 7551 PetscCall(VecDestroy(&seq)); 7552 PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend)); 7553 PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag)); 7554 PetscCall(VecGetArrayRead(par, &parv)); 7555 cnt = 0; 7556 PetscCall(MatGetSize(mat, NULL, &n)); 7557 for (PetscInt i = 0; i < mat->rmap->n; i++) { 7558 PetscInt start, end, d = 0, od = 0; 7559 7560 start = (PetscInt)PetscRealPart(parv[cnt]); 7561 end = (PetscInt)PetscRealPart(parv[cnt + 1]); 7562 cnt += 2; 7563 7564 if (start < cstart) { 7565 od += cstart - start + n - cend; 7566 d += cend - cstart; 7567 } else if (start < cend) { 7568 od += n - cend; 7569 d += cend - start; 7570 } else od += n - start; 7571 if (end <= cstart) { 7572 od -= cstart - end + n - cend; 7573 d -= cend - cstart; 7574 } else if (end < cend) { 7575 od -= n - cend; 7576 d -= cend - end; 7577 } else od -= n - end; 7578 7579 odiag[i] = od; 7580 diag[i] = d; 7581 } 7582 PetscCall(VecRestoreArrayRead(par, &parv)); 7583 PetscCall(VecDestroy(&par)); 7584 PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL)); 7585 PetscCall(PetscFree2(diag, odiag)); 7586 PetscCall(PetscFree2(sizes, starts)); 7587 7588 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container)); 7589 PetscCall(PetscContainerSetPointer(container, edata)); 7590 PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy)); 7591 PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container)); 7592 PetscCall(PetscObjectDereference((PetscObject)container)); 7593 PetscFunctionReturn(PETSC_SUCCESS); 7594 } 7595 7596 /*@ 7597 MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A 7598 7599 Collective 7600 7601 Input Parameters: 7602 . A - the matrix 7603 7604 Output Parameters: 7605 . C - matrix with inverted block diagonal of A. This matrix should be created and may have its type set. 7606 7607 Level: advanced 7608 7609 Note: 7610 For efficiency the matrix A should have all the nonzero entries clustered in smallish blocks along the diagonal. 7611 7612 .seealso: `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()` 7613 @*/ 7614 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C) 7615 { 7616 PetscContainer container; 7617 EnvelopeData *edata; 7618 PetscObjectState nonzerostate; 7619 7620 PetscFunctionBegin; 7621 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7622 if (!container) { 7623 PetscCall(MatComputeVariableBlockEnvelope(A)); 7624 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7625 } 7626 PetscCall(PetscContainerGetPointer(container, (void **)&edata)); 7627 PetscCall(MatGetNonzeroState(A, &nonzerostate)); 7628 PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure"); 7629 PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output"); 7630 7631 PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat)); 7632 *C = edata->C; 7633 7634 for (PetscInt i = 0; i < edata->n; i++) { 7635 Mat D; 7636 PetscScalar *dvalues; 7637 7638 PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D)); 7639 PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE)); 7640 PetscCall(MatSeqDenseInvert(D)); 7641 PetscCall(MatDenseGetArray(D, &dvalues)); 7642 PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES)); 7643 PetscCall(MatDestroy(&D)); 7644 } 7645 PetscCall(MatDestroySubMatrices(edata->n, &edata->mat)); 7646 PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY)); 7647 PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY)); 7648 PetscFunctionReturn(PETSC_SUCCESS); 7649 } 7650 7651 /*@ 7652 MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size 7653 7654 Logically Collective 7655 7656 Input Parameters: 7657 + mat - the matrix 7658 . nblocks - the number of blocks on this process, each block can only exist on a single process 7659 - bsizes - the block sizes 7660 7661 Level: intermediate 7662 7663 Notes: 7664 Currently used by `PCVPBJACOBI` for `MATAIJ` matrices 7665 7666 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. 7667 7668 .seealso: `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, 7669 `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI` 7670 @*/ 7671 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes) 7672 { 7673 PetscInt i, ncnt = 0, nlocal; 7674 7675 PetscFunctionBegin; 7676 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7677 PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero"); 7678 PetscCall(MatGetLocalSize(mat, &nlocal, NULL)); 7679 for (i = 0; i < nblocks; i++) ncnt += bsizes[i]; 7680 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); 7681 PetscCall(PetscFree(mat->bsizes)); 7682 mat->nblocks = nblocks; 7683 PetscCall(PetscMalloc1(nblocks, &mat->bsizes)); 7684 PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks)); 7685 PetscFunctionReturn(PETSC_SUCCESS); 7686 } 7687 7688 /*@C 7689 MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size 7690 7691 Logically Collective; No Fortran Support 7692 7693 Input Parameter: 7694 . mat - the matrix 7695 7696 Output Parameters: 7697 + nblocks - the number of blocks on this process 7698 - bsizes - the block sizes 7699 7700 Level: intermediate 7701 7702 .seealso: `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()` 7703 @*/ 7704 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes) 7705 { 7706 PetscFunctionBegin; 7707 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7708 *nblocks = mat->nblocks; 7709 *bsizes = mat->bsizes; 7710 PetscFunctionReturn(PETSC_SUCCESS); 7711 } 7712 7713 /*@ 7714 MatSetBlockSizes - Sets the matrix block row and column sizes. 7715 7716 Logically Collective 7717 7718 Input Parameters: 7719 + mat - the matrix 7720 . rbs - row block size 7721 - cbs - column block size 7722 7723 Level: intermediate 7724 7725 Notes: 7726 Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix. 7727 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7728 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7729 7730 For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes 7731 are compatible with the matrix local sizes. 7732 7733 The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`. 7734 7735 .seealso: `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()` 7736 @*/ 7737 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs) 7738 { 7739 PetscFunctionBegin; 7740 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7741 PetscValidLogicalCollectiveInt(mat, rbs, 2); 7742 PetscValidLogicalCollectiveInt(mat, cbs, 3); 7743 PetscTryTypeMethod(mat, setblocksizes, rbs, cbs); 7744 if (mat->rmap->refcnt) { 7745 ISLocalToGlobalMapping l2g = NULL; 7746 PetscLayout nmap = NULL; 7747 7748 PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap)); 7749 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g)); 7750 PetscCall(PetscLayoutDestroy(&mat->rmap)); 7751 mat->rmap = nmap; 7752 mat->rmap->mapping = l2g; 7753 } 7754 if (mat->cmap->refcnt) { 7755 ISLocalToGlobalMapping l2g = NULL; 7756 PetscLayout nmap = NULL; 7757 7758 PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap)); 7759 if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g)); 7760 PetscCall(PetscLayoutDestroy(&mat->cmap)); 7761 mat->cmap = nmap; 7762 mat->cmap->mapping = l2g; 7763 } 7764 PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs)); 7765 PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs)); 7766 PetscFunctionReturn(PETSC_SUCCESS); 7767 } 7768 7769 /*@ 7770 MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices 7771 7772 Logically Collective 7773 7774 Input Parameters: 7775 + mat - the matrix 7776 . fromRow - matrix from which to copy row block size 7777 - fromCol - matrix from which to copy column block size (can be same as fromRow) 7778 7779 Level: developer 7780 7781 .seealso: `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()` 7782 @*/ 7783 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol) 7784 { 7785 PetscFunctionBegin; 7786 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7787 PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2); 7788 PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3); 7789 if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs)); 7790 if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs)); 7791 PetscFunctionReturn(PETSC_SUCCESS); 7792 } 7793 7794 /*@ 7795 MatResidual - Default routine to calculate the residual r = b - Ax 7796 7797 Collective 7798 7799 Input Parameters: 7800 + mat - the matrix 7801 . b - the right-hand-side 7802 - x - the approximate solution 7803 7804 Output Parameter: 7805 . r - location to store the residual 7806 7807 Level: developer 7808 7809 .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()` 7810 @*/ 7811 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r) 7812 { 7813 PetscFunctionBegin; 7814 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7815 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 7816 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 7817 PetscValidHeaderSpecific(r, VEC_CLASSID, 4); 7818 PetscValidType(mat, 1); 7819 MatCheckPreallocated(mat, 1); 7820 PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0)); 7821 if (!mat->ops->residual) { 7822 PetscCall(MatMult(mat, x, r)); 7823 PetscCall(VecAYPX(r, -1.0, b)); 7824 } else { 7825 PetscUseTypeMethod(mat, residual, b, x, r); 7826 } 7827 PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0)); 7828 PetscFunctionReturn(PETSC_SUCCESS); 7829 } 7830 7831 /*MC 7832 MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix 7833 7834 Synopsis: 7835 MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 7836 7837 Not Collective 7838 7839 Input Parameters: 7840 + A - the matrix 7841 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7842 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7843 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicats if the nonzero structure of the 7844 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7845 always used. 7846 7847 Output Parameters: 7848 + n - number of local rows in the (possibly compressed) matrix 7849 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 7850 . ja - the column indices 7851 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7852 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7853 7854 Level: developer 7855 7856 Note: 7857 Use `MatRestoreRowIJF90()` when you no longer need access to the data 7858 7859 .seealso: [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()` 7860 M*/ 7861 7862 /*MC 7863 MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()` 7864 7865 Synopsis: 7866 MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 7867 7868 Not Collective 7869 7870 Input Parameters: 7871 + A - the matrix 7872 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7873 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7874 inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicats if the nonzero structure of the 7875 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7876 always used. 7877 . n - number of local rows in the (possibly compressed) matrix 7878 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 7879 . ja - the column indices 7880 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7881 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7882 7883 Level: developer 7884 7885 .seealso: [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()` 7886 M*/ 7887 7888 /*@C 7889 MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix 7890 7891 Collective 7892 7893 Input Parameters: 7894 + mat - the matrix 7895 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 7896 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7897 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicats if the nonzero structure of the 7898 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7899 always used. 7900 7901 Output Parameters: 7902 + n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed 7903 . 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 7904 . ja - the column indices, use `NULL` if not needed 7905 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 7906 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 7907 7908 Level: developer 7909 7910 Notes: 7911 You CANNOT change any of the ia[] or ja[] values. 7912 7913 Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values. 7914 7915 Fortran Notes: 7916 Use 7917 .vb 7918 PetscInt, pointer :: ia(:),ja(:) 7919 call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr) 7920 ! Access the ith and jth entries via ia(i) and ja(j) 7921 .ve 7922 `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()` 7923 7924 .seealso: `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()` 7925 @*/ 7926 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7927 { 7928 PetscFunctionBegin; 7929 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7930 PetscValidType(mat, 1); 7931 if (n) PetscValidIntPointer(n, 5); 7932 if (ia) PetscValidPointer(ia, 6); 7933 if (ja) PetscValidPointer(ja, 7); 7934 if (done) PetscValidBoolPointer(done, 8); 7935 MatCheckPreallocated(mat, 1); 7936 if (!mat->ops->getrowij && done) *done = PETSC_FALSE; 7937 else { 7938 if (done) *done = PETSC_TRUE; 7939 PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0)); 7940 PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done); 7941 PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0)); 7942 } 7943 PetscFunctionReturn(PETSC_SUCCESS); 7944 } 7945 7946 /*@C 7947 MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices. 7948 7949 Collective 7950 7951 Input Parameters: 7952 + mat - the matrix 7953 . shift - 1 or zero indicating we want the indices starting at 0 or 1 7954 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be 7955 symmetrized 7956 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7957 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7958 always used. 7959 . n - number of columns in the (possibly compressed) matrix 7960 . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix 7961 - ja - the row indices 7962 7963 Output Parameters: 7964 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned 7965 7966 Level: developer 7967 7968 .seealso: `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 7969 @*/ 7970 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 7971 { 7972 PetscFunctionBegin; 7973 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7974 PetscValidType(mat, 1); 7975 PetscValidIntPointer(n, 5); 7976 if (ia) PetscValidPointer(ia, 6); 7977 if (ja) PetscValidPointer(ja, 7); 7978 PetscValidBoolPointer(done, 8); 7979 MatCheckPreallocated(mat, 1); 7980 if (!mat->ops->getcolumnij) *done = PETSC_FALSE; 7981 else { 7982 *done = PETSC_TRUE; 7983 PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 7984 } 7985 PetscFunctionReturn(PETSC_SUCCESS); 7986 } 7987 7988 /*@C 7989 MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`. 7990 7991 Collective 7992 7993 Input Parameters: 7994 + mat - the matrix 7995 . shift - 1 or zero indicating we want the indices starting at 0 or 1 7996 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 7997 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 7998 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 7999 always used. 8000 . n - size of (possibly compressed) matrix 8001 . ia - the row pointers 8002 - ja - the column indices 8003 8004 Output Parameters: 8005 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8006 8007 Level: developer 8008 8009 Note: 8010 This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental 8011 us of the array after it has been restored. If you pass `NULL`, it will 8012 not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid. 8013 8014 Fortran Note: 8015 `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()` 8016 .seealso: `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()` 8017 @*/ 8018 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8019 { 8020 PetscFunctionBegin; 8021 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8022 PetscValidType(mat, 1); 8023 if (ia) PetscValidPointer(ia, 6); 8024 if (ja) PetscValidPointer(ja, 7); 8025 if (done) PetscValidBoolPointer(done, 8); 8026 MatCheckPreallocated(mat, 1); 8027 8028 if (!mat->ops->restorerowij && done) *done = PETSC_FALSE; 8029 else { 8030 if (done) *done = PETSC_TRUE; 8031 PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8032 if (n) *n = 0; 8033 if (ia) *ia = NULL; 8034 if (ja) *ja = NULL; 8035 } 8036 PetscFunctionReturn(PETSC_SUCCESS); 8037 } 8038 8039 /*@C 8040 MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`. 8041 8042 Collective on Mat 8043 8044 Input Parameters: 8045 + mat - the matrix 8046 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8047 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8048 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8049 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8050 always used. 8051 8052 Output Parameters: 8053 + n - size of (possibly compressed) matrix 8054 . ia - the column pointers 8055 . ja - the row indices 8056 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8057 8058 Level: developer 8059 8060 .seealso: `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()` 8061 @*/ 8062 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8063 { 8064 PetscFunctionBegin; 8065 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8066 PetscValidType(mat, 1); 8067 if (ia) PetscValidPointer(ia, 6); 8068 if (ja) PetscValidPointer(ja, 7); 8069 PetscValidBoolPointer(done, 8); 8070 MatCheckPreallocated(mat, 1); 8071 8072 if (!mat->ops->restorecolumnij) *done = PETSC_FALSE; 8073 else { 8074 *done = PETSC_TRUE; 8075 PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8076 if (n) *n = 0; 8077 if (ia) *ia = NULL; 8078 if (ja) *ja = NULL; 8079 } 8080 PetscFunctionReturn(PETSC_SUCCESS); 8081 } 8082 8083 /*@C 8084 MatColoringPatch -Used inside matrix coloring routines that use `MatGetRowIJ()` and/or `MatGetColumnIJ()`. 8085 8086 Collective 8087 8088 Input Parameters: 8089 + mat - the matrix 8090 . ncolors - max color value 8091 . n - number of entries in colorarray 8092 - colorarray - array indicating color for each column 8093 8094 Output Parameters: 8095 . iscoloring - coloring generated using colorarray information 8096 8097 Level: developer 8098 8099 .seealso: `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()` 8100 @*/ 8101 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring) 8102 { 8103 PetscFunctionBegin; 8104 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8105 PetscValidType(mat, 1); 8106 PetscValidIntPointer(colorarray, 4); 8107 PetscValidPointer(iscoloring, 5); 8108 MatCheckPreallocated(mat, 1); 8109 8110 if (!mat->ops->coloringpatch) { 8111 PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring)); 8112 } else { 8113 PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring); 8114 } 8115 PetscFunctionReturn(PETSC_SUCCESS); 8116 } 8117 8118 /*@ 8119 MatSetUnfactored - Resets a factored matrix to be treated as unfactored. 8120 8121 Logically Collective 8122 8123 Input Parameter: 8124 . mat - the factored matrix to be reset 8125 8126 Level: developer 8127 8128 Notes: 8129 This routine should be used only with factored matrices formed by in-place 8130 factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE` 8131 format). This option can save memory, for example, when solving nonlinear 8132 systems with a matrix-free Newton-Krylov method and a matrix-based, in-place 8133 ILU(0) preconditioner. 8134 8135 One can specify in-place ILU(0) factorization by calling 8136 .vb 8137 PCType(pc,PCILU); 8138 PCFactorSeUseInPlace(pc); 8139 .ve 8140 or by using the options -pc_type ilu -pc_factor_in_place 8141 8142 In-place factorization ILU(0) can also be used as a local 8143 solver for the blocks within the block Jacobi or additive Schwarz 8144 methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc 8145 for details on setting local solver options. 8146 8147 Most users should employ the `KSP` interface for linear solvers 8148 instead of working directly with matrix algebra routines such as this. 8149 See, e.g., `KSPCreate()`. 8150 8151 .seealso: `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()` 8152 @*/ 8153 PetscErrorCode MatSetUnfactored(Mat mat) 8154 { 8155 PetscFunctionBegin; 8156 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8157 PetscValidType(mat, 1); 8158 MatCheckPreallocated(mat, 1); 8159 mat->factortype = MAT_FACTOR_NONE; 8160 if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS); 8161 PetscUseTypeMethod(mat, setunfactored); 8162 PetscFunctionReturn(PETSC_SUCCESS); 8163 } 8164 8165 /*MC 8166 MatDenseGetArrayF90 - Accesses a matrix array from Fortran 8167 8168 Synopsis: 8169 MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8170 8171 Not collective 8172 8173 Input Parameter: 8174 . x - matrix 8175 8176 Output Parameters: 8177 + xx_v - the Fortran pointer to the array 8178 - ierr - error code 8179 8180 Example of Usage: 8181 .vb 8182 PetscScalar, pointer xx_v(:,:) 8183 .... 8184 call MatDenseGetArrayF90(x,xx_v,ierr) 8185 a = xx_v(3) 8186 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8187 .ve 8188 8189 Level: advanced 8190 8191 .seealso: `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()` 8192 M*/ 8193 8194 /*MC 8195 MatDenseRestoreArrayF90 - Restores a matrix array that has been 8196 accessed with `MatDenseGetArrayF90()`. 8197 8198 Synopsis: 8199 MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8200 8201 Not collective 8202 8203 Input Parameters: 8204 + x - matrix 8205 - xx_v - the Fortran90 pointer to the array 8206 8207 Output Parameter: 8208 . ierr - error code 8209 8210 Example of Usage: 8211 .vb 8212 PetscScalar, pointer xx_v(:,:) 8213 .... 8214 call MatDenseGetArrayF90(x,xx_v,ierr) 8215 a = xx_v(3) 8216 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8217 .ve 8218 8219 Level: advanced 8220 8221 .seealso: `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()` 8222 M*/ 8223 8224 /*MC 8225 MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran. 8226 8227 Synopsis: 8228 MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8229 8230 Not collective 8231 8232 Input Parameter: 8233 . x - matrix 8234 8235 Output Parameters: 8236 + xx_v - the Fortran pointer to the array 8237 - ierr - error code 8238 8239 Example of Usage: 8240 .vb 8241 PetscScalar, pointer xx_v(:) 8242 .... 8243 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8244 a = xx_v(3) 8245 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8246 .ve 8247 8248 Level: advanced 8249 8250 .seealso: `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()` 8251 M*/ 8252 8253 /*MC 8254 MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been 8255 accessed with `MatSeqAIJGetArrayF90()`. 8256 8257 Synopsis: 8258 MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8259 8260 Not collective 8261 8262 Input Parameters: 8263 + x - matrix 8264 - xx_v - the Fortran90 pointer to the array 8265 8266 Output Parameter: 8267 . ierr - error code 8268 8269 Example of Usage: 8270 .vb 8271 PetscScalar, pointer xx_v(:) 8272 .... 8273 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8274 a = xx_v(3) 8275 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8276 .ve 8277 8278 Level: advanced 8279 8280 .seealso: `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()` 8281 M*/ 8282 8283 /*@ 8284 MatCreateSubMatrix - Gets a single submatrix on the same number of processors 8285 as the original matrix. 8286 8287 Collective 8288 8289 Input Parameters: 8290 + mat - the original matrix 8291 . isrow - parallel IS containing the rows this processor should obtain 8292 . 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. 8293 - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 8294 8295 Output Parameter: 8296 . newmat - the new submatrix, of the same type as the old 8297 8298 Level: advanced 8299 8300 Notes: 8301 The submatrix will be able to be multiplied with vectors using the same layout as iscol. 8302 8303 Some matrix types place restrictions on the row and column indices, such 8304 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; 8305 for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row. 8306 8307 The index sets may not have duplicate entries. 8308 8309 The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`, 8310 the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls 8311 to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX` 8312 will reuse the matrix generated the first time. You should call `MatDestroy()` on newmat when 8313 you are finished using it. 8314 8315 The communicator of the newly obtained matrix is ALWAYS the same as the communicator of 8316 the input matrix. 8317 8318 If iscol is `NULL` then all columns are obtained (not supported in Fortran). 8319 8320 Example usage: 8321 Consider the following 8x8 matrix with 34 non-zero values, that is 8322 assembled across 3 processors. Let's assume that proc0 owns 3 rows, 8323 proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 8324 as follows: 8325 8326 .vb 8327 1 2 0 | 0 3 0 | 0 4 8328 Proc0 0 5 6 | 7 0 0 | 8 0 8329 9 0 10 | 11 0 0 | 12 0 8330 ------------------------------------- 8331 13 0 14 | 15 16 17 | 0 0 8332 Proc1 0 18 0 | 19 20 21 | 0 0 8333 0 0 0 | 22 23 0 | 24 0 8334 ------------------------------------- 8335 Proc2 25 26 27 | 0 0 28 | 29 0 8336 30 0 0 | 31 32 33 | 0 34 8337 .ve 8338 8339 Suppose isrow = [0 1 | 4 | 6 7] and iscol = [1 2 | 3 4 5 | 6]. The resulting submatrix is 8340 8341 .vb 8342 2 0 | 0 3 0 | 0 8343 Proc0 5 6 | 7 0 0 | 8 8344 ------------------------------- 8345 Proc1 18 0 | 19 20 21 | 0 8346 ------------------------------- 8347 Proc2 26 27 | 0 0 28 | 29 8348 0 0 | 31 32 33 | 0 8349 .ve 8350 8351 .seealso: `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()` 8352 @*/ 8353 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat) 8354 { 8355 PetscMPIInt size; 8356 Mat *local; 8357 IS iscoltmp; 8358 PetscBool flg; 8359 8360 PetscFunctionBegin; 8361 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8362 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 8363 if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 8364 PetscValidPointer(newmat, 5); 8365 if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5); 8366 PetscValidType(mat, 1); 8367 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8368 PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX"); 8369 8370 MatCheckPreallocated(mat, 1); 8371 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8372 8373 if (!iscol || isrow == iscol) { 8374 PetscBool stride; 8375 PetscMPIInt grabentirematrix = 0, grab; 8376 PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride)); 8377 if (stride) { 8378 PetscInt first, step, n, rstart, rend; 8379 PetscCall(ISStrideGetInfo(isrow, &first, &step)); 8380 if (step == 1) { 8381 PetscCall(MatGetOwnershipRange(mat, &rstart, &rend)); 8382 if (rstart == first) { 8383 PetscCall(ISGetLocalSize(isrow, &n)); 8384 if (n == rend - rstart) grabentirematrix = 1; 8385 } 8386 } 8387 } 8388 PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat))); 8389 if (grab) { 8390 PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n")); 8391 if (cll == MAT_INITIAL_MATRIX) { 8392 *newmat = mat; 8393 PetscCall(PetscObjectReference((PetscObject)mat)); 8394 } 8395 PetscFunctionReturn(PETSC_SUCCESS); 8396 } 8397 } 8398 8399 if (!iscol) { 8400 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp)); 8401 } else { 8402 iscoltmp = iscol; 8403 } 8404 8405 /* if original matrix is on just one processor then use submatrix generated */ 8406 if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) { 8407 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat)); 8408 goto setproperties; 8409 } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) { 8410 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local)); 8411 *newmat = *local; 8412 PetscCall(PetscFree(local)); 8413 goto setproperties; 8414 } else if (!mat->ops->createsubmatrix) { 8415 /* Create a new matrix type that implements the operation using the full matrix */ 8416 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8417 switch (cll) { 8418 case MAT_INITIAL_MATRIX: 8419 PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat)); 8420 break; 8421 case MAT_REUSE_MATRIX: 8422 PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp)); 8423 break; 8424 default: 8425 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX"); 8426 } 8427 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8428 goto setproperties; 8429 } 8430 8431 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8432 PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat); 8433 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8434 8435 setproperties: 8436 PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg)); 8437 if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat)); 8438 if (!iscol) PetscCall(ISDestroy(&iscoltmp)); 8439 if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat)); 8440 PetscFunctionReturn(PETSC_SUCCESS); 8441 } 8442 8443 /*@ 8444 MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix 8445 8446 Not Collective 8447 8448 Input Parameters: 8449 + A - the matrix we wish to propagate options from 8450 - B - the matrix we wish to propagate options to 8451 8452 Level: beginner 8453 8454 Note: 8455 Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL` 8456 8457 .seealso: `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, MatIsStructurallySymmetricKnown()` 8458 @*/ 8459 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B) 8460 { 8461 PetscFunctionBegin; 8462 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8463 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 8464 B->symmetry_eternal = A->symmetry_eternal; 8465 B->structural_symmetry_eternal = A->structural_symmetry_eternal; 8466 B->symmetric = A->symmetric; 8467 B->structurally_symmetric = A->structurally_symmetric; 8468 B->spd = A->spd; 8469 B->hermitian = A->hermitian; 8470 PetscFunctionReturn(PETSC_SUCCESS); 8471 } 8472 8473 /*@ 8474 MatStashSetInitialSize - sets the sizes of the matrix stash, that is 8475 used during the assembly process to store values that belong to 8476 other processors. 8477 8478 Not Collective 8479 8480 Input Parameters: 8481 + mat - the matrix 8482 . size - the initial size of the stash. 8483 - bsize - the initial size of the block-stash(if used). 8484 8485 Options Database Keys: 8486 + -matstash_initial_size <size> or <size0,size1,...sizep-1> 8487 - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1> 8488 8489 Level: intermediate 8490 8491 Notes: 8492 The block-stash is used for values set with `MatSetValuesBlocked()` while 8493 the stash is used for values set with `MatSetValues()` 8494 8495 Run with the option -info and look for output of the form 8496 MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs. 8497 to determine the appropriate value, MM, to use for size and 8498 MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs. 8499 to determine the value, BMM to use for bsize 8500 8501 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()` 8502 @*/ 8503 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize) 8504 { 8505 PetscFunctionBegin; 8506 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8507 PetscValidType(mat, 1); 8508 PetscCall(MatStashSetInitialSize_Private(&mat->stash, size)); 8509 PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize)); 8510 PetscFunctionReturn(PETSC_SUCCESS); 8511 } 8512 8513 /*@ 8514 MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of 8515 the matrix 8516 8517 Neighbor-wise Collective 8518 8519 Input Parameters: 8520 + mat - the matrix 8521 . x,y - the vectors 8522 - w - where the result is stored 8523 8524 Level: intermediate 8525 8526 Notes: 8527 `w` may be the same vector as `y`. 8528 8529 This allows one to use either the restriction or interpolation (its transpose) 8530 matrix to do the interpolation 8531 8532 .seealso: `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8533 @*/ 8534 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w) 8535 { 8536 PetscInt M, N, Ny; 8537 8538 PetscFunctionBegin; 8539 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8540 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8541 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8542 PetscValidHeaderSpecific(w, VEC_CLASSID, 4); 8543 PetscCall(MatGetSize(A, &M, &N)); 8544 PetscCall(VecGetSize(y, &Ny)); 8545 if (M == Ny) { 8546 PetscCall(MatMultAdd(A, x, y, w)); 8547 } else { 8548 PetscCall(MatMultTransposeAdd(A, x, y, w)); 8549 } 8550 PetscFunctionReturn(PETSC_SUCCESS); 8551 } 8552 8553 /*@ 8554 MatInterpolate - y = A*x or A'*x depending on the shape of 8555 the matrix 8556 8557 Neighbor-wise Collective 8558 8559 Input Parameters: 8560 + mat - the matrix 8561 - x,y - the vectors 8562 8563 Level: intermediate 8564 8565 Note: 8566 This allows one to use either the restriction or interpolation (its transpose) 8567 matrix to do the interpolation 8568 8569 .seealso: `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8570 @*/ 8571 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y) 8572 { 8573 PetscInt M, N, Ny; 8574 8575 PetscFunctionBegin; 8576 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8577 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8578 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8579 PetscCall(MatGetSize(A, &M, &N)); 8580 PetscCall(VecGetSize(y, &Ny)); 8581 if (M == Ny) { 8582 PetscCall(MatMult(A, x, y)); 8583 } else { 8584 PetscCall(MatMultTranspose(A, x, y)); 8585 } 8586 PetscFunctionReturn(PETSC_SUCCESS); 8587 } 8588 8589 /*@ 8590 MatRestrict - y = A*x or A'*x 8591 8592 Neighbor-wise Collective on Mat 8593 8594 Input Parameters: 8595 + mat - the matrix 8596 - x,y - the vectors 8597 8598 Level: intermediate 8599 8600 Note: 8601 This allows one to use either the restriction or interpolation (its transpose) 8602 matrix to do the restriction 8603 8604 .seealso: `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG` 8605 @*/ 8606 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y) 8607 { 8608 PetscInt M, N, Ny; 8609 8610 PetscFunctionBegin; 8611 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8612 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8613 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8614 PetscCall(MatGetSize(A, &M, &N)); 8615 PetscCall(VecGetSize(y, &Ny)); 8616 if (M == Ny) { 8617 PetscCall(MatMult(A, x, y)); 8618 } else { 8619 PetscCall(MatMultTranspose(A, x, y)); 8620 } 8621 PetscFunctionReturn(PETSC_SUCCESS); 8622 } 8623 8624 /*@ 8625 MatMatInterpolateAdd - Y = W + A*X or W + A'*X 8626 8627 Neighbor-wise Collective on Mat 8628 8629 Input Parameters: 8630 + mat - the matrix 8631 - w, x - the input dense matrices 8632 8633 Output Parameters: 8634 . y - the output dense matrix 8635 8636 Level: intermediate 8637 8638 Note: 8639 This allows one to use either the restriction or interpolation (its transpose) 8640 matrix to do the interpolation. y matrix can be reused if already created with the proper sizes, 8641 otherwise it will be recreated. y must be initialized to `NULL` if not supplied. 8642 8643 .seealso: `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG` 8644 @*/ 8645 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y) 8646 { 8647 PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0; 8648 PetscBool trans = PETSC_TRUE; 8649 MatReuse reuse = MAT_INITIAL_MATRIX; 8650 8651 PetscFunctionBegin; 8652 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8653 PetscValidHeaderSpecific(x, MAT_CLASSID, 2); 8654 PetscValidType(x, 2); 8655 if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3); 8656 if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4); 8657 PetscCall(MatGetSize(A, &M, &N)); 8658 PetscCall(MatGetSize(x, &Mx, &Nx)); 8659 if (N == Mx) trans = PETSC_FALSE; 8660 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); 8661 Mo = trans ? N : M; 8662 if (*y) { 8663 PetscCall(MatGetSize(*y, &My, &Ny)); 8664 if (Mo == My && Nx == Ny) { 8665 reuse = MAT_REUSE_MATRIX; 8666 } else { 8667 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); 8668 PetscCall(MatDestroy(y)); 8669 } 8670 } 8671 8672 if (w && *y == w) { /* this is to minimize changes in PCMG */ 8673 PetscBool flg; 8674 8675 PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w)); 8676 if (w) { 8677 PetscInt My, Ny, Mw, Nw; 8678 8679 PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg)); 8680 PetscCall(MatGetSize(*y, &My, &Ny)); 8681 PetscCall(MatGetSize(w, &Mw, &Nw)); 8682 if (!flg || My != Mw || Ny != Nw) w = NULL; 8683 } 8684 if (!w) { 8685 PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w)); 8686 PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w)); 8687 PetscCall(PetscObjectDereference((PetscObject)w)); 8688 } else { 8689 PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN)); 8690 } 8691 } 8692 if (!trans) { 8693 PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8694 } else { 8695 PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y)); 8696 } 8697 if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN)); 8698 PetscFunctionReturn(PETSC_SUCCESS); 8699 } 8700 8701 /*@ 8702 MatMatInterpolate - Y = A*X or A'*X 8703 8704 Neighbor-wise Collective on Mat 8705 8706 Input Parameters: 8707 + mat - the matrix 8708 - x - the input dense matrix 8709 8710 Output Parameters: 8711 . y - the output dense matrix 8712 8713 Level: intermediate 8714 8715 Note: 8716 This allows one to use either the restriction or interpolation (its transpose) 8717 matrix to do the interpolation. y matrix can be reused if already created with the proper sizes, 8718 otherwise it will be recreated. y must be initialized to `NULL` if not supplied. 8719 8720 .seealso: `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG` 8721 @*/ 8722 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y) 8723 { 8724 PetscFunctionBegin; 8725 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8726 PetscFunctionReturn(PETSC_SUCCESS); 8727 } 8728 8729 /*@ 8730 MatMatRestrict - Y = A*X or A'*X 8731 8732 Neighbor-wise Collective on Mat 8733 8734 Input Parameters: 8735 + mat - the matrix 8736 - x - the input dense matrix 8737 8738 Output Parameters: 8739 . y - the output dense matrix 8740 8741 Level: intermediate 8742 8743 Note: 8744 This allows one to use either the restriction or interpolation (its transpose) 8745 matrix to do the restriction. y matrix can be reused if already created with the proper sizes, 8746 otherwise it will be recreated. y must be initialized to `NULL` if not supplied. 8747 8748 .seealso: `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG` 8749 @*/ 8750 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y) 8751 { 8752 PetscFunctionBegin; 8753 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8754 PetscFunctionReturn(PETSC_SUCCESS); 8755 } 8756 8757 /*@ 8758 MatGetNullSpace - retrieves the null space of a matrix. 8759 8760 Logically Collective 8761 8762 Input Parameters: 8763 + mat - the matrix 8764 - nullsp - the null space object 8765 8766 Level: developer 8767 8768 .seealso: `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace` 8769 @*/ 8770 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp) 8771 { 8772 PetscFunctionBegin; 8773 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8774 PetscValidPointer(nullsp, 2); 8775 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp; 8776 PetscFunctionReturn(PETSC_SUCCESS); 8777 } 8778 8779 /*@ 8780 MatSetNullSpace - attaches a null space to a matrix. 8781 8782 Logically Collective 8783 8784 Input Parameters: 8785 + mat - the matrix 8786 - nullsp - the null space object 8787 8788 Level: advanced 8789 8790 Notes: 8791 This null space is used by the `KSP` linear solvers to solve singular systems. 8792 8793 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` 8794 8795 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 8796 to zero but the linear system will still be solved in a least squares sense. 8797 8798 The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that 8799 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). 8800 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 8801 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 8802 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). 8803 This \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix. 8804 8805 If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called 8806 `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this 8807 routine also automatically calls `MatSetTransposeNullSpace()`. 8808 8809 The user should call `MatNullSpaceDestroy()`. 8810 8811 .seealso: `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, 8812 `KSPSetPCSide()` 8813 @*/ 8814 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp) 8815 { 8816 PetscFunctionBegin; 8817 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8818 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8819 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8820 PetscCall(MatNullSpaceDestroy(&mat->nullsp)); 8821 mat->nullsp = nullsp; 8822 if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp)); 8823 PetscFunctionReturn(PETSC_SUCCESS); 8824 } 8825 8826 /*@ 8827 MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix. 8828 8829 Logically Collective 8830 8831 Input Parameters: 8832 + mat - the matrix 8833 - nullsp - the null space object 8834 8835 Level: developer 8836 8837 .seealso: `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()` 8838 @*/ 8839 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp) 8840 { 8841 PetscFunctionBegin; 8842 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8843 PetscValidType(mat, 1); 8844 PetscValidPointer(nullsp, 2); 8845 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp; 8846 PetscFunctionReturn(PETSC_SUCCESS); 8847 } 8848 8849 /*@ 8850 MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix 8851 8852 Logically Collective 8853 8854 Input Parameters: 8855 + mat - the matrix 8856 - nullsp - the null space object 8857 8858 Level: advanced 8859 8860 Notes: 8861 This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning. 8862 8863 See `MatSetNullSpace()` 8864 8865 .seealso: `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()` 8866 @*/ 8867 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp) 8868 { 8869 PetscFunctionBegin; 8870 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8871 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8872 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8873 PetscCall(MatNullSpaceDestroy(&mat->transnullsp)); 8874 mat->transnullsp = nullsp; 8875 PetscFunctionReturn(PETSC_SUCCESS); 8876 } 8877 8878 /*@ 8879 MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions 8880 This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix. 8881 8882 Logically Collective 8883 8884 Input Parameters: 8885 + mat - the matrix 8886 - nullsp - the null space object 8887 8888 Level: advanced 8889 8890 Notes: 8891 Overwrites any previous near null space that may have been attached 8892 8893 You can remove the null space by calling this routine with an nullsp of `NULL` 8894 8895 .seealso: `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()` 8896 @*/ 8897 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp) 8898 { 8899 PetscFunctionBegin; 8900 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8901 PetscValidType(mat, 1); 8902 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8903 MatCheckPreallocated(mat, 1); 8904 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8905 PetscCall(MatNullSpaceDestroy(&mat->nearnullsp)); 8906 mat->nearnullsp = nullsp; 8907 PetscFunctionReturn(PETSC_SUCCESS); 8908 } 8909 8910 /*@ 8911 MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()` 8912 8913 Not Collective 8914 8915 Input Parameter: 8916 . mat - the matrix 8917 8918 Output Parameter: 8919 . nullsp - the null space object, `NULL` if not set 8920 8921 Level: advanced 8922 8923 .seealso: `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()` 8924 @*/ 8925 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp) 8926 { 8927 PetscFunctionBegin; 8928 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8929 PetscValidType(mat, 1); 8930 PetscValidPointer(nullsp, 2); 8931 MatCheckPreallocated(mat, 1); 8932 *nullsp = mat->nearnullsp; 8933 PetscFunctionReturn(PETSC_SUCCESS); 8934 } 8935 8936 /*@C 8937 MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix. 8938 8939 Collective 8940 8941 Input Parameters: 8942 + mat - the matrix 8943 . row - row/column permutation 8944 . fill - expected fill factor >= 1.0 8945 - level - level of fill, for ICC(k) 8946 8947 Notes: 8948 Probably really in-place only when level of fill is zero, otherwise allocates 8949 new space to store factored matrix and deletes previous memory. 8950 8951 Most users should employ the `KSP` interface for linear solvers 8952 instead of working directly with matrix algebra routines such as this. 8953 See, e.g., `KSPCreate()`. 8954 8955 Level: developer 8956 8957 Developer Note: 8958 The Fortran interface is not autogenerated as the 8959 interface definition cannot be generated correctly [due to `MatFactorInfo`] 8960 8961 .seealso: `Mat`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 8962 @*/ 8963 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info) 8964 { 8965 PetscFunctionBegin; 8966 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8967 PetscValidType(mat, 1); 8968 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 8969 PetscValidPointer(info, 3); 8970 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 8971 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 8972 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8973 MatCheckPreallocated(mat, 1); 8974 PetscUseTypeMethod(mat, iccfactor, row, info); 8975 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 8976 PetscFunctionReturn(PETSC_SUCCESS); 8977 } 8978 8979 /*@ 8980 MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the 8981 ghosted ones. 8982 8983 Not Collective 8984 8985 Input Parameters: 8986 + mat - the matrix 8987 - diag - the diagonal values, including ghost ones 8988 8989 Level: developer 8990 8991 Notes: 8992 Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices 8993 8994 This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()` 8995 8996 .seealso: `Mat`, `MatDiagonalScale()` 8997 @*/ 8998 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag) 8999 { 9000 PetscMPIInt size; 9001 9002 PetscFunctionBegin; 9003 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9004 PetscValidHeaderSpecific(diag, VEC_CLASSID, 2); 9005 PetscValidType(mat, 1); 9006 9007 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled"); 9008 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 9009 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 9010 if (size == 1) { 9011 PetscInt n, m; 9012 PetscCall(VecGetSize(diag, &n)); 9013 PetscCall(MatGetSize(mat, NULL, &m)); 9014 PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions"); 9015 PetscCall(MatDiagonalScale(mat, NULL, diag)); 9016 } else { 9017 PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag)); 9018 } 9019 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 9020 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9021 PetscFunctionReturn(PETSC_SUCCESS); 9022 } 9023 9024 /*@ 9025 MatGetInertia - Gets the inertia from a factored matrix 9026 9027 Collective 9028 9029 Input Parameter: 9030 . mat - the matrix 9031 9032 Output Parameters: 9033 + nneg - number of negative eigenvalues 9034 . nzero - number of zero eigenvalues 9035 - npos - number of positive eigenvalues 9036 9037 Level: advanced 9038 9039 Note: 9040 Matrix must have been factored by `MatCholeskyFactor()` 9041 9042 .seealso: `Mat`, `MatGetFactor()`, `MatCholeskyFactor()` 9043 @*/ 9044 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos) 9045 { 9046 PetscFunctionBegin; 9047 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9048 PetscValidType(mat, 1); 9049 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9050 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled"); 9051 PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos); 9052 PetscFunctionReturn(PETSC_SUCCESS); 9053 } 9054 9055 /*@C 9056 MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors 9057 9058 Neighbor-wise Collective 9059 9060 Input Parameters: 9061 + mat - the factored matrix obtained with `MatGetFactor()` 9062 - b - the right-hand-side vectors 9063 9064 Output Parameter: 9065 . x - the result vectors 9066 9067 Level: developer 9068 9069 Note: 9070 The vectors `b` and `x` cannot be the same. I.e., one cannot 9071 call `MatSolves`(A,x,x). 9072 9073 .seealso: `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()` 9074 @*/ 9075 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x) 9076 { 9077 PetscFunctionBegin; 9078 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9079 PetscValidType(mat, 1); 9080 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 9081 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9082 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 9083 9084 MatCheckPreallocated(mat, 1); 9085 PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0)); 9086 PetscUseTypeMethod(mat, solves, b, x); 9087 PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0)); 9088 PetscFunctionReturn(PETSC_SUCCESS); 9089 } 9090 9091 /*@ 9092 MatIsSymmetric - Test whether a matrix is symmetric 9093 9094 Collective 9095 9096 Input Parameters: 9097 + A - the matrix to test 9098 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose) 9099 9100 Output Parameters: 9101 . flg - the result 9102 9103 Level: intermediate 9104 9105 Notes: 9106 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9107 9108 If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()` 9109 9110 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9111 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9112 9113 .seealso: `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`, 9114 `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()` 9115 @*/ 9116 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg) 9117 { 9118 PetscFunctionBegin; 9119 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9120 PetscValidBoolPointer(flg, 3); 9121 9122 if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE; 9123 else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE; 9124 else { 9125 if (!A->ops->issymmetric) { 9126 MatType mattype; 9127 PetscCall(MatGetType(A, &mattype)); 9128 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for symmetric", mattype); 9129 } 9130 PetscUseTypeMethod(A, issymmetric, tol, flg); 9131 if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg)); 9132 } 9133 PetscFunctionReturn(PETSC_SUCCESS); 9134 } 9135 9136 /*@ 9137 MatIsHermitian - Test whether a matrix is Hermitian 9138 9139 Collective on Mat 9140 9141 Input Parameters: 9142 + A - the matrix to test 9143 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian) 9144 9145 Output Parameters: 9146 . flg - the result 9147 9148 Level: intermediate 9149 9150 Notes: 9151 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9152 9153 If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()` 9154 9155 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9156 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`) 9157 9158 .seealso: `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, 9159 `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()` 9160 @*/ 9161 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg) 9162 { 9163 PetscFunctionBegin; 9164 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9165 PetscValidBoolPointer(flg, 3); 9166 9167 if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE; 9168 else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE; 9169 else { 9170 if (!A->ops->ishermitian) { 9171 MatType mattype; 9172 PetscCall(MatGetType(A, &mattype)); 9173 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for hermitian", mattype); 9174 } 9175 PetscUseTypeMethod(A, ishermitian, tol, flg); 9176 if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg)); 9177 } 9178 PetscFunctionReturn(PETSC_SUCCESS); 9179 } 9180 9181 /*@ 9182 MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state 9183 9184 Not Collective 9185 9186 Input Parameter: 9187 . A - the matrix to check 9188 9189 Output Parameters: 9190 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid) 9191 - flg - the result (only valid if set is `PETSC_TRUE`) 9192 9193 Level: advanced 9194 9195 Notes: 9196 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()` 9197 if you want it explicitly checked 9198 9199 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9200 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9201 9202 .seealso: `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9203 @*/ 9204 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9205 { 9206 PetscFunctionBegin; 9207 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9208 PetscValidBoolPointer(set, 2); 9209 PetscValidBoolPointer(flg, 3); 9210 if (A->symmetric != PETSC_BOOL3_UNKNOWN) { 9211 *set = PETSC_TRUE; 9212 *flg = PetscBool3ToBool(A->symmetric); 9213 } else { 9214 *set = PETSC_FALSE; 9215 } 9216 PetscFunctionReturn(PETSC_SUCCESS); 9217 } 9218 9219 /*@ 9220 MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state 9221 9222 Not Collective 9223 9224 Input Parameter: 9225 . A - the matrix to check 9226 9227 Output Parameters: 9228 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid) 9229 - flg - the result (only valid if set is `PETSC_TRUE`) 9230 9231 Level: advanced 9232 9233 Notes: 9234 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). 9235 9236 One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD 9237 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`) 9238 9239 .seealso: `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9240 @*/ 9241 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg) 9242 { 9243 PetscFunctionBegin; 9244 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9245 PetscValidBoolPointer(set, 2); 9246 PetscValidBoolPointer(flg, 3); 9247 if (A->spd != PETSC_BOOL3_UNKNOWN) { 9248 *set = PETSC_TRUE; 9249 *flg = PetscBool3ToBool(A->spd); 9250 } else { 9251 *set = PETSC_FALSE; 9252 } 9253 PetscFunctionReturn(PETSC_SUCCESS); 9254 } 9255 9256 /*@ 9257 MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state 9258 9259 Not Collective 9260 9261 Input Parameter: 9262 . A - the matrix to check 9263 9264 Output Parameters: 9265 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid) 9266 - flg - the result (only valid if set is `PETSC_TRUE`) 9267 9268 Level: advanced 9269 9270 Notes: 9271 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()` 9272 if you want it explicitly checked 9273 9274 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9275 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9276 9277 .seealso: `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()` 9278 @*/ 9279 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg) 9280 { 9281 PetscFunctionBegin; 9282 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9283 PetscValidBoolPointer(set, 2); 9284 PetscValidBoolPointer(flg, 3); 9285 if (A->hermitian != PETSC_BOOL3_UNKNOWN) { 9286 *set = PETSC_TRUE; 9287 *flg = PetscBool3ToBool(A->hermitian); 9288 } else { 9289 *set = PETSC_FALSE; 9290 } 9291 PetscFunctionReturn(PETSC_SUCCESS); 9292 } 9293 9294 /*@ 9295 MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric 9296 9297 Collective on Mat 9298 9299 Input Parameter: 9300 . A - the matrix to test 9301 9302 Output Parameters: 9303 . flg - the result 9304 9305 Level: intermediate 9306 9307 Notes: 9308 If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()` 9309 9310 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 9311 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9312 9313 .seealso: `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()` 9314 @*/ 9315 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg) 9316 { 9317 PetscFunctionBegin; 9318 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9319 PetscValidBoolPointer(flg, 2); 9320 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9321 *flg = PetscBool3ToBool(A->structurally_symmetric); 9322 } else { 9323 PetscUseTypeMethod(A, isstructurallysymmetric, flg); 9324 PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg)); 9325 } 9326 PetscFunctionReturn(PETSC_SUCCESS); 9327 } 9328 9329 /*@ 9330 MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state 9331 9332 Not Collective 9333 9334 Input Parameter: 9335 . A - the matrix to check 9336 9337 Output Parameters: 9338 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid) 9339 - flg - the result (only valid if set is PETSC_TRUE) 9340 9341 Level: advanced 9342 9343 Notes: 9344 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 9345 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9346 9347 Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation) 9348 9349 .seealso: `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9350 @*/ 9351 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9352 { 9353 PetscFunctionBegin; 9354 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9355 PetscValidBoolPointer(set, 2); 9356 PetscValidBoolPointer(flg, 3); 9357 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9358 *set = PETSC_TRUE; 9359 *flg = PetscBool3ToBool(A->structurally_symmetric); 9360 } else { 9361 *set = PETSC_FALSE; 9362 } 9363 PetscFunctionReturn(PETSC_SUCCESS); 9364 } 9365 9366 /*@ 9367 MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need 9368 to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process 9369 9370 Not collective 9371 9372 Input Parameter: 9373 . mat - the matrix 9374 9375 Output Parameters: 9376 + nstash - the size of the stash 9377 . reallocs - the number of additional mallocs incurred. 9378 . bnstash - the size of the block stash 9379 - breallocs - the number of additional mallocs incurred.in the block stash 9380 9381 Level: advanced 9382 9383 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()` 9384 @*/ 9385 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs) 9386 { 9387 PetscFunctionBegin; 9388 PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs)); 9389 PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs)); 9390 PetscFunctionReturn(PETSC_SUCCESS); 9391 } 9392 9393 /*@C 9394 MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same 9395 parallel layout, `PetscLayout` for rows and columns 9396 9397 Collective 9398 9399 Input Parameter: 9400 . mat - the matrix 9401 9402 Output Parameters: 9403 + right - (optional) vector that the matrix can be multiplied against 9404 - left - (optional) vector that the matrix vector product can be stored in 9405 9406 Level: advanced 9407 9408 Notes: 9409 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()`. 9410 9411 These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed 9412 9413 .seealso: `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()` 9414 @*/ 9415 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left) 9416 { 9417 PetscFunctionBegin; 9418 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9419 PetscValidType(mat, 1); 9420 if (mat->ops->getvecs) { 9421 PetscUseTypeMethod(mat, getvecs, right, left); 9422 } else { 9423 PetscInt rbs, cbs; 9424 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 9425 if (right) { 9426 PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup"); 9427 PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), right)); 9428 PetscCall(VecSetSizes(*right, mat->cmap->n, PETSC_DETERMINE)); 9429 PetscCall(VecSetBlockSize(*right, cbs)); 9430 PetscCall(VecSetType(*right, mat->defaultvectype)); 9431 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9432 if (mat->boundtocpu && mat->bindingpropagates) { 9433 PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE)); 9434 PetscCall(VecBindToCPU(*right, PETSC_TRUE)); 9435 } 9436 #endif 9437 PetscCall(PetscLayoutReference(mat->cmap, &(*right)->map)); 9438 } 9439 if (left) { 9440 PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup"); 9441 PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), left)); 9442 PetscCall(VecSetSizes(*left, mat->rmap->n, PETSC_DETERMINE)); 9443 PetscCall(VecSetBlockSize(*left, rbs)); 9444 PetscCall(VecSetType(*left, mat->defaultvectype)); 9445 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9446 if (mat->boundtocpu && mat->bindingpropagates) { 9447 PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE)); 9448 PetscCall(VecBindToCPU(*left, PETSC_TRUE)); 9449 } 9450 #endif 9451 PetscCall(PetscLayoutReference(mat->rmap, &(*left)->map)); 9452 } 9453 } 9454 PetscFunctionReturn(PETSC_SUCCESS); 9455 } 9456 9457 /*@C 9458 MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure 9459 with default values. 9460 9461 Not Collective 9462 9463 Input Parameters: 9464 . info - the `MatFactorInfo` data structure 9465 9466 Level: developer 9467 9468 Notes: 9469 The solvers are generally used through the `KSP` and `PC` objects, for example 9470 `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC` 9471 9472 Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed 9473 9474 Developer Note: 9475 The Fortran interface is not autogenerated as the 9476 interface definition cannot be generated correctly [due to `MatFactorInfo`] 9477 9478 .seealso: `Mat`, `MatGetFactor()`, `MatFactorInfo` 9479 @*/ 9480 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info) 9481 { 9482 PetscFunctionBegin; 9483 PetscCall(PetscMemzero(info, sizeof(MatFactorInfo))); 9484 PetscFunctionReturn(PETSC_SUCCESS); 9485 } 9486 9487 /*@ 9488 MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed 9489 9490 Collective 9491 9492 Input Parameters: 9493 + mat - the factored matrix 9494 - is - the index set defining the Schur indices (0-based) 9495 9496 Level: advanced 9497 9498 Notes: 9499 Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system. 9500 9501 You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call. 9502 9503 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9504 9505 .seealso: `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`, 9506 `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9507 @*/ 9508 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is) 9509 { 9510 PetscErrorCode (*f)(Mat, IS); 9511 9512 PetscFunctionBegin; 9513 PetscValidType(mat, 1); 9514 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9515 PetscValidType(is, 2); 9516 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 9517 PetscCheckSameComm(mat, 1, is, 2); 9518 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 9519 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f)); 9520 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO"); 9521 PetscCall(MatDestroy(&mat->schur)); 9522 PetscCall((*f)(mat, is)); 9523 PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created"); 9524 PetscFunctionReturn(PETSC_SUCCESS); 9525 } 9526 9527 /*@ 9528 MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step 9529 9530 Logically Collective 9531 9532 Input Parameters: 9533 + F - the factored matrix obtained by calling `MatGetFactor()` 9534 . S - location where to return the Schur complement, can be `NULL` 9535 - status - the status of the Schur complement matrix, can be `NULL` 9536 9537 Level: advanced 9538 9539 Notes: 9540 You must call `MatFactorSetSchurIS()` before calling this routine. 9541 9542 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9543 9544 The routine provides a copy of the Schur matrix stored within the solver data structures. 9545 The caller must destroy the object when it is no longer needed. 9546 If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse. 9547 9548 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) 9549 9550 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9551 9552 Developer Note: 9553 The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc 9554 matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix. 9555 9556 .seealso: `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9557 @*/ 9558 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9559 { 9560 PetscFunctionBegin; 9561 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9562 if (S) PetscValidPointer(S, 2); 9563 if (status) PetscValidPointer(status, 3); 9564 if (S) { 9565 PetscErrorCode (*f)(Mat, Mat *); 9566 9567 PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f)); 9568 if (f) { 9569 PetscCall((*f)(F, S)); 9570 } else { 9571 PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S)); 9572 } 9573 } 9574 if (status) *status = F->schur_status; 9575 PetscFunctionReturn(PETSC_SUCCESS); 9576 } 9577 9578 /*@ 9579 MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix 9580 9581 Logically Collective 9582 9583 Input Parameters: 9584 + F - the factored matrix obtained by calling `MatGetFactor()` 9585 . *S - location where to return the Schur complement, can be `NULL` 9586 - status - the status of the Schur complement matrix, can be `NULL` 9587 9588 Level: advanced 9589 9590 Notes: 9591 You must call `MatFactorSetSchurIS()` before calling this routine. 9592 9593 Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS` 9594 9595 The routine returns a the Schur Complement stored within the data structures of the solver. 9596 9597 If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement. 9598 9599 The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed. 9600 9601 Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix 9602 9603 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9604 9605 .seealso: `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9606 @*/ 9607 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9608 { 9609 PetscFunctionBegin; 9610 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9611 if (S) PetscValidPointer(S, 2); 9612 if (status) PetscValidPointer(status, 3); 9613 if (S) *S = F->schur; 9614 if (status) *status = F->schur_status; 9615 PetscFunctionReturn(PETSC_SUCCESS); 9616 } 9617 9618 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F) 9619 { 9620 Mat S = F->schur; 9621 9622 PetscFunctionBegin; 9623 switch (F->schur_status) { 9624 case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through 9625 case MAT_FACTOR_SCHUR_INVERTED: 9626 if (S) { 9627 S->ops->solve = NULL; 9628 S->ops->matsolve = NULL; 9629 S->ops->solvetranspose = NULL; 9630 S->ops->matsolvetranspose = NULL; 9631 S->ops->solveadd = NULL; 9632 S->ops->solvetransposeadd = NULL; 9633 S->factortype = MAT_FACTOR_NONE; 9634 PetscCall(PetscFree(S->solvertype)); 9635 } 9636 case MAT_FACTOR_SCHUR_FACTORED: // fall-through 9637 break; 9638 default: 9639 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9640 } 9641 PetscFunctionReturn(PETSC_SUCCESS); 9642 } 9643 9644 /*@ 9645 MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()` 9646 9647 Logically Collective 9648 9649 Input Parameters: 9650 + F - the factored matrix obtained by calling `MatGetFactor()` 9651 . *S - location where the Schur complement is stored 9652 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`) 9653 9654 Level: advanced 9655 9656 .seealso: `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9657 @*/ 9658 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status) 9659 { 9660 PetscFunctionBegin; 9661 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9662 if (S) { 9663 PetscValidHeaderSpecific(*S, MAT_CLASSID, 2); 9664 *S = NULL; 9665 } 9666 F->schur_status = status; 9667 PetscCall(MatFactorUpdateSchurStatus_Private(F)); 9668 PetscFunctionReturn(PETSC_SUCCESS); 9669 } 9670 9671 /*@ 9672 MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step 9673 9674 Logically Collective 9675 9676 Input Parameters: 9677 + F - the factored matrix obtained by calling `MatGetFactor()` 9678 . rhs - location where the right hand side of the Schur complement system is stored 9679 - sol - location where the solution of the Schur complement system has to be returned 9680 9681 Level: advanced 9682 9683 Notes: 9684 The sizes of the vectors should match the size of the Schur complement 9685 9686 Must be called after `MatFactorSetSchurIS()` 9687 9688 .seealso: `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()` 9689 @*/ 9690 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol) 9691 { 9692 PetscFunctionBegin; 9693 PetscValidType(F, 1); 9694 PetscValidType(rhs, 2); 9695 PetscValidType(sol, 3); 9696 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9697 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9698 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9699 PetscCheckSameComm(F, 1, rhs, 2); 9700 PetscCheckSameComm(F, 1, sol, 3); 9701 PetscCall(MatFactorFactorizeSchurComplement(F)); 9702 switch (F->schur_status) { 9703 case MAT_FACTOR_SCHUR_FACTORED: 9704 PetscCall(MatSolveTranspose(F->schur, rhs, sol)); 9705 break; 9706 case MAT_FACTOR_SCHUR_INVERTED: 9707 PetscCall(MatMultTranspose(F->schur, rhs, sol)); 9708 break; 9709 default: 9710 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9711 } 9712 PetscFunctionReturn(PETSC_SUCCESS); 9713 } 9714 9715 /*@ 9716 MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step 9717 9718 Logically Collective 9719 9720 Input Parameters: 9721 + F - the factored matrix obtained by calling `MatGetFactor()` 9722 . rhs - location where the right hand side of the Schur complement system is stored 9723 - sol - location where the solution of the Schur complement system has to be returned 9724 9725 Level: advanced 9726 9727 Notes: 9728 The sizes of the vectors should match the size of the Schur complement 9729 9730 Must be called after `MatFactorSetSchurIS()` 9731 9732 .seealso: `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()` 9733 @*/ 9734 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol) 9735 { 9736 PetscFunctionBegin; 9737 PetscValidType(F, 1); 9738 PetscValidType(rhs, 2); 9739 PetscValidType(sol, 3); 9740 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9741 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9742 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9743 PetscCheckSameComm(F, 1, rhs, 2); 9744 PetscCheckSameComm(F, 1, sol, 3); 9745 PetscCall(MatFactorFactorizeSchurComplement(F)); 9746 switch (F->schur_status) { 9747 case MAT_FACTOR_SCHUR_FACTORED: 9748 PetscCall(MatSolve(F->schur, rhs, sol)); 9749 break; 9750 case MAT_FACTOR_SCHUR_INVERTED: 9751 PetscCall(MatMult(F->schur, rhs, sol)); 9752 break; 9753 default: 9754 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9755 } 9756 PetscFunctionReturn(PETSC_SUCCESS); 9757 } 9758 9759 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat); 9760 #if PetscDefined(HAVE_CUDA) 9761 PETSC_EXTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Private(Mat); 9762 #endif 9763 9764 /* Schur status updated in the interface */ 9765 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F) 9766 { 9767 Mat S = F->schur; 9768 9769 PetscFunctionBegin; 9770 if (S) { 9771 PetscMPIInt size; 9772 PetscBool isdense, isdensecuda; 9773 9774 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size)); 9775 PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented"); 9776 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense)); 9777 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda)); 9778 PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name); 9779 PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0)); 9780 if (isdense) { 9781 PetscCall(MatSeqDenseInvertFactors_Private(S)); 9782 } else if (isdensecuda) { 9783 #if defined(PETSC_HAVE_CUDA) 9784 PetscCall(MatSeqDenseCUDAInvertFactors_Private(S)); 9785 #endif 9786 } 9787 PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0)); 9788 } 9789 PetscFunctionReturn(PETSC_SUCCESS); 9790 } 9791 9792 /*@ 9793 MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step 9794 9795 Logically Collective on F 9796 9797 Input Parameters: 9798 . F - the factored matrix obtained by calling `MatGetFactor()` 9799 9800 Level: advanced 9801 9802 Notes: 9803 Must be called after `MatFactorSetSchurIS()`. 9804 9805 Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it. 9806 9807 .seealso: `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()` 9808 @*/ 9809 PetscErrorCode MatFactorInvertSchurComplement(Mat F) 9810 { 9811 PetscFunctionBegin; 9812 PetscValidType(F, 1); 9813 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9814 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS); 9815 PetscCall(MatFactorFactorizeSchurComplement(F)); 9816 PetscCall(MatFactorInvertSchurComplement_Private(F)); 9817 F->schur_status = MAT_FACTOR_SCHUR_INVERTED; 9818 PetscFunctionReturn(PETSC_SUCCESS); 9819 } 9820 9821 /*@ 9822 MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step 9823 9824 Logically Collective 9825 9826 Input Parameters: 9827 . F - the factored matrix obtained by calling `MatGetFactor()` 9828 9829 Level: advanced 9830 9831 Note: 9832 Must be called after `MatFactorSetSchurIS()` 9833 9834 .seealso: `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()` 9835 @*/ 9836 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F) 9837 { 9838 MatFactorInfo info; 9839 9840 PetscFunctionBegin; 9841 PetscValidType(F, 1); 9842 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9843 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS); 9844 PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0)); 9845 if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */ 9846 PetscCall(MatCholeskyFactor(F->schur, NULL, &info)); 9847 } else { 9848 PetscCall(MatLUFactor(F->schur, NULL, NULL, &info)); 9849 } 9850 PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0)); 9851 F->schur_status = MAT_FACTOR_SCHUR_FACTORED; 9852 PetscFunctionReturn(PETSC_SUCCESS); 9853 } 9854 9855 /*@ 9856 MatPtAP - Creates the matrix product C = P^T * A * P 9857 9858 Neighbor-wise Collective 9859 9860 Input Parameters: 9861 + A - the matrix 9862 . P - the projection matrix 9863 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9864 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate 9865 if the result is a dense matrix this is irrelevant 9866 9867 Output Parameters: 9868 . C - the product matrix 9869 9870 Level: intermediate 9871 9872 Notes: 9873 C will be created and must be destroyed by the user with `MatDestroy()`. 9874 9875 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9876 9877 Developer Note: 9878 For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`. 9879 9880 .seealso: `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()` 9881 @*/ 9882 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C) 9883 { 9884 PetscFunctionBegin; 9885 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 9886 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9887 9888 if (scall == MAT_INITIAL_MATRIX) { 9889 PetscCall(MatProductCreate(A, P, NULL, C)); 9890 PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP)); 9891 PetscCall(MatProductSetAlgorithm(*C, "default")); 9892 PetscCall(MatProductSetFill(*C, fill)); 9893 9894 (*C)->product->api_user = PETSC_TRUE; 9895 PetscCall(MatProductSetFromOptions(*C)); 9896 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); 9897 PetscCall(MatProductSymbolic(*C)); 9898 } else { /* scall == MAT_REUSE_MATRIX */ 9899 PetscCall(MatProductReplaceMats(A, P, NULL, *C)); 9900 } 9901 9902 PetscCall(MatProductNumeric(*C)); 9903 (*C)->symmetric = A->symmetric; 9904 (*C)->spd = A->spd; 9905 PetscFunctionReturn(PETSC_SUCCESS); 9906 } 9907 9908 /*@ 9909 MatRARt - Creates the matrix product C = R * A * R^T 9910 9911 Neighbor-wise Collective 9912 9913 Input Parameters: 9914 + A - the matrix 9915 . R - the projection matrix 9916 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9917 - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate 9918 if the result is a dense matrix this is irrelevant 9919 9920 Output Parameters: 9921 . C - the product matrix 9922 9923 Level: intermediate 9924 9925 Notes: 9926 C will be created and must be destroyed by the user with `MatDestroy()`. 9927 9928 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9929 9930 This routine is currently only implemented for pairs of `MATAIJ` matrices and classes 9931 which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes, 9932 parallel MatRARt is implemented via explicit transpose of R, which could be very expensive. 9933 We recommend using MatPtAP(). 9934 9935 .seealso: `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()` 9936 @*/ 9937 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C) 9938 { 9939 PetscFunctionBegin; 9940 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 9941 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9942 9943 if (scall == MAT_INITIAL_MATRIX) { 9944 PetscCall(MatProductCreate(A, R, NULL, C)); 9945 PetscCall(MatProductSetType(*C, MATPRODUCT_RARt)); 9946 PetscCall(MatProductSetAlgorithm(*C, "default")); 9947 PetscCall(MatProductSetFill(*C, fill)); 9948 9949 (*C)->product->api_user = PETSC_TRUE; 9950 PetscCall(MatProductSetFromOptions(*C)); 9951 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); 9952 PetscCall(MatProductSymbolic(*C)); 9953 } else { /* scall == MAT_REUSE_MATRIX */ 9954 PetscCall(MatProductReplaceMats(A, R, NULL, *C)); 9955 } 9956 9957 PetscCall(MatProductNumeric(*C)); 9958 if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 9959 PetscFunctionReturn(PETSC_SUCCESS); 9960 } 9961 9962 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C) 9963 { 9964 PetscFunctionBegin; 9965 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9966 9967 if (scall == MAT_INITIAL_MATRIX) { 9968 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype])); 9969 PetscCall(MatProductCreate(A, B, NULL, C)); 9970 PetscCall(MatProductSetType(*C, ptype)); 9971 PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT)); 9972 PetscCall(MatProductSetFill(*C, fill)); 9973 9974 (*C)->product->api_user = PETSC_TRUE; 9975 PetscCall(MatProductSetFromOptions(*C)); 9976 PetscCall(MatProductSymbolic(*C)); 9977 } else { /* scall == MAT_REUSE_MATRIX */ 9978 Mat_Product *product = (*C)->product; 9979 PetscBool isdense; 9980 9981 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, "")); 9982 if (isdense && product && product->type != ptype) { 9983 PetscCall(MatProductClear(*C)); 9984 product = NULL; 9985 } 9986 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype])); 9987 if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */ 9988 PetscCheck(isdense, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first"); 9989 PetscCall(MatProductCreate_Private(A, B, NULL, *C)); 9990 product = (*C)->product; 9991 product->fill = fill; 9992 product->api_user = PETSC_TRUE; 9993 product->clear = PETSC_TRUE; 9994 9995 PetscCall(MatProductSetType(*C, ptype)); 9996 PetscCall(MatProductSetFromOptions(*C)); 9997 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); 9998 PetscCall(MatProductSymbolic(*C)); 9999 } else { /* user may change input matrices A or B when REUSE */ 10000 PetscCall(MatProductReplaceMats(A, B, NULL, *C)); 10001 } 10002 } 10003 PetscCall(MatProductNumeric(*C)); 10004 PetscFunctionReturn(PETSC_SUCCESS); 10005 } 10006 10007 /*@ 10008 MatMatMult - Performs matrix-matrix multiplication C=A*B. 10009 10010 Neighbor-wise Collective 10011 10012 Input Parameters: 10013 + A - the left matrix 10014 . B - the right matrix 10015 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10016 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate 10017 if the result is a dense matrix this is irrelevant 10018 10019 Output Parameters: 10020 . C - the product matrix 10021 10022 Notes: 10023 Unless scall is `MAT_REUSE_MATRIX` C will be created. 10024 10025 `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 10026 call to this function with `MAT_INITIAL_MATRIX`. 10027 10028 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed. 10029 10030 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`, 10031 rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse. 10032 10033 Example of Usage: 10034 .vb 10035 MatProductCreate(A,B,NULL,&C); 10036 MatProductSetType(C,MATPRODUCT_AB); 10037 MatProductSymbolic(C); 10038 MatProductNumeric(C); // compute C=A * B 10039 MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1 10040 MatProductNumeric(C); 10041 MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1 10042 MatProductNumeric(C); 10043 .ve 10044 10045 Level: intermediate 10046 10047 .seealso: `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()` 10048 @*/ 10049 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10050 { 10051 PetscFunctionBegin; 10052 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C)); 10053 PetscFunctionReturn(PETSC_SUCCESS); 10054 } 10055 10056 /*@ 10057 MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T. 10058 10059 Neighbor-wise Collective 10060 10061 Input Parameters: 10062 + A - the left matrix 10063 . B - the right matrix 10064 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10065 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 10066 10067 Output Parameters: 10068 . C - the product matrix 10069 10070 Level: intermediate 10071 10072 Notes: 10073 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10074 10075 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call 10076 10077 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10078 actually needed. 10079 10080 This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class, 10081 and for pairs of `MATMPIDENSE` matrices. 10082 10083 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt` 10084 10085 Options Database Keys: 10086 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the 10087 first redundantly copies the transposed B matrix on each process and requiers O(log P) communication complexity; 10088 the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity. 10089 10090 .seealso: `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductCreate()`, `MatProductAlgorithm`, `MatProductType`, `MATPRODUCT_ABt` 10091 @*/ 10092 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10093 { 10094 PetscFunctionBegin; 10095 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C)); 10096 if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10097 PetscFunctionReturn(PETSC_SUCCESS); 10098 } 10099 10100 /*@ 10101 MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B. 10102 10103 Neighbor-wise Collective 10104 10105 Input Parameters: 10106 + A - the left matrix 10107 . B - the right matrix 10108 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10109 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known 10110 10111 Output Parameters: 10112 . C - the product matrix 10113 10114 Level: intermediate 10115 10116 Notes: 10117 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10118 10119 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call. 10120 10121 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB` 10122 10123 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10124 actually needed. 10125 10126 This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes 10127 which inherit from `MATSEQAIJ`. C will be of the same type as the input matrices. 10128 10129 .seealso: `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()` 10130 @*/ 10131 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10132 { 10133 PetscFunctionBegin; 10134 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C)); 10135 PetscFunctionReturn(PETSC_SUCCESS); 10136 } 10137 10138 /*@ 10139 MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C. 10140 10141 Neighbor-wise Collective 10142 10143 Input Parameters: 10144 + A - the left matrix 10145 . B - the middle matrix 10146 . C - the right matrix 10147 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10148 - 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 10149 if the result is a dense matrix this is irrelevant 10150 10151 Output Parameters: 10152 . D - the product matrix 10153 10154 Level: intermediate 10155 10156 Notes: 10157 Unless scall is `MAT_REUSE_MATRIX` D will be created. 10158 10159 `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call 10160 10161 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC` 10162 10163 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10164 actually needed. 10165 10166 If you have many matrices with the same non-zero structure to multiply, you 10167 should use `MAT_REUSE_MATRIX` in all calls but the first 10168 10169 .seealso: `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()` 10170 @*/ 10171 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D) 10172 { 10173 PetscFunctionBegin; 10174 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6); 10175 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10176 10177 if (scall == MAT_INITIAL_MATRIX) { 10178 PetscCall(MatProductCreate(A, B, C, D)); 10179 PetscCall(MatProductSetType(*D, MATPRODUCT_ABC)); 10180 PetscCall(MatProductSetAlgorithm(*D, "default")); 10181 PetscCall(MatProductSetFill(*D, fill)); 10182 10183 (*D)->product->api_user = PETSC_TRUE; 10184 PetscCall(MatProductSetFromOptions(*D)); 10185 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, 10186 ((PetscObject)C)->type_name); 10187 PetscCall(MatProductSymbolic(*D)); 10188 } else { /* user may change input matrices when REUSE */ 10189 PetscCall(MatProductReplaceMats(A, B, C, *D)); 10190 } 10191 PetscCall(MatProductNumeric(*D)); 10192 PetscFunctionReturn(PETSC_SUCCESS); 10193 } 10194 10195 /*@ 10196 MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators. 10197 10198 Collective 10199 10200 Input Parameters: 10201 + mat - the matrix 10202 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices) 10203 . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used) 10204 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10205 10206 Output Parameter: 10207 . matredundant - redundant matrix 10208 10209 Level: advanced 10210 10211 Notes: 10212 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 10213 original matrix has not changed from that last call to MatCreateRedundantMatrix(). 10214 10215 This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before 10216 calling it. 10217 10218 `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be. 10219 10220 .seealso: `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubComm` 10221 @*/ 10222 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant) 10223 { 10224 MPI_Comm comm; 10225 PetscMPIInt size; 10226 PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs; 10227 Mat_Redundant *redund = NULL; 10228 PetscSubcomm psubcomm = NULL; 10229 MPI_Comm subcomm_in = subcomm; 10230 Mat *matseq; 10231 IS isrow, iscol; 10232 PetscBool newsubcomm = PETSC_FALSE; 10233 10234 PetscFunctionBegin; 10235 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10236 if (nsubcomm && reuse == MAT_REUSE_MATRIX) { 10237 PetscValidPointer(*matredundant, 5); 10238 PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5); 10239 } 10240 10241 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10242 if (size == 1 || nsubcomm == 1) { 10243 if (reuse == MAT_INITIAL_MATRIX) { 10244 PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant)); 10245 } else { 10246 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"); 10247 PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN)); 10248 } 10249 PetscFunctionReturn(PETSC_SUCCESS); 10250 } 10251 10252 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10253 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10254 MatCheckPreallocated(mat, 1); 10255 10256 PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0)); 10257 if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */ 10258 /* create psubcomm, then get subcomm */ 10259 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10260 PetscCallMPI(MPI_Comm_size(comm, &size)); 10261 PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size); 10262 10263 PetscCall(PetscSubcommCreate(comm, &psubcomm)); 10264 PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm)); 10265 PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS)); 10266 PetscCall(PetscSubcommSetFromOptions(psubcomm)); 10267 PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL)); 10268 newsubcomm = PETSC_TRUE; 10269 PetscCall(PetscSubcommDestroy(&psubcomm)); 10270 } 10271 10272 /* get isrow, iscol and a local sequential matrix matseq[0] */ 10273 if (reuse == MAT_INITIAL_MATRIX) { 10274 mloc_sub = PETSC_DECIDE; 10275 nloc_sub = PETSC_DECIDE; 10276 if (bs < 1) { 10277 PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M)); 10278 PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N)); 10279 } else { 10280 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M)); 10281 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N)); 10282 } 10283 PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm)); 10284 rstart = rend - mloc_sub; 10285 PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow)); 10286 PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol)); 10287 } else { /* reuse == MAT_REUSE_MATRIX */ 10288 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"); 10289 /* retrieve subcomm */ 10290 PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm)); 10291 redund = (*matredundant)->redundant; 10292 isrow = redund->isrow; 10293 iscol = redund->iscol; 10294 matseq = redund->matseq; 10295 } 10296 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq)); 10297 10298 /* get matredundant over subcomm */ 10299 if (reuse == MAT_INITIAL_MATRIX) { 10300 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant)); 10301 10302 /* create a supporting struct and attach it to C for reuse */ 10303 PetscCall(PetscNew(&redund)); 10304 (*matredundant)->redundant = redund; 10305 redund->isrow = isrow; 10306 redund->iscol = iscol; 10307 redund->matseq = matseq; 10308 if (newsubcomm) { 10309 redund->subcomm = subcomm; 10310 } else { 10311 redund->subcomm = MPI_COMM_NULL; 10312 } 10313 } else { 10314 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant)); 10315 } 10316 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 10317 if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) { 10318 PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE)); 10319 PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE)); 10320 } 10321 #endif 10322 PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0)); 10323 PetscFunctionReturn(PETSC_SUCCESS); 10324 } 10325 10326 /*@C 10327 MatGetMultiProcBlock - Create multiple 'parallel submatrices' from 10328 a given `Mat`. Each submatrix can span multiple procs. 10329 10330 Collective 10331 10332 Input Parameters: 10333 + mat - the matrix 10334 . subcomm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))` 10335 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10336 10337 Output Parameter: 10338 . subMat - parallel sub-matrices each spanning a given `subcomm` 10339 10340 Level: advanced 10341 10342 Notes: 10343 The submatrix partition across processors is dictated by `subComm` a 10344 communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm` 10345 is not restricted to be grouped with consecutive original ranks. 10346 10347 Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices 10348 map directly to the layout of the original matrix [wrt the local 10349 row,col partitioning]. So the original 'DiagonalMat' naturally maps 10350 into the 'DiagonalMat' of the `subMat`, hence it is used directly from 10351 the `subMat`. However the offDiagMat looses some columns - and this is 10352 reconstructed with `MatSetValues()` 10353 10354 This is used by `PCBJACOBI` when a single block spans multiple MPI ranks 10355 10356 .seealso: `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI` 10357 @*/ 10358 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) 10359 { 10360 PetscMPIInt commsize, subCommSize; 10361 10362 PetscFunctionBegin; 10363 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize)); 10364 PetscCallMPI(MPI_Comm_size(subComm, &subCommSize)); 10365 PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize); 10366 10367 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"); 10368 PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10369 PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat); 10370 PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10371 PetscFunctionReturn(PETSC_SUCCESS); 10372 } 10373 10374 /*@ 10375 MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering 10376 10377 Not Collective 10378 10379 Input Parameters: 10380 + mat - matrix to extract local submatrix from 10381 . isrow - local row indices for submatrix 10382 - iscol - local column indices for submatrix 10383 10384 Output Parameter: 10385 . submat - the submatrix 10386 10387 Level: intermediate 10388 10389 Notes: 10390 `submat` should be disposed of with `MatRestoreLocalSubMatrix()`. 10391 10392 Depending on the format of `mat`, the returned submat may not implement `MatMult()`. Its communicator may be 10393 the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of `mat`'s. 10394 10395 `submat` always implements `MatSetValuesLocal()`. If `isrow` and `iscol` have the same block size, then 10396 `MatSetValuesBlockedLocal()` will also be implemented. 10397 10398 `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`. 10399 Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided. 10400 10401 .seealso: `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()` 10402 @*/ 10403 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10404 { 10405 PetscFunctionBegin; 10406 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10407 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10408 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10409 PetscCheckSameComm(isrow, 2, iscol, 3); 10410 PetscValidPointer(submat, 4); 10411 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call"); 10412 10413 if (mat->ops->getlocalsubmatrix) { 10414 PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat); 10415 } else { 10416 PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat)); 10417 } 10418 PetscFunctionReturn(PETSC_SUCCESS); 10419 } 10420 10421 /*@ 10422 MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()` 10423 10424 Not Collective 10425 10426 Input Parameters: 10427 + mat - matrix to extract local submatrix from 10428 . isrow - local row indices for submatrix 10429 . iscol - local column indices for submatrix 10430 - submat - the submatrix 10431 10432 Level: intermediate 10433 10434 .seealso: `Mat`, `MatGetLocalSubMatrix()` 10435 @*/ 10436 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10437 { 10438 PetscFunctionBegin; 10439 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10440 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10441 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10442 PetscCheckSameComm(isrow, 2, iscol, 3); 10443 PetscValidPointer(submat, 4); 10444 if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4); 10445 10446 if (mat->ops->restorelocalsubmatrix) { 10447 PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat); 10448 } else { 10449 PetscCall(MatDestroy(submat)); 10450 } 10451 *submat = NULL; 10452 PetscFunctionReturn(PETSC_SUCCESS); 10453 } 10454 10455 /*@ 10456 MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix 10457 10458 Collective 10459 10460 Input Parameter: 10461 . mat - the matrix 10462 10463 Output Parameter: 10464 . is - if any rows have zero diagonals this contains the list of them 10465 10466 Level: developer 10467 10468 .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10469 @*/ 10470 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is) 10471 { 10472 PetscFunctionBegin; 10473 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10474 PetscValidType(mat, 1); 10475 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10476 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10477 10478 if (!mat->ops->findzerodiagonals) { 10479 Vec diag; 10480 const PetscScalar *a; 10481 PetscInt *rows; 10482 PetscInt rStart, rEnd, r, nrow = 0; 10483 10484 PetscCall(MatCreateVecs(mat, &diag, NULL)); 10485 PetscCall(MatGetDiagonal(mat, diag)); 10486 PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd)); 10487 PetscCall(VecGetArrayRead(diag, &a)); 10488 for (r = 0; r < rEnd - rStart; ++r) 10489 if (a[r] == 0.0) ++nrow; 10490 PetscCall(PetscMalloc1(nrow, &rows)); 10491 nrow = 0; 10492 for (r = 0; r < rEnd - rStart; ++r) 10493 if (a[r] == 0.0) rows[nrow++] = r + rStart; 10494 PetscCall(VecRestoreArrayRead(diag, &a)); 10495 PetscCall(VecDestroy(&diag)); 10496 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is)); 10497 } else { 10498 PetscUseTypeMethod(mat, findzerodiagonals, is); 10499 } 10500 PetscFunctionReturn(PETSC_SUCCESS); 10501 } 10502 10503 /*@ 10504 MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size) 10505 10506 Collective 10507 10508 Input Parameter: 10509 . mat - the matrix 10510 10511 Output Parameter: 10512 . is - contains the list of rows with off block diagonal entries 10513 10514 Level: developer 10515 10516 .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10517 @*/ 10518 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is) 10519 { 10520 PetscFunctionBegin; 10521 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10522 PetscValidType(mat, 1); 10523 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10524 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10525 10526 PetscUseTypeMethod(mat, findoffblockdiagonalentries, is); 10527 PetscFunctionReturn(PETSC_SUCCESS); 10528 } 10529 10530 /*@C 10531 MatInvertBlockDiagonal - Inverts the block diagonal entries. 10532 10533 Collective; No Fortran Support 10534 10535 Input Parameters: 10536 . mat - the matrix 10537 10538 Output Parameters: 10539 . values - the block inverses in column major order (FORTRAN-like) 10540 10541 Level: advanced 10542 10543 Notes: 10544 The size of the blocks is determined by the block size of the matrix. 10545 10546 The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case 10547 10548 The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size 10549 10550 .seealso: `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()` 10551 @*/ 10552 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values) 10553 { 10554 PetscFunctionBegin; 10555 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10556 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10557 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10558 PetscUseTypeMethod(mat, invertblockdiagonal, values); 10559 PetscFunctionReturn(PETSC_SUCCESS); 10560 } 10561 10562 /*@C 10563 MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries. 10564 10565 Collective; No Fortran Support 10566 10567 Input Parameters: 10568 + mat - the matrix 10569 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()` 10570 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()` 10571 10572 Output Parameters: 10573 . values - the block inverses in column major order (FORTRAN-like) 10574 10575 Level: advanced 10576 10577 Notes: 10578 Use `MatInvertBlockDiagonal()` if all blocks have the same size 10579 10580 The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case 10581 10582 .seealso: `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()` 10583 @*/ 10584 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values) 10585 { 10586 PetscFunctionBegin; 10587 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10588 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10589 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10590 PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values); 10591 PetscFunctionReturn(PETSC_SUCCESS); 10592 } 10593 10594 /*@ 10595 MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A 10596 10597 Collective on Mat 10598 10599 Input Parameters: 10600 + A - the matrix 10601 - C - matrix with inverted block diagonal of `A`. This matrix should be created and may have its type set. 10602 10603 Level: advanced 10604 10605 Note: 10606 The blocksize of the matrix is used to determine the blocks on the diagonal of `C` 10607 10608 .seealso: `Mat`, `MatInvertBlockDiagonal()` 10609 @*/ 10610 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C) 10611 { 10612 const PetscScalar *vals; 10613 PetscInt *dnnz; 10614 PetscInt m, rstart, rend, bs, i, j; 10615 10616 PetscFunctionBegin; 10617 PetscCall(MatInvertBlockDiagonal(A, &vals)); 10618 PetscCall(MatGetBlockSize(A, &bs)); 10619 PetscCall(MatGetLocalSize(A, &m, NULL)); 10620 PetscCall(MatSetLayouts(C, A->rmap, A->cmap)); 10621 PetscCall(PetscMalloc1(m / bs, &dnnz)); 10622 for (j = 0; j < m / bs; j++) dnnz[j] = 1; 10623 PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL)); 10624 PetscCall(PetscFree(dnnz)); 10625 PetscCall(MatGetOwnershipRange(C, &rstart, &rend)); 10626 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE)); 10627 for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES)); 10628 PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 10629 PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 10630 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE)); 10631 PetscFunctionReturn(PETSC_SUCCESS); 10632 } 10633 10634 /*@C 10635 MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created 10636 via `MatTransposeColoringCreate()`. 10637 10638 Collective on c 10639 10640 Input Parameter: 10641 . c - coloring context 10642 10643 Level: intermediate 10644 10645 .seealso: `Mat`, `MatTransposeColoringCreate()` 10646 @*/ 10647 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c) 10648 { 10649 MatTransposeColoring matcolor = *c; 10650 10651 PetscFunctionBegin; 10652 if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS); 10653 if (--((PetscObject)matcolor)->refct > 0) { 10654 matcolor = NULL; 10655 PetscFunctionReturn(PETSC_SUCCESS); 10656 } 10657 10658 PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow)); 10659 PetscCall(PetscFree(matcolor->rows)); 10660 PetscCall(PetscFree(matcolor->den2sp)); 10661 PetscCall(PetscFree(matcolor->colorforcol)); 10662 PetscCall(PetscFree(matcolor->columns)); 10663 if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart)); 10664 PetscCall(PetscHeaderDestroy(c)); 10665 PetscFunctionReturn(PETSC_SUCCESS); 10666 } 10667 10668 /*@C 10669 MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which 10670 a `MatTransposeColoring` context has been created, computes a dense B^T by applying 10671 `MatTransposeColoring` to sparse B. 10672 10673 Collective on coloring 10674 10675 Input Parameters: 10676 + B - sparse matrix B 10677 . Btdense - symbolic dense matrix B^T 10678 - coloring - coloring context created with `MatTransposeColoringCreate()` 10679 10680 Output Parameter: 10681 . Btdense - dense matrix B^T 10682 10683 Level: developer 10684 10685 Note: 10686 These are used internally for some implementations of `MatRARt()` 10687 10688 .seealso: `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()` 10689 @*/ 10690 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense) 10691 { 10692 PetscFunctionBegin; 10693 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 10694 PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3); 10695 PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10696 10697 PetscCall((B->ops->transcoloringapplysptoden)(coloring, B, Btdense)); 10698 PetscFunctionReturn(PETSC_SUCCESS); 10699 } 10700 10701 /*@C 10702 MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which 10703 a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense 10704 in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix 10705 Csp from Cden. 10706 10707 Collective 10708 10709 Input Parameters: 10710 + coloring - coloring context created with `MatTransposeColoringCreate()` 10711 - Cden - matrix product of a sparse matrix and a dense matrix Btdense 10712 10713 Output Parameter: 10714 . Csp - sparse matrix 10715 10716 Level: developer 10717 10718 Note: 10719 These are used internally for some implementations of `MatRARt()` 10720 10721 .seealso: `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()` 10722 @*/ 10723 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp) 10724 { 10725 PetscFunctionBegin; 10726 PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10727 PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2); 10728 PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3); 10729 10730 PetscCall((Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp)); 10731 PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY)); 10732 PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY)); 10733 PetscFunctionReturn(PETSC_SUCCESS); 10734 } 10735 10736 /*@C 10737 MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T. 10738 10739 Collective 10740 10741 Input Parameters: 10742 + mat - the matrix product C 10743 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()` 10744 10745 Output Parameter: 10746 . color - the new coloring context 10747 10748 Level: intermediate 10749 10750 .seealso: `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`, 10751 `MatTransColoringApplyDenToSp()` 10752 @*/ 10753 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color) 10754 { 10755 MatTransposeColoring c; 10756 MPI_Comm comm; 10757 10758 PetscFunctionBegin; 10759 PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10760 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10761 PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL)); 10762 10763 c->ctype = iscoloring->ctype; 10764 PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c); 10765 10766 *color = c; 10767 PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10768 PetscFunctionReturn(PETSC_SUCCESS); 10769 } 10770 10771 /*@ 10772 MatGetNonzeroState - Returns a 64 bit integer representing the current state of nonzeros in the matrix. If the 10773 matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the 10774 same, otherwise it will be larger 10775 10776 Not Collective 10777 10778 Input Parameter: 10779 . A - the matrix 10780 10781 Output Parameter: 10782 . state - the current state 10783 10784 Level: intermediate 10785 10786 Notes: 10787 You can only compare states from two different calls to the SAME matrix, you cannot compare calls between 10788 different matrices 10789 10790 Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix 10791 10792 Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers. 10793 10794 .seealso: `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()` 10795 @*/ 10796 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state) 10797 { 10798 PetscFunctionBegin; 10799 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10800 *state = mat->nonzerostate; 10801 PetscFunctionReturn(PETSC_SUCCESS); 10802 } 10803 10804 /*@ 10805 MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential 10806 matrices from each processor 10807 10808 Collective 10809 10810 Input Parameters: 10811 + comm - the communicators the parallel matrix will live on 10812 . seqmat - the input sequential matrices 10813 . n - number of local columns (or `PETSC_DECIDE`) 10814 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10815 10816 Output Parameter: 10817 . mpimat - the parallel matrix generated 10818 10819 Level: developer 10820 10821 Note: 10822 The number of columns of the matrix in EACH processor MUST be the same. 10823 10824 .seealso: `Mat` 10825 @*/ 10826 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat) 10827 { 10828 PetscMPIInt size; 10829 10830 PetscFunctionBegin; 10831 PetscCallMPI(MPI_Comm_size(comm, &size)); 10832 if (size == 1) { 10833 if (reuse == MAT_INITIAL_MATRIX) { 10834 PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat)); 10835 } else { 10836 PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN)); 10837 } 10838 PetscFunctionReturn(PETSC_SUCCESS); 10839 } 10840 10841 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"); 10842 10843 PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0)); 10844 PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat)); 10845 PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0)); 10846 PetscFunctionReturn(PETSC_SUCCESS); 10847 } 10848 10849 /*@ 10850 MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent ranks' ownership ranges. 10851 10852 Collective 10853 10854 Input Parameters: 10855 + A - the matrix to create subdomains from 10856 - N - requested number of subdomains 10857 10858 Output Parameters: 10859 + n - number of subdomains resulting on this rank 10860 - iss - `IS` list with indices of subdomains on this rank 10861 10862 Level: advanced 10863 10864 Note: 10865 The number of subdomains must be smaller than the communicator size 10866 10867 .seealso: `Mat`, `IS` 10868 @*/ 10869 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[]) 10870 { 10871 MPI_Comm comm, subcomm; 10872 PetscMPIInt size, rank, color; 10873 PetscInt rstart, rend, k; 10874 10875 PetscFunctionBegin; 10876 PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 10877 PetscCallMPI(MPI_Comm_size(comm, &size)); 10878 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 10879 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); 10880 *n = 1; 10881 k = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */ 10882 color = rank / k; 10883 PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm)); 10884 PetscCall(PetscMalloc1(1, iss)); 10885 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 10886 PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0])); 10887 PetscCallMPI(MPI_Comm_free(&subcomm)); 10888 PetscFunctionReturn(PETSC_SUCCESS); 10889 } 10890 10891 /*@ 10892 MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection. 10893 10894 If the interpolation and restriction operators are the same, uses `MatPtAP()`. 10895 If they are not the same, uses `MatMatMatMult()`. 10896 10897 Once the coarse grid problem is constructed, correct for interpolation operators 10898 that are not of full rank, which can legitimately happen in the case of non-nested 10899 geometric multigrid. 10900 10901 Input Parameters: 10902 + restrct - restriction operator 10903 . dA - fine grid matrix 10904 . interpolate - interpolation operator 10905 . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10906 - fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate 10907 10908 Output Parameters: 10909 . A - the Galerkin coarse matrix 10910 10911 Options Database Key: 10912 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used 10913 10914 Level: developer 10915 10916 .seealso: `Mat`, `MatPtAP()`, `MatMatMatMult()` 10917 @*/ 10918 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A) 10919 { 10920 IS zerorows; 10921 Vec diag; 10922 10923 PetscFunctionBegin; 10924 PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10925 /* Construct the coarse grid matrix */ 10926 if (interpolate == restrct) { 10927 PetscCall(MatPtAP(dA, interpolate, reuse, fill, A)); 10928 } else { 10929 PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A)); 10930 } 10931 10932 /* If the interpolation matrix is not of full rank, A will have zero rows. 10933 This can legitimately happen in the case of non-nested geometric multigrid. 10934 In that event, we set the rows of the matrix to the rows of the identity, 10935 ignoring the equations (as the RHS will also be zero). */ 10936 10937 PetscCall(MatFindZeroRows(*A, &zerorows)); 10938 10939 if (zerorows != NULL) { /* if there are any zero rows */ 10940 PetscCall(MatCreateVecs(*A, &diag, NULL)); 10941 PetscCall(MatGetDiagonal(*A, diag)); 10942 PetscCall(VecISSet(diag, zerorows, 1.0)); 10943 PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES)); 10944 PetscCall(VecDestroy(&diag)); 10945 PetscCall(ISDestroy(&zerorows)); 10946 } 10947 PetscFunctionReturn(PETSC_SUCCESS); 10948 } 10949 10950 /*@C 10951 MatSetOperation - Allows user to set a matrix operation for any matrix type 10952 10953 Logically Collective 10954 10955 Input Parameters: 10956 + mat - the matrix 10957 . op - the name of the operation 10958 - f - the function that provides the operation 10959 10960 Level: developer 10961 10962 Usage: 10963 .vb 10964 extern PetscErrorCode usermult(Mat, Vec, Vec); 10965 10966 PetscCall(MatCreateXXX(comm, ..., &A)); 10967 PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFunction)usermult)); 10968 .ve 10969 10970 Notes: 10971 See the file `include/petscmat.h` for a complete list of matrix 10972 operations, which all have the form MATOP_<OPERATION>, where 10973 <OPERATION> is the name (in all capital letters) of the 10974 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 10975 10976 All user-provided functions (except for `MATOP_DESTROY`) should have the same calling 10977 sequence as the usual matrix interface routines, since they 10978 are intended to be accessed via the usual matrix interface 10979 routines, e.g., 10980 .vb 10981 MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec) 10982 .ve 10983 10984 In particular each function MUST return `PETSC_SUCCESS` on success and 10985 nonzero on failure. 10986 10987 This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type. 10988 10989 .seealso: `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()` 10990 @*/ 10991 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void)) 10992 { 10993 PetscFunctionBegin; 10994 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10995 if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view; 10996 (((void (**)(void))mat->ops)[op]) = f; 10997 PetscFunctionReturn(PETSC_SUCCESS); 10998 } 10999 11000 /*@C 11001 MatGetOperation - Gets a matrix operation for any matrix type. 11002 11003 Not Collective 11004 11005 Input Parameters: 11006 + mat - the matrix 11007 - op - the name of the operation 11008 11009 Output Parameter: 11010 . f - the function that provides the operation 11011 11012 Level: developer 11013 11014 Usage: 11015 $ PetscErrorCode (*usermult)(Mat,Vec,Vec); 11016 $ MatGetOperation(A,MATOP_MULT,(void(**)(void))&usermult); 11017 11018 Notes: 11019 See the file include/petscmat.h for a complete list of matrix 11020 operations, which all have the form MATOP_<OPERATION>, where 11021 <OPERATION> is the name (in all capital letters) of the 11022 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11023 11024 This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type. 11025 11026 .seealso: `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()` 11027 @*/ 11028 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void)) 11029 { 11030 PetscFunctionBegin; 11031 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11032 *f = (((void (**)(void))mat->ops)[op]); 11033 PetscFunctionReturn(PETSC_SUCCESS); 11034 } 11035 11036 /*@ 11037 MatHasOperation - Determines whether the given matrix supports the particular operation. 11038 11039 Not Collective 11040 11041 Input Parameters: 11042 + mat - the matrix 11043 - op - the operation, for example, `MATOP_GET_DIAGONAL` 11044 11045 Output Parameter: 11046 . has - either `PETSC_TRUE` or `PETSC_FALSE` 11047 11048 Level: advanced 11049 11050 Note: 11051 See `MatSetOperation()` for additional discussion on naming convention and usage of `op`. 11052 11053 .seealso: `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()` 11054 @*/ 11055 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has) 11056 { 11057 PetscFunctionBegin; 11058 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11059 PetscValidBoolPointer(has, 3); 11060 if (mat->ops->hasoperation) { 11061 PetscUseTypeMethod(mat, hasoperation, op, has); 11062 } else { 11063 if (((void **)mat->ops)[op]) *has = PETSC_TRUE; 11064 else { 11065 *has = PETSC_FALSE; 11066 if (op == MATOP_CREATE_SUBMATRIX) { 11067 PetscMPIInt size; 11068 11069 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 11070 if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has)); 11071 } 11072 } 11073 } 11074 PetscFunctionReturn(PETSC_SUCCESS); 11075 } 11076 11077 /*@ 11078 MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent 11079 11080 Collective 11081 11082 Input Parameters: 11083 . mat - the matrix 11084 11085 Output Parameter: 11086 . cong - either `PETSC_TRUE` or `PETSC_FALSE` 11087 11088 Level: beginner 11089 11090 .seealso: `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout` 11091 @*/ 11092 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong) 11093 { 11094 PetscFunctionBegin; 11095 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11096 PetscValidType(mat, 1); 11097 PetscValidBoolPointer(cong, 2); 11098 if (!mat->rmap || !mat->cmap) { 11099 *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE; 11100 PetscFunctionReturn(PETSC_SUCCESS); 11101 } 11102 if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */ 11103 PetscCall(PetscLayoutSetUp(mat->rmap)); 11104 PetscCall(PetscLayoutSetUp(mat->cmap)); 11105 PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong)); 11106 if (*cong) mat->congruentlayouts = 1; 11107 else mat->congruentlayouts = 0; 11108 } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE; 11109 PetscFunctionReturn(PETSC_SUCCESS); 11110 } 11111 11112 PetscErrorCode MatSetInf(Mat A) 11113 { 11114 PetscFunctionBegin; 11115 PetscUseTypeMethod(A, setinf); 11116 PetscFunctionReturn(PETSC_SUCCESS); 11117 } 11118 11119 /*@C 11120 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 11121 and possibly removes small values from the graph structure. 11122 11123 Collective 11124 11125 Input Parameters: 11126 + A - the matrix 11127 . sym - `PETSC_TRUE` indicates that the graph should be symmetrized 11128 . scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry 11129 - filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value 11130 11131 Output Parameter: 11132 . graph - the resulting graph 11133 11134 Level: advanced 11135 11136 .seealso: `Mat`, `MatCreate()`, `PCGAMG` 11137 @*/ 11138 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph) 11139 { 11140 PetscFunctionBegin; 11141 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11142 PetscValidType(A, 1); 11143 PetscValidLogicalCollectiveBool(A, scale, 3); 11144 PetscValidPointer(graph, 5); 11145 PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph); 11146 PetscFunctionReturn(PETSC_SUCCESS); 11147 } 11148 11149 /*@ 11150 MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place, 11151 meaning the same memory is used for the matrix, and no new memory is allocated. 11152 11153 Collective on mat 11154 11155 Input Parameter: 11156 . A - the matrix 11157 11158 Output Parameter: 11159 . A - the matrix 11160 11161 Level: intermediate 11162 11163 .seealso: `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatChop()` 11164 @*/ 11165 PetscErrorCode MatEliminateZeros(Mat A) 11166 { 11167 PetscFunctionBegin; 11168 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11169 PetscUseTypeMethod(A, eliminatezeros); 11170 PetscFunctionReturn(PETSC_SUCCESS); 11171 } 11172